summaryrefslogtreecommitdiff
authorWeiguang Ruan <Weiguang.ruan@amlogic.com>2016-01-27 06:52:08 (GMT)
committer Weiguang Ruan <Weiguang.ruan@amlogic.com>2016-01-27 06:52:08 (GMT)
commit3935905e634318e3b3affbd569aea6dedb433eb1 (patch)
tree7eca3bbda26602c3688e761c152573c3c2457f49
parentaf8b243c66ebd4e40bed51b4114d6c7dcb45293f (diff)
downloadbtusb-3935905e634318e3b3affbd569aea6dedb433eb1.zip
btusb-3935905e634318e3b3affbd569aea6dedb433eb1.tar.gz
btusb-3935905e634318e3b3affbd569aea6dedb433eb1.tar.bz2
PD #xxxx bt: add support for AP6269
Change-Id: I1a0495cd4b4aab016864780fbe60ae6ebb75f0b3
Diffstat
-rwxr-xr-xbtusb_1_6_29_1/.svn/all-wcprops23
-rwxr-xr-xbtusb_1_6_29_1/.svn/entries136
-rwxr-xr-xbtusb_1_6_29_1/.svn/prop-base/cpmod.svn-base5
-rwxr-xr-xbtusb_1_6_29_1/.svn/text-base/Makefile.svn-base87
-rwxr-xr-xbtusb_1_6_29_1/.svn/text-base/Release_btusb.txt.svn-base26
-rwxr-xr-xbtusb_1_6_29_1/.svn/text-base/cpmod.svn-base1
-rwxr-xr-xbtusb_1_6_29_1/Makefile86
-rwxr-xr-xbtusb_1_6_29_1/Release_btusb.txt26
-rwxr-xr-xbtusb_1_6_29_1/cpmod1
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/all-wcprops89
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/entries504
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/bt_target.h.svn-base0
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/bt_types.h.svn-base78
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/btusb.h.svn-base367
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/btusb_lite.h.svn-base198
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/btusb_lite_av.h.svn-base135
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/btusb_lite_avdt.h.svn-base148
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/btusb_lite_hci.h.svn-base71
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/btusb_lite_l2c.h.svn-base105
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/btusbext.h.svn-base169
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/data_types.h.svn-base79
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/gki.h.svn-base190
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/gki_int.h.svn-base197
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/hcidefs.h.svn-base1819
-rwxr-xr-xbtusb_1_6_29_1/inc/.svn/text-base/target.h.svn-base121
-rwxr-xr-xbtusb_1_6_29_1/inc/bt_target.h0
-rwxr-xr-xbtusb_1_6_29_1/inc/bt_types.h78
-rwxr-xr-xbtusb_1_6_29_1/inc/btusb.h367
-rwxr-xr-xbtusb_1_6_29_1/inc/btusb_lite.h198
-rwxr-xr-xbtusb_1_6_29_1/inc/btusb_lite_av.h135
-rwxr-xr-xbtusb_1_6_29_1/inc/btusb_lite_avdt.h148
-rwxr-xr-xbtusb_1_6_29_1/inc/btusb_lite_hci.h71
-rwxr-xr-xbtusb_1_6_29_1/inc/btusb_lite_l2c.h105
-rwxr-xr-xbtusb_1_6_29_1/inc/btusbext.h169
-rwxr-xr-xbtusb_1_6_29_1/inc/data_types.h79
-rwxr-xr-xbtusb_1_6_29_1/inc/gki.h190
-rwxr-xr-xbtusb_1_6_29_1/inc/gki_int.h197
-rwxr-xr-xbtusb_1_6_29_1/inc/hcidefs.h1819
-rwxr-xr-xbtusb_1_6_29_1/inc/target.h121
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/all-wcprops53
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/entries303
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb.c.svn-base1625
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb_dev.c.svn-base2630
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb_isoc.c.svn-base311
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb_lite.c.svn-base1794
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb_lite_av.c.svn-base1322
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb_lite_avdt.c.svn-base426
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb_lite_hci.c.svn-base440
-rwxr-xr-xbtusb_1_6_29_1/src/.svn/text-base/btusb_lite_l2c.c.svn-base278
-rwxr-xr-xbtusb_1_6_29_1/src/btusb.c1625
-rwxr-xr-xbtusb_1_6_29_1/src/btusb_dev.c2630
-rwxr-xr-xbtusb_1_6_29_1/src/btusb_isoc.c311
-rwxr-xr-xbtusb_1_6_29_1/src/btusb_lite.c1794
-rwxr-xr-xbtusb_1_6_29_1/src/btusb_lite_av.c1322
-rwxr-xr-xbtusb_1_6_29_1/src/btusb_lite_avdt.c426
-rwxr-xr-xbtusb_1_6_29_1/src/btusb_lite_hci.c440
-rwxr-xr-xbtusb_1_6_29_1/src/btusb_lite_l2c.c278
-rwxr-xr-xbtusb_1_6_29_1/src/gki/.svn/all-wcprops17
-rwxr-xr-xbtusb_1_6_29_1/src/gki/.svn/entries96
-rwxr-xr-xbtusb_1_6_29_1/src/gki/.svn/text-base/gki_buffer.c.svn-base1280
-rwxr-xr-xbtusb_1_6_29_1/src/gki/.svn/text-base/gki_klinux.c.svn-base271
-rwxr-xr-xbtusb_1_6_29_1/src/gki/gki_buffer.c1282
-rwxr-xr-xbtusb_1_6_29_1/src/gki/gki_klinux.c271
63 files changed, 29563 insertions, 0 deletions
diff --git a/btusb_1_6_29_1/.svn/all-wcprops b/btusb_1_6_29_1/.svn/all-wcprops
new file mode 100755
index 0000000..cccf6b0
--- a/dev/null
+++ b/btusb_1_6_29_1/.svn/all-wcprops
@@ -0,0 +1,23 @@
+K 25
+svn:wc:ra_dav:version-url
+V 68
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1
+END
+Makefile
+K 25
+svn:wc:ra_dav:version-url
+V 77
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/Makefile
+END
+Release_btusb.txt
+K 25
+svn:wc:ra_dav:version-url
+V 86
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/Release_btusb.txt
+END
+cpmod
+K 25
+svn:wc:ra_dav:version-url
+V 74
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/cpmod
+END
diff --git a/btusb_1_6_29_1/.svn/entries b/btusb_1_6_29_1/.svn/entries
new file mode 100755
index 0000000..f497902
--- a/dev/null
+++ b/btusb_1_6_29_1/.svn/entries
@@ -0,0 +1,136 @@
+10
+
+dir
+941
+http://10.10.29.8/svn/SiP/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1
+http://10.10.29.8/svn/SiP
+
+
+
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+e48500f2-7125-4e9d-852c-c0ee60673d08
+
+inc
+dir
+
+Makefile
+file
+
+
+
+
+2014-08-14T08:53:29.628694Z
+613a7ac6f3c22a8df0d808dc9ea41cab
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2281
+
+Release_btusb.txt
+file
+
+
+
+
+2014-08-14T08:53:29.628694Z
+5ae7fa642bcfd9d734a5a2d0e73f29ef
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1168
+
+cpmod
+file
+
+
+
+
+2014-08-14T08:53:29.684694Z
+f5fbc1e2f70baab680ccd2922670616a
+2014-08-14T09:21:52.961444Z
+725
+luke
+has-props
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+69
+
+src
+dir
+
diff --git a/btusb_1_6_29_1/.svn/prop-base/cpmod.svn-base b/btusb_1_6_29_1/.svn/prop-base/cpmod.svn-base
new file mode 100755
index 0000000..869ac71
--- a/dev/null
+++ b/btusb_1_6_29_1/.svn/prop-base/cpmod.svn-base
@@ -0,0 +1,5 @@
+K 14
+svn:executable
+V 1
+*
+END
diff --git a/btusb_1_6_29_1/.svn/text-base/Makefile.svn-base b/btusb_1_6_29_1/.svn/text-base/Makefile.svn-base
new file mode 100755
index 0000000..6180ea6
--- a/dev/null
+++ b/btusb_1_6_29_1/.svn/text-base/Makefile.svn-base
@@ -0,0 +1,87 @@
+
+# Specify Include folders
+EXTRA_CFLAGS += -I$(SUBDIRS)
+EXTRA_CFLAGS += -I$(SUBDIRS)/inc
+EXTRA_CFLAGS += -I$(SUBDIRS)/src
+EXTRA_CFLAGS += -I$(SUBDIRS)/src/gki
+
+EXTRA_CFLAGS += -DEXPORT_SYMTAB
+
+LITE ?= FALSE
+ifeq ($(strip $(LITE)),TRUE)
+EXTRA_CFLAGS += -DBUILDCFG
+EXTRA_CFLAGS += -DBTUSB_LITE
+EXTRA_CFLAGS += -I$(SUBDIRS)/../btpcm
+EXTRA_CFLAGS += -I$(SUBDIRS)/../btsbc
+COMPONENTS_PATH := $(SUBDIRS)/../../../../../Components
+EXTRA_CFLAGS += -I$(COMPONENTS_PATH)/bta/include
+EXTRA_CFLAGS += -I$(COMPONENTS_PATH)/stack/include
+EXTRA_CFLAGS += -I$(COMPONENTS_PATH)/hcis
+endif
+
+SEC ?= FALSE
+ifeq ($(strip $(SEC)),TRUE)
+EXTRA_CFLAGS += -DBTUSB_LITE_SEC
+EXTRA_CFLAGS += -I$(SUBDIRS)/../btsec
+endif
+
+EXTRA_CFLAGS += -DEXPORT_SYMTAB
+
+# BTUSB_VID and BTUSB_PID can be defined to support a single BT controller type
+# The following definitions are examples for 20702A1 chip
+#EXTRA_CFLAGS += -DBTUSB_VID=0x0A5C
+#EXTRA_CFLAGS += -DBTUSB_PID=0x22BE
+
+usbobjs := \
+ src/btusb.o \
+ src/btusb_dev.o \
+ src/btusb_isoc.o
+
+ifeq ($(strip $(LITE)),TRUE)
+liteobjs := src/btusb_lite.o \
+ src/btusb_lite_av.o \
+ src/btusb_lite_avdt.o \
+ src/btusb_lite_l2c.o \
+ src/btusb_lite_hci.o
+endif
+
+gkiobjs := \
+ src/gki/gki_buffer.o \
+ src/gki/gki_klinux.o
+
+obj-m += btusb.o
+btusb-objs := $(usbobjs) $(gkiobjs) $(liteobjs)
+
+# specify Kernel build location
+KDIR := /lib/modules/$(shell uname -r)/build
+
+PWD := $(shell pwd)
+
+default:
+ifeq ($(strip $(LITE)),TRUE)
+ cat ../btpcm/Module.symvers > ./Module.symvers
+ cat ../btsbc/Module.symvers >> ./Module.symvers
+ifeq ($(strip $(SEC)),TRUE)
+ cat ../btsec/Module.symvers >> ./Module.symvers
+endif
+endif
+ $(MAKE) -C $(KDIR) SUBDIRS=$(PWD) modules
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
+ rm -f Module.markers
+ rm -f Module.symvers
+ rm -f modules.order
+ rm -f ./src/*.o
+ rm -f ./src/.*.o.cmd
+ rm -f ./src/gki/*.o
+ rm -f ./src/gki/.*.o.cmd
+
+help:
+ @echo "BTUSB module configurations and targets:"
+ @echo " LITE=FALSE : No StackLite (Default)"
+ @echo " LITE=TRUE : StackLite compiled"
+ @echo " SEC=FALSE : No SEC Encoder Support(default)"
+ @echo " SEC=TRUE : SEC Encoder Support. Requires StackLite"
+ @echo " clean"
+
diff --git a/btusb_1_6_29_1/.svn/text-base/Release_btusb.txt.svn-base b/btusb_1_6_29_1/.svn/text-base/Release_btusb.txt.svn-base
new file mode 100755
index 0000000..f6228fe
--- a/dev/null
+++ b/btusb_1_6_29_1/.svn/text-base/Release_btusb.txt.svn-base
@@ -0,0 +1,26 @@
+To compile the Bluetooth USB Driver (BTUSB) you have to:
+> cd /3rdparty/embedded/brcm/linux/btusb
+> make
+
+The Makefile may need to be adapted to the target:
+KDIR := /lib/modules/$(shell uname -r)/build => For local kernel (currently running)
+KDIR := /opt/brcm/linux => For different kernel, it should point to the appropriate kernel version
+
+By default btusb supports the most Broadcom's BT controller types.
+To restrict the support to a single VID/PID (USB identifier of the BT controller type), the BTUSB_VID and BTUSB_PID can be defined.
+For 20702 the values to use are:
+EXTRA_CFLAGS += -DBTUSB_VID=0x0A5C
+EXTRA_CFLAGS += -DBTUSB_PID=0x22BE
+
+To install the btusb.ko module, you may have to create a node in /dev:
+mknod btusb0 c 180 194
+
+Furthermore, BlueZ must be uninstalled to avoid driver conflicts.
+
+See BSA Software user guide for further information.
+
+BTUSB Compile Options for Lite Stack Support:
+> make LITE=FALSE => No StackLite (Default)"
+> make LITE=TRUE => StackLite compiled"
+> make SEC=FALSE => No SEC Encoder Support(default)"
+> make SEC=TRUE => SEC Encoder Support (Requires StackLite)
diff --git a/btusb_1_6_29_1/.svn/text-base/cpmod.svn-base b/btusb_1_6_29_1/.svn/text-base/cpmod.svn-base
new file mode 100755
index 0000000..28919a8
--- a/dev/null
+++ b/btusb_1_6_29_1/.svn/text-base/cpmod.svn-base
@@ -0,0 +1 @@
+cp -v btusb.ko /lib/modules/$(uname -r)/kernel/drivers/brcm/btusb.ko
diff --git a/btusb_1_6_29_1/Makefile b/btusb_1_6_29_1/Makefile
new file mode 100755
index 0000000..12b77ca
--- a/dev/null
+++ b/btusb_1_6_29_1/Makefile
@@ -0,0 +1,86 @@
+# Specify Include folders
+EXTRA_CFLAGS += -I$(src)
+EXTRA_CFLAGS += -I$(src)/inc
+EXTRA_CFLAGS += -I$(src)/src
+EXTRA_CFLAGS += -I$(src)/src/gki
+
+EXTRA_CFLAGS += -DEXPORT_SYMTAB
+
+LITE ?= FALSE
+ifeq ($(strip $(LITE)),TRUE)
+EXTRA_CFLAGS += -DBUILDCFG
+EXTRA_CFLAGS += -DBTUSB_LITE
+EXTRA_CFLAGS += -I$(src)/../btpcm
+EXTRA_CFLAGS += -I$(src)/../btsbc
+COMPONENTS_PATH := $(src)/../../../../../Components
+EXTRA_CFLAGS += -I$(COMPONENTS_PATH)/bta/include
+EXTRA_CFLAGS += -I$(COMPONENTS_PATH)/stack/include
+EXTRA_CFLAGS += -I$(COMPONENTS_PATH)/hcis
+endif
+
+SEC ?= FALSE
+ifeq ($(strip $(SEC)),TRUE)
+EXTRA_CFLAGS += -DBTUSB_LITE_SEC
+EXTRA_CFLAGS += -I$(src)/../btsec
+endif
+
+EXTRA_CFLAGS += -DEXPORT_SYMTAB
+
+# BTUSB_VID and BTUSB_PID can be defined to support a single BT controller type
+# The following definitions are examples for 20702A1 chip
+#EXTRA_CFLAGS += -DBTUSB_VID=0x0A5C
+#EXTRA_CFLAGS += -DBTUSB_PID=0x22BE
+
+usbobjs := \
+ src/btusb.o \
+ src/btusb_dev.o \
+ src/btusb_isoc.o
+
+ifeq ($(strip $(LITE)),TRUE)
+liteobjs := src/btusb_lite.o \
+ src/btusb_lite_av.o \
+ src/btusb_lite_avdt.o \
+ src/btusb_lite_l2c.o \
+ src/btusb_lite_hci.o
+endif
+
+gkiobjs := \
+ src/gki/gki_buffer.o \
+ src/gki/gki_klinux.o
+
+obj-m += btusb.o
+btusb-objs := $(usbobjs) $(gkiobjs) $(liteobjs)
+
+# specify Kernel build location
+KDIR := /lib/modules/$(shell uname -r)/build
+
+PWD := $(shell pwd)
+
+default:
+ifeq ($(strip $(LITE)),TRUE)
+ cat ../btpcm/Module.symvers > ./Module.symvers
+ cat ../btsbc/Module.symvers >> ./Module.symvers
+ifeq ($(strip $(SEC)),TRUE)
+ cat ../btsec/Module.symvers >> ./Module.symvers
+endif
+endif
+ $(MAKE) -C $(KDIR) src=$(PWD) modules
+
+clean:
+ rm -rf *.o *~ core .depend .*.cmd *.ko *.mod.c .tmp_versions
+ rm -f Module.markers
+ rm -f Module.symvers
+ rm -f modules.order
+ rm -f ./src/*.o
+ rm -f ./src/.*.o.cmd
+ rm -f ./src/gki/*.o
+ rm -f ./src/gki/.*.o.cmd
+
+help:
+ @echo "BTUSB module configurations and targets:"
+ @echo " LITE=FALSE : No StackLite (Default)"
+ @echo " LITE=TRUE : StackLite compiled"
+ @echo " SEC=FALSE : No SEC Encoder Support(default)"
+ @echo " SEC=TRUE : SEC Encoder Support. Requires StackLite"
+ @echo " clean"
+
diff --git a/btusb_1_6_29_1/Release_btusb.txt b/btusb_1_6_29_1/Release_btusb.txt
new file mode 100755
index 0000000..f6228fe
--- a/dev/null
+++ b/btusb_1_6_29_1/Release_btusb.txt
@@ -0,0 +1,26 @@
+To compile the Bluetooth USB Driver (BTUSB) you have to:
+> cd /3rdparty/embedded/brcm/linux/btusb
+> make
+
+The Makefile may need to be adapted to the target:
+KDIR := /lib/modules/$(shell uname -r)/build => For local kernel (currently running)
+KDIR := /opt/brcm/linux => For different kernel, it should point to the appropriate kernel version
+
+By default btusb supports the most Broadcom's BT controller types.
+To restrict the support to a single VID/PID (USB identifier of the BT controller type), the BTUSB_VID and BTUSB_PID can be defined.
+For 20702 the values to use are:
+EXTRA_CFLAGS += -DBTUSB_VID=0x0A5C
+EXTRA_CFLAGS += -DBTUSB_PID=0x22BE
+
+To install the btusb.ko module, you may have to create a node in /dev:
+mknod btusb0 c 180 194
+
+Furthermore, BlueZ must be uninstalled to avoid driver conflicts.
+
+See BSA Software user guide for further information.
+
+BTUSB Compile Options for Lite Stack Support:
+> make LITE=FALSE => No StackLite (Default)"
+> make LITE=TRUE => StackLite compiled"
+> make SEC=FALSE => No SEC Encoder Support(default)"
+> make SEC=TRUE => SEC Encoder Support (Requires StackLite)
diff --git a/btusb_1_6_29_1/cpmod b/btusb_1_6_29_1/cpmod
new file mode 100755
index 0000000..28919a8
--- a/dev/null
+++ b/btusb_1_6_29_1/cpmod
@@ -0,0 +1 @@
+cp -v btusb.ko /lib/modules/$(uname -r)/kernel/drivers/brcm/btusb.ko
diff --git a/btusb_1_6_29_1/inc/.svn/all-wcprops b/btusb_1_6_29_1/inc/.svn/all-wcprops
new file mode 100755
index 0000000..7907fbf
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/all-wcprops
@@ -0,0 +1,89 @@
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc
+END
+btusb.h
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/btusb.h
+END
+btusb_lite_hci.h
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/btusb_lite_hci.h
+END
+btusbext.h
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/btusbext.h
+END
+btusb_lite_av.h
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/btusb_lite_av.h
+END
+gki_int.h
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/gki_int.h
+END
+hcidefs.h
+K 25
+svn:wc:ra_dav:version-url
+V 82
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/hcidefs.h
+END
+target.h
+K 25
+svn:wc:ra_dav:version-url
+V 81
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/target.h
+END
+bt_types.h
+K 25
+svn:wc:ra_dav:version-url
+V 83
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/bt_types.h
+END
+btusb_lite_avdt.h
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/btusb_lite_avdt.h
+END
+gki.h
+K 25
+svn:wc:ra_dav:version-url
+V 78
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/gki.h
+END
+bt_target.h
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/bt_target.h
+END
+btusb_lite.h
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/btusb_lite.h
+END
+btusb_lite_l2c.h
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/btusb_lite_l2c.h
+END
+data_types.h
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc/data_types.h
+END
diff --git a/btusb_1_6_29_1/inc/.svn/entries b/btusb_1_6_29_1/inc/.svn/entries
new file mode 100755
index 0000000..0300d47
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/entries
@@ -0,0 +1,504 @@
+10
+
+dir
+941
+http://10.10.29.8/svn/SiP/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/inc
+http://10.10.29.8/svn/SiP
+
+
+
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+e48500f2-7125-4e9d-852c-c0ee60673d08
+
+gki_int.h
+file
+
+
+
+
+2014-08-14T08:53:29.672694Z
+e12699f83ff72e3ea04eb7b4e695d999
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5217
+
+hcidefs.h
+file
+
+
+
+
+2014-08-14T08:53:29.684694Z
+dc513c53ca589714768661c65bbd4ba6
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+98140
+
+target.h
+file
+
+
+
+
+2014-08-14T08:53:29.684694Z
+83d3483cbd12dab6fc402e79269e1a05
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2927
+
+bt_types.h
+file
+
+
+
+
+2014-08-14T08:53:29.672694Z
+d4dac46e67c5b708bb4ac7f465ca6bef
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2658
+
+btusb_lite_avdt.h
+file
+
+
+
+
+2014-08-14T08:53:29.644694Z
+81424e4fa8b627779450ac671f8e97ed
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5378
+
+gki.h
+file
+
+
+
+
+2014-08-14T08:53:29.664694Z
+01a5cb997d8a01694f2c0a7edb41da11
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5192
+
+bt_target.h
+file
+
+
+
+
+2014-08-14T08:53:29.684694Z
+d41d8cd98f00b204e9800998ecf8427e
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+0
+
+btusb_lite.h
+file
+
+
+
+
+2014-08-14T08:53:29.652694Z
+97874c1b893d5614d484d7de067947a0
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5144
+
+btusb_lite_l2c.h
+file
+
+
+
+
+2014-08-14T08:53:29.664694Z
+3fa9e2192480e62e9e46499deb2bee84
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+3040
+
+data_types.h
+file
+
+
+
+
+2014-08-14T08:53:29.684694Z
+a14133e6bdadaeee7a812045308ceee7
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+1689
+
+btusb_lite_hci.h
+file
+
+
+
+
+2014-08-14T08:53:29.640694Z
+4ed1c472b2461f945a9f9a4b7f0f9f56
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+2389
+
+btusb.h
+file
+
+
+
+
+2014-08-14T08:53:29.672694Z
+4229196b0ea098c53b26f8482495f2d0
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+12940
+
+btusbext.h
+file
+
+
+
+
+2014-08-14T08:53:29.660694Z
+e41460795e6d063a6e512457c955ad1d
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+5138
+
+btusb_lite_av.h
+file
+
+
+
+
+2014-08-14T08:53:29.652694Z
+7e808f53488a2e2274a186adc40502c6
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+4745
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/bt_target.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/bt_target.h.svn-base
new file mode 100755
index 0000000..e69de29
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/bt_target.h.svn-base
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/bt_types.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/bt_types.h.svn-base
new file mode 100755
index 0000000..f214d54
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/bt_types.h.svn-base
@@ -0,0 +1,78 @@
+/*
+*
+* bt_types.h
+*
+*
+*
+* Copyright (C) 2011-2013 Broadcom Corporation.
+*
+*
+*
+* This software is licensed under the terms of the GNU General Public License,
+* version 2, as published by the Free Software Foundation (the "GPL"), and may
+* be copied, distributed, and modified under those terms.
+*
+* 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 GPL for more details.
+*
+*
+* A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+* or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA
+*
+*
+*/
+
+#ifndef BT_TYPES_H
+#define BT_TYPES_H
+
+#include "data_types.h"
+
+/* READ WELL !!
+**
+** This section defines global events. These are events that cross layers.
+** Any event that passes between layers MUST be one of these events. Tasks
+** can use their own events internally, but a FUNDAMENTAL design issue is
+** that global events MUST be one of these events defined below.
+**
+** The convention used is the the event name contains the layer that the
+** event is going to.
+*/
+#define BT_EVT_TO_BTU_HCI_EVT 0x1000 /* HCI Event */
+
+#define BT_EVT_TO_BTU_HCI_SCO 0x1200 /* SCO Data from HCI */
+
+#define BT_EVT_TO_LM_HCI_CMD 0x2000 /* HCI Command */
+#define BT_EVT_TO_LM_HCI_ACL 0x2100 /* HCI ACL Data */
+#define BT_EVT_TO_LM_DIAG 0x2c00 /* LM Diagnostics commands */
+
+
+#define BT_EVT_BTU_IPC_EVT 0x9000
+#define BT_EVT_BTU_IPC_LOGMSG_EVT (0x0000 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_ACL_EVT (0x0001 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BTU_EVT (0x0002 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_L2C_EVT (0x0003 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_L2C_MSG_EVT (0x0004 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BTM_EVT (0x0005 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_AVDT_EVT (0x0006 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_SLIP_EVT (0x0007 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_MGMT_EVT (0x0008 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BTTRC_EVT (0x0009 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BURST_EVT (0x000A | BT_EVT_BTU_IPC_EVT)
+
+
+/* Define the header of each buffer used in the Bluetooth stack.
+*/
+typedef struct
+{
+ UINT16 event;
+ UINT16 len;
+ UINT16 offset;
+ UINT16 layer_specific;
+} BT_HDR;
+
+#define BT_HDR_SIZE (sizeof (BT_HDR))
+
+
+#endif
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/btusb.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/btusb.h.svn-base
new file mode 100755
index 0000000..aa7534d
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/btusb.h.svn-base
@@ -0,0 +1,367 @@
+/*
+ *
+ * btusb.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef BTUSB_H
+#define BTUSB_H
+
+#include <linux/version.h>
+#include <linux/usb.h>
+#include <linux/tty.h>
+#include <linux/time.h>
+
+#include "bt_types.h"
+#include "gki_int.h"
+#include "btusbext.h"
+
+#ifdef BTUSB_LITE
+#include "btusb_lite.h"
+#endif
+
+/* Linux kernel compatibility abstraction */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
+#define BTUSB_USHRT_MAX USHORT_MAX
+#else
+#define BTUSB_USHRT_MAX USHRT_MAX
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+#define BTUSB_PDE_DATA(inode) PDE(inode)->data
+#else
+#define BTUSB_PDE_DATA(inode) PDE_DATA(inode)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+#define BTUSB_BUFFER_ALLOC usb_buffer_alloc
+#define BTUSB_BUFFER_FREE usb_buffer_free
+#else
+#define BTUSB_BUFFER_ALLOC usb_alloc_coherent
+#define BTUSB_BUFFER_FREE usb_free_coherent
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+#define BTUSB_EP_TYPE(ep) (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+#define BTUSB_EP_DIR_IN(ep) ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+#define BTUSB_EP_DIR_OUT(ep) ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+#else
+#define BTUSB_EP_TYPE(ep) usb_endpoint_type(ep)
+#define BTUSB_EP_DIR_IN(ep) usb_endpoint_dir_in(ep)
+#define BTUSB_EP_DIR_OUT(ep) usb_endpoint_dir_out(ep)
+#endif
+
+// debug information flags. one-hot encoded:
+// bit0 : enable printk(KERN_DEBUG)
+// bit1 : enable printk(KERN_INFO)
+// bit16 : enable all message dumps in printk
+// bit18 : enable GKI buffer check
+// bit19 : enable RX ACL size check
+#define BTUSB_DBG_MSG 0x0001
+#define BTUSB_INFO_MSG 0x0002
+#define BTUSB_DUMP_MSG 0x0100
+#define BTUSB_GKI_CHK_MSG 0x0400
+//#define BTUSB_DBGFLAGS (BTUSB_DBG_MSG | BTUSB_INFO_MSG | BTUSB_DUMP_MSG | BTUSB_GKI_CHK_MSG)
+#define BTUSB_DBGFLAGS 0
+
+extern int dbgflags;
+
+#define BTUSB_DBG(fmt, ...) if (unlikely(dbgflags & BTUSB_DBG_MSG)) \
+ printk(KERN_DEBUG "BTUSB %s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+
+#define BTUSB_INFO(fmt, ...) if (unlikely(dbgflags & BTUSB_INFO_MSG))\
+ printk(KERN_INFO "BTUSB %s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+
+#define BTUSB_ERR(fmt, ...) \
+ printk(KERN_ERR "BTUSB %s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+
+// TBD: how do we assign the minor range?
+#define BTUSB_MINOR_BASE 194
+
+// 1025 = size(con_hdl) + size(acl_len) + size(3-dh5) = 2 + 2 + 1021
+#define BTUSB_HCI_MAX_ACL_SIZE 1025
+// Maximum size of command and events packets (events = 255 + 2, commands = 255 + 3)
+#define BTUSB_HCI_MAX_CMD_SIZE 258
+#define BTUSB_HCI_MAX_EVT_SIZE 258
+
+// Maximum HCI H4 size = HCI type + ACL packet
+#define BTUSB_H4_MAX_SIZE (1 + BTUSB_HCI_MAX_ACL_SIZE)
+
+#define BTUSB_NUM_OF_ACL_RX_BUFFERS 12
+#define BTUSB_NUM_OF_ACL_TX_BUFFERS 12
+#define BTUSB_NUM_OF_DIAG_RX_BUFFERS 2 // must not be less than 2
+#define BTUSB_NUM_OF_DIAG_TX_BUFFERS 2
+#define BTUSB_NUM_OF_EVENT_BUFFERS 8 // should not be less than 2
+#define BTUSB_NUM_OF_CMD_BUFFERS 8
+#define BTUSB_MAXIMUM_TX_VOICE_SIZE 192
+#define BTUSB_NUM_OF_VOICE_RX_BUFFERS 2 // for now should match 2 urbs
+#define BTUSB_NUM_OF_VOICE_TX_BUFFERS 32
+
+#define SCO_RX_BUFF_SIZE 360
+#define SCO_RX_MAX_LEN 240
+
+#define BTUSB_VOICE_BURST_SIZE 48
+#define BTUSB_VOICE_HEADER_SIZE 3
+#define BTUSB_VOICE_FRAMES_PER_URB 9
+#define BTUSB_VOICE_BUFFER_MAXSIZE (BTUSB_VOICE_FRAMES_PER_URB * \
+ ALIGN(BTUSB_VOICE_BURST_SIZE + BTUSB_VOICE_HEADER_SIZE, 4))
+
+
+#ifndef UINT8_TO_STREAM
+#define UINT8_TO_STREAM(p, u8) {*(p)++ = (UINT8)(u8);}
+#define UINT16_TO_STREAM(p, u16) {*(p)++ = (UINT8)(u16); *(p)++ = (UINT8)((u16) >> 8);}
+#define BDADDR_TO_STREAM(p, a) {register int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (UINT8) a[BD_ADDR_LEN - 1 - ijk];}
+#define ARRAY_TO_STREAM(p, a, len) {register int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (UINT8) a[ijk];}
+
+#define STREAM_TO_UINT8(u8, p) {u8 = (UINT8)(*(p)); (p) += 1;}
+#define STREAM_TO_UINT16(u16, p) {u16 = (UINT16)((*(p)) + ((*((p) + 1)) << 8)); (p) += 2;}
+#define STREAM_TO_UINT32(u32, p) {u32 = (((UINT32)(*(p))) + ((((UINT32)(*((p) + 1)))) << 8) + ((((UINT32)(*((p) + 2)))) << 16) + ((((UINT32)(*((p) + 3)))) << 24)); (p) += 4;}
+#define STREAM_TO_BDADDR(a, p) {register int ijk; register UINT8 *pbda = (UINT8 *)a + BD_ADDR_LEN - 1; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *pbda-- = *p++;}
+#define STREAM_TO_ARRAY(a, p, len) {register int ijk; for (ijk = 0; ijk < len; ijk++) ((UINT8 *) a)[ijk] = *p++;}
+#endif
+
+#define UINT32_TO_BE_STREAM(p, u32) {*(p)++ = (UINT8)((u32) >> 24); *(p)++ = (UINT8)((u32) >> 16); *(p)++ = (UINT8)((u32) >> 8); *(p)++ = (UINT8)(u32); }
+#define UINT24_TO_BE_STREAM(p, u24) {*(p)++ = (UINT8)((u24) >> 16); *(p)++ = (UINT8)((u24) >> 8); *(p)++ = (UINT8)(u24);}
+#define UINT16_TO_BE_STREAM(p, u16) {*(p)++ = (UINT8)((u16) >> 8); *(p)++ = (UINT8)(u16);}
+#define UINT8_TO_BE_STREAM(p, u8) {*(p)++ = (UINT8)(u8);}
+
+// macro that helps parsing arrays
+#define BTUSB_ARRAY_FOR_EACH_TRANS(__a) \
+ for (idx = 0, p_trans = &__a[0]; idx < ARRAY_SIZE(__a); idx++, p_trans = &__a[idx])
+
+/* Layer Specific field: Used to send packet to User Space */
+#define BTUSB_LS_H4_TYPE_SENT (1<<0) /* H4 HCI Type already sent */
+#define BTUSB_LS_GKI_BUFFER (1<<1) /* Locally allocated buffer-not to resubmit */
+
+//
+// Container used to copy the URB to sniff the SCO
+//
+struct btusb_scosniff
+{
+ struct list_head lh; // to add element to a list
+ int s; // start frame
+ unsigned int n; // number of descriptors
+ unsigned int l; // buffer length
+ struct usb_iso_packet_descriptor d[0]; // descriptors
+};
+
+//
+// This data structure is used for isochronous transfers
+//
+typedef struct
+{
+ // These two must go in sequence
+ void *dev;
+ unsigned char *packet;
+ int length;
+ unsigned long index;
+ int used;
+
+ // URB & related info must be the last fields
+ struct urb urb;
+ // enough to cover the longest request
+ struct usb_iso_packet_descriptor IsoPacket[(BTUSB_MAXIMUM_TX_VOICE_SIZE /9) + 1];
+} tBTUSB_ISO_ELEMENT;
+
+// BTUSB transaction
+typedef struct
+{
+ /* This is mapped to a GKI buffer to allow queuing */
+ BUFFER_HDR_T gki_hdr;
+ /* Sharing queue with other packets -> needs BT header to multiplex */
+ BT_HDR bt_hdr;
+ /* Pointer to the location where the USB data is received */
+ UINT8 *dma_buffer;
+ /* DMA structure */
+ dma_addr_t dma;
+ /* URB for this transaction */
+ struct urb *p_urb;
+ void *context;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ /* Magic number */
+ UINT32 magic;
+#endif
+} tBTUSB_TRANSACTION;
+
+// Voice channel descriptor
+typedef struct
+{
+ unsigned short sco_handle;
+ unsigned char burst;
+} tBTUSB_SCO_INFO;
+
+typedef struct
+{
+ int used;
+ BT_HDR *p_msg;
+ tBTUSB_SCO_INFO info;
+} tBTUSB_VOICE_CHANNEL;
+
+#define BTUSB_QUIRK_ZLP_TX_REQ (1 << 0)
+#define BTUSB_QUIRK_ZLP_RX_WA (1 << 1)
+
+// Define the main structure
+typedef struct btusb_cb
+{
+ struct usb_device *p_udev; // the usb device for this device
+ const struct usb_device_id *p_id; // Device Id from probe
+ struct usb_interface *p_main_intf; // Main Interface reference
+ struct usb_interface *p_voice_intf; // VOICE Interface reference
+ struct usb_interface *p_dfu_intf; // DFU Interface reference
+ struct usb_interface *p_diag_intf; // Diag Interface reference
+
+ struct usb_host_endpoint *p_acl_in; // the acl bulk in endpoint
+ struct usb_host_endpoint *p_acl_out; // the acl bulk out endpoint
+ struct usb_host_endpoint *p_diag_in; // the diag bulk in endpoint
+ struct usb_host_endpoint *p_diag_out; // the diag bulk out endpoint
+ struct usb_host_endpoint *p_event_in; // the interrupt in endpoint
+ struct usb_host_endpoint *p_voice_out; // iso out endpoint
+ struct usb_host_endpoint *p_voice_in; // voice in endpoint
+ struct ktermios kterm; // TTY emulation
+ struct mutex open_mutex; // protect concurrent open accesses
+ spinlock_t tasklet_lock;
+ struct kref kref;
+ tBTUSB_STATS stats;
+ bool opened;
+ bool issharedusb;
+ unsigned int quirks;
+
+ // reception queue
+ wait_queue_head_t rx_wait_q;
+
+ // tx tasklet
+ struct tasklet_struct tx_task;
+
+ // proc filesystem entry to retrieve info from driver environment
+ struct proc_dir_entry *p_debug_pde;
+ bool scosniff_active;
+ struct proc_dir_entry *p_scosniff_pde;
+ struct list_head scosniff_list;
+ struct completion scosniff_completion;
+
+ // Command transmit path
+ tBTUSB_TRANSACTION cmd_array[BTUSB_NUM_OF_CMD_BUFFERS];
+ struct usb_ctrlrequest cmd_req_array[BTUSB_NUM_OF_CMD_BUFFERS];
+ struct usb_anchor cmd_submitted;
+
+ // Event receive path
+ tBTUSB_TRANSACTION event_array[BTUSB_NUM_OF_EVENT_BUFFERS];
+ struct usb_anchor event_submitted;
+
+ // ACL receive path
+ tBTUSB_TRANSACTION acl_rx_array[BTUSB_NUM_OF_ACL_RX_BUFFERS];
+ struct usb_anchor acl_rx_submitted;
+
+ // ACL transmit path
+ tBTUSB_TRANSACTION acl_tx_array[BTUSB_NUM_OF_ACL_TX_BUFFERS];
+ struct usb_anchor acl_tx_submitted;
+
+ // Diagnostics receive path
+ tBTUSB_TRANSACTION diag_rx_array[BTUSB_NUM_OF_DIAG_RX_BUFFERS];
+ struct usb_anchor diag_rx_submitted;
+
+ // Diagnostics transmit path
+ tBTUSB_TRANSACTION diag_tx_array[BTUSB_NUM_OF_DIAG_TX_BUFFERS];
+ struct usb_anchor diag_tx_submitted;
+
+ // Voice
+ tBTUSB_TRANSACTION voice_rx_array[BTUSB_NUM_OF_VOICE_RX_BUFFERS];
+ struct usb_anchor voice_rx_submitted;
+
+ tBTUSB_VOICE_CHANNEL voice_channels[3];
+ unsigned short desired_packet_size;
+ unsigned int pending_bytes;
+ BT_HDR **pp_pending_msg;
+ unsigned char pending_hdr[BTUSB_VOICE_HEADER_SIZE];
+ unsigned int pending_hdr_size;
+
+ BT_HDR *p_write_msg;
+
+ unsigned long room_for_device_object; // must be here before the pending buffer
+ tBTUSB_ISO_ELEMENT *p_voicetxIrpList;
+ unsigned long voicetxIrpIndex;
+
+ BUFFER_Q rx_queue;
+ BT_HDR *p_rx_msg;
+ BUFFER_Q tx_queue;
+
+#ifdef BTUSB_LITE
+ struct btusb_lite_cb lite_cb;
+#endif
+} tBTUSB_CB;
+
+
+//
+// Function prototypes
+//
+void btusb_delete(struct kref *kref);
+
+void btusb_tx_task(unsigned long arg);
+
+void btusb_cancel_voice(tBTUSB_CB *p_dev);
+void btusb_cancel_urbs(tBTUSB_CB *p_dev);
+
+void btusb_voice_stats(unsigned long *p_max, unsigned long *p_min,
+ struct timeval *p_result, struct timeval *p_last_time);
+
+/* URB submit */
+int btusb_submit(tBTUSB_CB *p_dev, struct usb_anchor *p_anchor, tBTUSB_TRANSACTION *p_trans, int mem_flags);
+void btusb_submit_voice_rx(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, int mem_flags);
+
+/* bt controller to host routines */
+void btusb_enqueue(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, UINT8 hcitype);
+void btusb_dequeued(tBTUSB_CB *p_dev, BT_HDR *p_msg);
+
+void btusb_dump_data(const UINT8 *p, int len, const char *p_title);
+
+void btusb_cmd_complete(struct urb *p_urb);
+void btusb_write_complete(struct urb *p_urb);
+void btusb_voicerx_complete(struct urb *p_urb);
+
+// USB device interface
+int btusb_open(struct inode *inode, struct file *file);
+int btusb_release(struct inode *inode, struct file *file);
+ssize_t btusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
+ssize_t btusb_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos);
+unsigned int btusb_poll(struct file *file, struct poll_table_struct *p_pt);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+long btusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+int btusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+
+// proc standard interface
+int btusb_debug_open(struct inode *inode, struct file *file);
+ssize_t btusb_debug_write(struct file *file, const char *buf, size_t count, loff_t *pos);
+
+ssize_t btusb_scosniff_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
+int btusb_scosniff_open(struct inode *inode, struct file *file);
+int btusb_scosniff_release(struct inode *inode, struct file *file);
+
+//
+// Globals
+//
+extern struct usb_driver btusb_driver;
+extern bool autopm;
+
+#endif // BTUSB_H
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite.h.svn-base
new file mode 100755
index 0000000..66faaaa
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite.h.svn-base
@@ -0,0 +1,198 @@
+/*
+ *
+ * btusb_lite.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_H
+#define BTUSB_LITE_H
+
+/* Forward declaration of BTUSB CB */
+struct btusb_cb;
+
+#include "bt_target.h"
+#include "hcidefs.h"
+#include "bd.h"
+#include "uipc_msg.h"
+#include "btusb_lite_av.h"
+#include "btusb_lite_avdt.h"
+#include "btusb_lite_l2c.h"
+#include "btusb_lite_hci.h"
+
+/*
+ * Definitions
+ */
+/* IPC Length Header Size (16 bits) */
+#define BTUSB_LITE_IPC_HDR_LEN_SIZE (sizeof(UINT16))
+
+/* IPC Event Header Size (16 bits) */
+#define BTUSB_LITE_IPC_HDR_EVT_SIZE (sizeof(UINT16))
+
+/* IPC Header contains a Length and an Event code */
+#define BTUSB_LITE_IPC_HDR_SIZE (BTUSB_LITE_IPC_HDR_LEN_SIZE + BTUSB_LITE_IPC_HDR_EVT_SIZE)
+
+struct btusb_lite_mgt_cb
+{
+ int opened;
+};
+
+struct btusb_lite_stat
+{
+ unsigned long event_bytes;
+ unsigned long event_completed;
+};
+
+struct btusb_lite_from_app
+{
+ BT_HDR *p_rx_msg;
+ UINT8 rx_header[BTUSB_LITE_IPC_HDR_SIZE];
+ UINT8 rx_header_len;
+ UINT16 rx_len; /* Decoded Rx Payload length */
+};
+
+struct btusb_lite_to_app
+{
+ BUFFER_Q ipc_queue; /* IPC message queue */
+ BT_HDR *p_ipc_msg;
+ BT_HDR *p_hdr_msg;
+ BT_HDR *p_hci_msg;
+};
+
+/* Lite Stack mode */
+#define BTU_FULL_STACK_ACTIVE 0
+#define BTU_LITE_STACK_ACTIVE 1
+#define BTU_TRANSPORT_HOLD 2
+#define BTU_FULL_TRANSPORT_ACTIVE 3
+#define BTU_LITE_TRANSPORT_ACTIVE 4
+
+#define BTU_IPC_CMD_SET_TRANSPORT_STATE 0 /* Set transport state (param=transprt state) */
+#define BTU_IPC_CMD_DISABLE_TRANSPORT 1 /* Set transport hardware (param=1 to disable) */
+
+struct btusb_lite_btu_cb
+{
+ UINT8 transport_state;
+ UINT8 transport_disabled;
+};
+
+typedef enum
+{
+ BTPCM_LITE_PCM_CLOSED = 0,
+ BTPCM_LITE_PCM_OPENED,
+ BTPCM_LITE_PCM_CONFIGURED,
+ BTPCM_LITE_PCM_STARTED
+} btusb_lite_pcm_state_t;
+
+struct btusb_lite_pcm_ccb
+{
+ btusb_lite_pcm_state_t state;
+ int channel;
+ int frequency;
+};
+
+struct btusb_lite_encoder_ccb
+{
+ int channel;
+ int opened;
+ int encoded_frame_size;
+ int pcm_frame_size;
+ int header_size;
+ int type; /* SBC, SEC, etc. */
+ tBTA_AV_AUDIO_CODEC_INFO encoder;
+};
+
+struct btusb_lite_av_cb
+{
+ UINT8 audio_open_cnt;
+ UINT16 curr_mtu;
+ UINT8 multi_av;
+ struct btusb_lite_pcm_ccb pcm;
+ struct btusb_lite_encoder_ccb encoder;
+ struct btusb_lite_av_scb scb[BTA_AV_NUM_STRS];
+ BT_HDR *p_buf_working;
+ UINT8 option;
+ UINT8 m_pt;
+ int header_len;
+ int payload_len;
+ UINT32 timestamp;
+};
+
+/* Main Lite Control Block */
+struct btusb_lite_cb
+{
+ struct proc_dir_entry *p_lite_pde;
+ int opened;
+ struct btusb_lite_stat stat;
+ struct btusb_lite_from_app from_app;
+ struct btusb_lite_to_app to_app;
+ struct btusb_lite_mgt_cb mgt; /* Management */
+ struct btusb_lite_btu_cb btu; /* BTU */
+ struct btusb_lite_l2c_cb l2c; /* L2C */
+ struct btusb_lite_av_cb av; /* AV */
+ struct btusb_lite_avdt_cb avdt;
+};
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_create
+ **
+ ** Description Create BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+int btusb_lite_create(struct btusb_cb *p_dev, struct usb_interface *p_interface);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_delete
+ **
+ ** Description Delete BTUSB Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+void btusb_lite_delete(struct btusb_cb *p_dev, struct usb_interface *p_interface);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_stop_all
+ **
+ ** Description Stop all sound streams
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_lite_stop_all(struct btusb_cb *p_dev);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_is_hci_over_ipc
+ **
+ ** Description Check if HCI is over IPC (Lite Interface).
+ **
+ ** Returns int (1 if HCI is over IPC otherwise 0)
+ **
+ *******************************************************************************/
+int btusb_lite_is_hci_over_ipc(struct btusb_cb *p_dev);
+
+#endif /* BTUSB_LITE_H*/
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_av.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_av.h.svn-base
new file mode 100755
index 0000000..f19ad0b
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_av.h.svn-base
@@ -0,0 +1,135 @@
+/*
+ *
+ * btusb_lite_av.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_AV_H
+#define BTUSB_LITE_AV_H
+
+typedef UINT8 tBTA_AV_CODEC; /* codec type */
+typedef UINT8 tBTA_AV_CHNL; /* the channel: audio/video */
+typedef UINT8 tBTA_AV_HNDL; /* the handle: ((hdi + 1)|chnl) */
+
+/* data type for the Audio Codec Information*/
+typedef struct
+{
+ UINT16 bit_rate; /* SBC encoder bit rate in kbps */
+ UINT16 bit_rate_busy; /* SBC encoder bit rate in kbps */
+ UINT16 bit_rate_swampd;/* SBC encoder bit rate in kbps */
+ UINT8 busy_level; /* Busy level indicating the bit-rate to be used */
+ UINT8 codec_info[AVDT_CODEC_SIZE];
+ UINT8 codec_type; /* Codec type */
+} tBTA_AV_AUDIO_CODEC_INFO;
+
+/* type for AV stream control block on Lite stack*/
+struct btusb_lite_av_scb
+{
+ BUFFER_Q out_q; /* used for audio channels only */
+ BD_ADDR peer_addr; /* peer BD address */
+ UINT16 l2c_cid; /* L2CAP channel ID */
+ tBTA_AV_CODEC codec_type; /* codec type */
+ BOOLEAN cong; /* TRUE if AVDTP congested */
+ tBTA_AV_CHNL chnl; /* the channel: audio/video */
+ tBTA_AV_HNDL hndl; /* the handle: ((hdi + 1)|chnl) */
+ UINT8 avdt_handle; /* AVDTP handle */
+ UINT8 hdi; /* the index to SCB[] */
+ UINT8 l2c_bufs; /* the number of buffers queued to L2CAP */
+ BOOLEAN started; /* TRUE if stream started from call-out perspective */
+ BOOLEAN start_stop_flag;/* TRUE when snk is INT and bta_av_start_ok() decides that */
+};
+
+/* these bits are defined for btusb_lite_av_cb.multi_av */
+#define BTA_AV_MULTI_AV_SUPPORTED 0x01
+#define BTA_AV_MULTI_AV_IN_USE 0x02
+
+/*
+ * Globals
+ */
+extern int pcm0_mute;
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_add
+**
+** Description Add (Sync) an AV channel.
+**
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_add(struct btusb_cb *p_dev, tBTA_AV_SYNC_INFO *p_sync_info,
+ UINT8 multi_av_supported, UINT16 curr_mtu);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_remove
+**
+** Description Remove (Cleanup) an AV channel.
+**
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_remove(struct btusb_cb *p_dev, UINT8 scb_idx,
+ UINT8 audio_open_cnt, UINT16 curr_mtu);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_start
+**
+** Description Start AV
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+void btusb_lite_av_start(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 start_stop_flag,
+ UINT8 audio_open_cnt, tBTA_AV_AUDIO_CODEC_INFO *p_codec_cfg);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_stop
+**
+** Description Start AV
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+void btusb_lite_av_stop(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_suspend
+**
+** Description Suspend AV
+**
+** Returns none.
+**
+*******************************************************************************/
+void btusb_lite_av_suspend(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt);
+
+#endif /* BTUSB_LITE_AV_H*/
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_avdt.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_avdt.h.svn-base
new file mode 100755
index 0000000..3538cc7
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_avdt.h.svn-base
@@ -0,0 +1,148 @@
+/*
+ *
+ * btusb_lite_avdt.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_AVDT_H
+#define BTUSB_LITE_AVDT_H
+
+/* AVDT Option */
+#define BTUSB_LITE_AVDT_OPT_NO_RTP 0x01 /* No RTP Header */
+#define BTUSB_LITE_AVDT_OPT_NO_MPH 0x02 /* No Media Payload Header */
+
+/* Definitions for A2DP packets */
+#define BTUSB_LITE_RTP_SIZE 12 /* RTP Header size */
+#define BTUSB_LITE_MEDIA_SIZE 1 /* Media Header size */
+#define BTUSB_LITE_SCMS_SIZE 1 /* SCMS Header size */
+
+/* Some A2DP Definitions */
+#define AVDT_MEDIA_OCTET1 0x80 /* First byte of media packet header */
+
+#define AVDT_MARKER_SET 0x80
+#define AVDT_RTP_PAYLOAD_TYPE 0x60 /* First Dynamic Payload type */
+
+/* AVDT Header size */
+#define BTUSB_LITE_AVDT_HDR_SIZE (BTUSB_LITE_RTP_SIZE + BTUSB_LITE_MEDIA_SIZE)
+
+/* A2DP Definitions */
+#define A2D_SBC_HDR_NUM_MSK 0x0F /* A2DP Media Header Frame Mask */
+
+
+/* channel control block type */
+struct btusb_lite_avdt_ccb
+{
+ BD_ADDR peer_addr; /* BD address of peer */
+ BOOLEAN allocated; /* Whether ccb is allocated */
+ UINT16 lcid; /* local L2CAP channel ID */
+ UINT16 peer_mtu; /* L2CAP mtu of the peer device */
+};
+
+/* SCMS information */
+struct btusb_lite_avdt_scms
+{
+ BOOLEAN enable; /* Indicates if SCMS is enabled */
+ UINT8 header; /* SCMS Header */
+};
+
+
+/* stream control block type */
+struct btusb_lite_avdt_scb
+{
+ BT_HDR *p_pkt; /* packet waiting to be sent */
+ struct btusb_lite_avdt_ccb *p_ccb; /* ccb associated with this scb */
+ UINT16 media_seq; /* media packet sequence number */
+ BOOLEAN allocated; /* whether scb is allocated or unused */
+ BOOLEAN in_use; /* whether stream being used by peer */
+ BOOLEAN cong; /* Whether media transport channel is congested */
+ UINT8 handle;
+ UINT8 mux_tsid_media; /* TSID for media transport session */
+ struct btusb_lite_avdt_scms scms;
+};
+
+struct btusb_lite_avdt_cb
+{
+ struct btusb_lite_avdt_ccb ccb[AVDT_NUM_LINKS]; /* channel control blocks */
+ struct btusb_lite_avdt_scb scb[AVDT_NUM_SEPS]; /* stream control blocks */
+
+};
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_scb_by_hdl
+**
+** Description Given an scb handle (or seid), return a pointer to the scb.
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+struct btusb_lite_avdt_scb *btusb_lite_avdt_scb_by_hdl(struct btusb_cb *p_dev, UINT8 hdl);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_init_scb
+**
+** Description allocate and initialize SCB/CCB with received sync info
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_init_scb(struct btusb_cb *p_dev, tAVDT_SCB_SYNC_INFO *p_scb_info);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_remove_scb
+**
+** Description deallocate SCB and CCB
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_remove_scb(struct btusb_cb *p_dev, UINT8 handle, tAVDT_SCB_SYNC_INFO *p_scb_info);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_send
+**
+** Description AVDT packet send
+**
+** Returns None
+**
+*******************************************************************************/
+void btusb_lite_avdt_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT8 avdt_handle,
+ UINT8 m_pt, UINT8 option, UINT32 timestamp);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_cp_set_scms
+**
+** Description Set SCMS Content Protection for a channel
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_cp_set_scms(struct btusb_cb *p_dev, UINT8 avdt_handle,
+ BOOLEAN enable, UINT8 scms_hdr);
+
+#endif /* BTUSB_LITE_AVDT_H*/
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_hci.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_hci.h.svn-base
new file mode 100755
index 0000000..bb88d26
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_hci.h.svn-base
@@ -0,0 +1,71 @@
+/*
+ *
+ * btusb_lite_hci.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef BTUSB_LITE_HCI_H
+#define BTUSB_LITE_HCI_H
+
+/* Definitions for HCI ACL packets */
+
+/* HCI ACL Packet: HCI_Type, ConHdl, Length */
+#define BTUSB_LITE_HCI_ACL_HDR_SIZE (sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT16))
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_acl_send
+ **
+ ** Description Send an ACL packet to HCI
+ **
+ ** Returns Status
+ **
+ *******************************************************************************/
+int btusb_lite_hci_acl_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 con_hdl);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_cmd_filter
+ **
+ ** Description Check if the Sent HCI Command need to be handled/caught (not
+ ** sent to BT controller).
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+int btusb_lite_hci_cmd_filter(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_event_filter
+ **
+ ** Description Handle/Filter HCI Events received from BT controller
+ **
+ ** Returns int (1 if HCI is over IPC otherwise 0)
+ **
+ *******************************************************************************/
+int btusb_lite_hci_event_filter(struct btusb_cb *p_dev, UINT8 *p_data, int length);
+
+#endif /* BTUSB_LITE_HCI_H */
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_l2c.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_l2c.h.svn-base
new file mode 100755
index 0000000..bf5aa6a
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/btusb_lite_l2c.h.svn-base
@@ -0,0 +1,105 @@
+/*
+ *
+ * btusb_lite_l2c.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_L2C_H
+#define BTUSB_LITE_L2C_H
+
+/* L2CAP Header Definition (Length, CID) */
+#define BTUSB_LITE_L2CAP_HDR_SIZE (sizeof(UINT16) + sizeof(UINT16))
+
+struct btusb_lite_l2c_ccb
+{
+ BOOLEAN in_use;
+ UINT16 local_cid;
+ UINT16 remote_cid;
+ UINT16 out_mtu;
+ UINT16 handle;
+ UINT16 link_xmit_quota;
+ UINT8 is_flushable;
+
+ UINT16 tx_pending;
+};
+
+struct btusb_lite_l2c_cb
+{
+ /* Req */
+ UINT16 light_xmit_quota;
+ UINT16 acl_data_size;
+ UINT16 non_flushable_pbf;
+ UINT8 multi_av_data_cong_start;
+ UINT8 multi_av_data_cong_end;
+ UINT8 multi_av_data_cong_discard;
+ struct btusb_lite_l2c_ccb ccb[BTM_SYNC_INFO_NUM_STR];
+
+ /* Status */
+ UINT16 light_xmit_unacked;
+};
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_add
+**
+** Description Synchronize (Add) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_add(struct btusb_cb *p_dev, tL2C_STREAM_INFO *p_l2c_stream);
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_remove
+**
+** Description Synchronize (Remove) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_remove(struct btusb_cb *p_dev, UINT16 local_cid);
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_send
+**
+** Description Send L2CAP packet
+**
+** Returns Status
+**
+*******************************************************************************/
+int btusb_lite_l2c_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 local_cid);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_l2c_nocp_hdlr
+ **
+ ** Description L2CAP NumberOfcompletePacket Handler function
+ **
+ ** Returns Number Of Complete Packet caught
+ **
+ *******************************************************************************/
+UINT16 btusb_lite_l2c_nocp_hdlr(struct btusb_cb *p_dev, UINT16 con_hdl, UINT16 num_cplt_pck);
+
+#endif /* BTUSB_LITE_L2C_H*/
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/btusbext.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/btusbext.h.svn-base
new file mode 100755
index 0000000..ccdff66
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/btusbext.h.svn-base
@@ -0,0 +1,169 @@
+/*
+ *
+ * btusbext.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef BTUSBEXT_H
+#define BTUSBEXT_H
+
+#include <linux/time.h>
+
+// BTUSB Statistics structure
+typedef struct
+{
+ // All URB submit counter
+ unsigned long urb_submit_ok;
+ unsigned long urb_submit_err;
+
+ // ACL RX counters
+ unsigned long acl_rx_submit_ok;
+ unsigned long acl_rx_submit_err;
+ unsigned long acl_rx_completed;
+ unsigned long acl_rx_resubmit;
+ unsigned long acl_rx_bytes;
+
+ // DIAG RX counters
+ unsigned long diag_rx_submit_ok;
+ unsigned long diag_rx_submit_err;
+ unsigned long diag_rx_completed;
+ unsigned long diag_rx_resubmit;
+ unsigned long diag_rx_bytes;
+
+ // EVENT counters
+ unsigned long event_submit_ok;
+ unsigned long event_submit_err;
+ unsigned long event_completed;
+ unsigned long event_resubmit;
+ unsigned long event_bytes;
+
+ // Number of Write IRPs submitted
+ unsigned long writes_submitted;
+
+ // Number of Write IRPs submitted in error
+ unsigned long writes_submitted_error;
+
+ // Number of Write IRPs completed
+ unsigned long writes_completed;
+
+ // Number of Write IRPs completed in error
+ unsigned long writes_completed_error;
+
+ // Number of Command IRPs submitted
+ unsigned long commands_submitted;
+
+ // Number of Command IRPs submitted in error
+ unsigned long commands_submitted_error;
+
+ // Number of Command IRPs completed
+ unsigned long commands_completed;
+
+ // Number of Command IRPs completed in error
+ unsigned long commands_completed_error;
+
+ // Number of voice reqs submitted to the USB software stack
+ unsigned long voicerx_submitted;
+
+ // Number of voice rx submitted in error
+ unsigned long voicerx_submitted_error;
+
+ // Number of voice req completions from the USB software stack
+ unsigned long voicerx_completed;
+
+ // Number of Voice req completions in error
+ unsigned long voicerx_completed_error;
+
+ // Number of bad voice RX packets received
+ unsigned long voicerx_bad_packets;
+
+ // Bytes received altogether
+ unsigned long voicerx_raw_bytes;
+
+ // Bytes skipped
+ unsigned long voicerx_skipped_bytes;
+
+ // SCO headers split across packets
+ unsigned long voicerx_split_hdr;
+
+ // Voice frames discarded due to no headers in data
+ unsigned long voicerx_disc_nohdr;
+
+ // Number of Voice Tx reqs submitted
+ unsigned long voicetx_submitted;
+
+ // Number of voice tx submitted in error
+ unsigned long voicetx_submitted_error;
+
+ // Number of Voice Tx reqs completed
+ unsigned long voicetx_completed;
+
+ // Number of Voice Tx reqs completed in error
+ unsigned long voicetx_completed_error;
+
+ // Number of Voice Tx not submitted due to no room on the tx queue
+ unsigned long voicetx_disc_nobuf;
+
+ // Number of Voice tx not submitted due to too long data
+ unsigned long voicetx_disc_toolong;
+
+ /* number of Voice packet pending */
+ unsigned long voice_tx_cnt;
+
+ /* max number of Voice packet pending */
+ unsigned long voice_max_tx_cnt;
+
+ /* max delta time between 2 consecutive tx done routine in us */
+ unsigned long voice_max_tx_done_delta_time;
+ unsigned long voice_min_tx_done_delta_time;
+ struct timeval voice_tx_done_delta_time;
+ struct timeval voice_last_tx_done_ts;
+
+ /* max delta time between 2 consecutive tx done routine in us */
+ unsigned long voice_max_rx_rdy_delta_time;
+ unsigned long voice_min_rx_rdy_delta_time;
+ struct timeval voice_rx_rdy_delta_time;
+ struct timeval voice_last_rx_rdy_ts;
+
+ /* max delta time between 2 consecutive tx done routine in us */
+ unsigned long voice_max_rx_feeding_interval;
+ unsigned long voice_min_rx_feeding_interval;
+ struct timeval voice_rx_feeding_interval;
+ struct timeval voice_last_rx_feeding_ts;
+} tBTUSB_STATS;
+
+//
+// IOCTL definitions (shared among all user mode applications, do not modify)
+//
+#define IOCTL_BTWUSB_GET_STATS 0x1001
+#define IOCTL_BTWUSB_CLEAR_STATS 0x1002
+#define IOCTL_BTWUSB_PUT 0x1003
+#define IOCTL_BTWUSB_PUT_CMD 0x1004
+#define IOCTL_BTWUSB_GET 0x1005
+#define IOCTL_BTWUSB_GET_EVENT 0x1006
+#define IOCTL_BTWUSB_PUT_VOICE 0x1007
+#define IOCTL_BTWUSB_GET_VOICE 0x1008
+#define IOCTL_BTWUSB_ADD_VOICE_CHANNEL 0x1009
+#define IOCTL_BTWUSB_REMOVE_VOICE_CHANNEL 0x100a
+#define IOCTL_BTWUSB_DEV_RESET 0x100b
+
+#endif // BTUSBEXT_H
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/data_types.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/data_types.h.svn-base
new file mode 100755
index 0000000..e8ccf4b
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/data_types.h.svn-base
@@ -0,0 +1,79 @@
+/*
+*
+* data_types.h
+*
+*
+*
+* Copyright (C) 2011 Broadcom Corporation.
+*
+*
+*
+* This software is licensed under the terms of the GNU General Public License,
+* version 2, as published by the Free Software Foundation (the "GPL"), and may
+* be copied, distributed, and modified under those terms.
+*
+* 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 GPL for more details.
+*
+*
+* A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+* or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA
+*
+*
+*/
+
+#ifndef DATA_TYPES_H
+#define DATA_TYPES_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32, *PUINT32;
+typedef signed int INT32, *PINT32;
+typedef signed char INT8;
+typedef signed short INT16;
+
+
+#if defined(_WIDE_CHAR) || defined(_UNICODE)
+typedef unsigned short WIDECHAR; /* for _BT_WIN32 possibly use wchar_t */
+#define WIDE_NULL_CHAR ((WIDECHAR)0)
+#else
+typedef unsigned char WIDECHAR;
+#define WIDE_NULL_CHAR '\0'
+#endif
+
+typedef UINT32 TIME_STAMP;
+
+
+#ifndef _WINDOWS_VXD
+typedef unsigned char BOOLEAN;
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+#endif
+
+typedef unsigned char UBYTE;
+
+#define PACKED
+#define INLINE
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN FALSE
+#endif
+
+#define UINT16_LOW_BYTE(x) ((x) & 0xff)
+#define UINT16_HI_BYTE(x) ((x) >> 8)
+
+#define ARRAY_SIZEOF(x) (sizeof(x)/sizeof(x[0]))
+
+#endif
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/gki.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/gki.h.svn-base
new file mode 100755
index 0000000..8b04756
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/gki.h.svn-base
@@ -0,0 +1,190 @@
+/*
+ *
+ * gki.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef GKI_H
+#define GKI_H
+
+#include "target.h"
+#include "data_types.h"
+
+//#define TRACE_GKI_BUFFERS
+
+/* Error codes */
+#define GKI_SUCCESS 0x00
+#define GKI_FAILURE 0x01
+#define GKI_INVALID_TASK 0xF0
+#define GKI_INVALID_POOL 0xFF
+
+
+
+/************************************************************************
+** Mailbox definitions. Each task has 4 mailboxes that are used to
+** send buffers to the task.
+*/
+#define TASK_MBOX_0 0
+#define TASK_MBOX_1 1
+#define TASK_MBOX_2 2
+#define TASK_MBOX_3 3
+
+#define NUM_TASK_MBOX 4
+
+/************************************************************************
+** Event definitions.
+**
+** There are 4 reserved events used to signal messages rcvd in task mailboxes.
+** There are 4 reserved events used to signal timeout events.
+** There are 8 general purpose events available for applications.
+*/
+#define MAX_EVENTS 16
+
+#define TASK_MBOX_0_EVT_MASK 0x0001
+#define TASK_MBOX_1_EVT_MASK 0x0002
+#define TASK_MBOX_2_EVT_MASK 0x0004
+#define TASK_MBOX_3_EVT_MASK 0x0008
+
+
+#define TIMER_0 0
+#define TIMER_1 1
+#define TIMER_2 2
+#define TIMER_3 3
+
+#define TIMER_0_EVT_MASK 0x0010
+#define TIMER_1_EVT_MASK 0x0020
+#define TIMER_2_EVT_MASK 0x0040
+#define TIMER_3_EVT_MASK 0x0080
+
+#define APPL_EVT_0 8
+#define APPL_EVT_1 9
+#define APPL_EVT_2 10
+#define APPL_EVT_3 11
+#define APPL_EVT_4 12
+#define APPL_EVT_5 13
+#define APPL_EVT_6 14
+#define APPL_EVT_7 15
+
+#define EVENT_MASK(evt) ((UINT16)(0x0001 << (evt)))
+
+/***********************************************************************
+** This queue is a general purpose buffer queue, for application use.
+*/
+typedef struct
+{
+ void *p_first;
+ void *p_last;
+ UINT16 count;
+} BUFFER_Q;
+
+#define GKI_IS_QUEUE_EMPTY(p_q) ((p_q)->count == 0)
+
+/* Task constants
+*/
+#ifndef TASKPTR_DEF
+#define TASKPTR_DEF
+#if defined (LINUX_KERNEL)
+typedef int (*TASKPTR)(UINT32);
+#else
+typedef void (*TASKPTR)(UINT32);
+#endif
+#endif
+
+#define GKI_PUBLIC_POOL 0 /* General pool accessible to GKI_getbuf() */
+#define GKI_RESTRICTED_POOL 1 /* Inaccessible pool to GKI_getbuf() */
+
+/***********************************************************************
+** Function prototypes
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Task management */
+BT_API extern void GKI_init(void);
+BT_API extern void GKI_shutdown(void);
+
+/* To get and release buffers, change owner and get size
+*/
+BT_API extern void GKI_change_buf_owner (void *, UINT8);
+BT_API extern UINT8 GKI_create_pool (UINT16, UINT16, UINT8, void *);
+BT_API extern void GKI_delete_pool (UINT8);
+BT_API extern void *GKI_find_buf_start (void *);
+BT_API extern void GKI_freebuf (void *);
+#ifdef TRACE_GKI_BUFFERS
+BT_API extern void *GKI_getbuf_trace (UINT16, char *, int);
+#define GKI_getbuf(_size) GKI_getbuf_trace(_size,__FILE__,__LINE__)
+#else
+BT_API extern void *GKI_getbuf (UINT16);
+#endif
+
+BT_API extern UINT16 GKI_get_buf_size (void *);
+BT_API extern UINT16 GKI_get_pool_bufsize (UINT8 pool_id);
+
+// For compatibility with BTE
+#define GKI_POOL_SIZE(x) GKI_get_pool_bufsize(x)
+
+
+#ifdef TRACE_GKI_BUFFERS
+BT_API extern void *GKI_getpoolbuf_trace (UINT8, char *, int);
+#define GKI_getpoolbuf(_pool) GKI_getpoolbuf_trace(_pool,__FILE__,__LINE__)
+#else
+BT_API extern void *GKI_getpoolbuf (UINT8);
+#endif
+
+BT_API extern UINT16 GKI_poolfreecount (UINT8);
+BT_API extern UINT16 GKI_poolutilization (UINT8);
+BT_API extern UINT8 GKI_set_pool_permission(UINT8, UINT8);
+
+
+/* User buffer queue management
+*/
+BT_API extern void *GKI_dequeue (BUFFER_Q *);
+BT_API extern UINT8 GKI_buffer_status(void *p_buf);
+BT_API extern void GKI_enqueue (BUFFER_Q *, void *);
+BT_API extern void GKI_enqueue_head (BUFFER_Q *, void *);
+BT_API extern void *GKI_getfirst (BUFFER_Q *);
+BT_API extern void *GKI_getnext (void *);
+BT_API extern void GKI_init_q (BUFFER_Q *);
+BT_API extern BOOLEAN GKI_queue_is_empty(BUFFER_Q *);
+BT_API extern void *GKI_remove_from_queue (BUFFER_Q *, void *);
+
+BT_API extern BOOLEAN GKI_chk_buf_pool_damage(UINT8 pool_id);
+
+/* Disable Interrupts, Enable Interrupts
+*/
+BT_API extern void GKI_enable(void);
+BT_API extern void GKI_disable(void);
+
+/* Exception handling
+*/
+BT_API extern void GKI_exception (UINT16, const char *msg, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/gki_int.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/gki_int.h.svn-base
new file mode 100755
index 0000000..f210e58
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/gki_int.h.svn-base
@@ -0,0 +1,197 @@
+/*
+ *
+ * gki_int.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef GKI_INT_H
+#define GKI_INT_H
+
+#include "gki.h"
+
+/* Task States: (For OSRdyTbl) */
+// TASK_DEAD is already defined by Linux => undefine it
+#ifdef TASK_DEAD
+#undef TASK_DEAD
+#endif
+
+#define TASK_DEAD 0 /* b0000 */
+#define TASK_READY 1 /* b0001 */
+#define TASK_WAIT 2 /* b0010 */
+#define TASK_DELAY 4 /* b0100 */
+#define TASK_SUSPEND 8 /* b1000 */
+
+
+/********************************************************************
+** Internal Error codes
+*********************************************************************/
+#define GKI_ERROR_BUF_CORRUPTED 0xFFFF
+#define GKI_ERROR_NOT_BUF_OWNER 0xFFFE
+#define GKI_ERROR_FREEBUF_BAD_QID 0xFFFD
+#define GKI_ERROR_FREEBUF_BUF_LINKED 0xFFFC
+#define GKI_ERROR_SEND_MSG_BAD_DEST 0xFFFB
+#define GKI_ERROR_SEND_MSG_BUF_LINKED 0xFFFA
+#define GKI_ERROR_ENQUEUE_BUF_LINKED 0xFFF9
+#define GKI_ERROR_DELETE_POOL_BAD_QID 0xFFF8
+#define GKI_ERROR_BUF_SIZE_TOOBIG 0xFFF7
+#define GKI_ERROR_BUF_SIZE_ZERO 0xFFF6
+#define GKI_ERROR_ADDR_NOT_IN_BUF 0xFFF5
+#define GKI_ERROR_BUF_POOL_CORRUPT 0xFFF4
+#define GKI_ERROR_BUFFER_TRACE_ON 0xFFF3
+#define GKI_ERROR_SEGS_EXCEEDED 0xFFF2
+#define GKI_ERROR_NO_MEMORY_FOR_SEG 0xFFF1
+
+
+/********************************************************************
+** Buffer Management Data Structures
+*********************************************************************/
+
+typedef struct _buffer_hdr
+{
+ struct _buffer_hdr *p_next;
+ UINT8 q_id;
+ UINT8 task_id;
+ UINT8 status;
+ UINT8 Type;
+#ifdef TRACE_GKI_BUFFERS
+ struct _buffer_hdr *p_next_all;
+ char *pFile;
+ int linenum;
+ UINT32 times_alloc;
+#endif
+} BUFFER_HDR_T;
+
+/* Allocate each buffer pool in up to 4 memory segments, for efficiency
+*/
+#define MAX_BUFFPOOL_SEGS 4
+
+typedef struct _free_queue
+{
+ UINT8 *seg_start[MAX_BUFFPOOL_SEGS];
+ UINT8 *seg_end[MAX_BUFFPOOL_SEGS];
+
+ BUFFER_HDR_T *p_first;
+ BUFFER_HDR_T *p_last;
+ UINT16 total;
+ UINT16 cur_cnt;
+ UINT16 max_cnt;
+#ifdef TRACE_GKI_BUFFERS
+ BUFFER_HDR_T *p_first_all;
+#endif
+} FREE_QUEUE_T;
+
+
+/* Buffer related defines
+*/
+#define BUFFER_HDR_SIZE (sizeof(BUFFER_HDR_T)) /* Offset past header */
+#define BUFFER_PADDING_SIZE (sizeof(BUFFER_HDR_T) + sizeof(UINT32)) /* Header + Magic Number */
+#define MAX_USER_BUF_SIZE ((UINT16)0xffff - BUFFER_PADDING_SIZE) /* pool size must allow for header */
+#define MAGIC_NO 0xDDBADDBA
+
+#define BUF_STATUS_FREE 0
+#define BUF_STATUS_UNLINKED 1
+#define BUF_STATUS_QUEUED 2
+
+/* Exception related structures
+*/
+#define MAX_EXCEPTION 8
+#define MAX_EXCEPTION_MSGLEN 64
+
+typedef struct
+{
+ UINT16 type;
+ UINT8 taskid;
+ UINT8 msg[MAX_EXCEPTION_MSGLEN];
+} EXCEPTION_T;
+
+
+/* Put all GKI variables into one control block
+*/
+typedef struct
+{
+ /* Task management variables
+ */
+ /* The stack and stack size are not used on Windows
+ */
+#if (GKI_USE_DYNAMIC_BUFFERS == FALSE)
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ UINT8 bufpool0[(GKI_BUF0_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ UINT8 bufpool1[(GKI_BUF1_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ UINT8 bufpool2[(GKI_BUF2_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ UINT8 bufpool3[(GKI_BUF3_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX];
+#endif
+
+#endif
+
+ INT IsRunning;
+
+ /* Define the buffer pool management variables
+ */
+ FREE_QUEUE_T freeq[GKI_NUM_TOTAL_BUF_POOLS];
+
+ UINT16 pool_buf_size[GKI_NUM_TOTAL_BUF_POOLS];
+ UINT16 pool_max_count[GKI_NUM_TOTAL_BUF_POOLS];
+ UINT16 pool_additions[GKI_NUM_TOTAL_BUF_POOLS];
+
+ UINT16 ExceptionCnt;
+ EXCEPTION_T Exception[MAX_EXCEPTION];
+
+ /* Define the buffer pool access control variables */
+ UINT16 pool_access_mask;
+ UINT8 pool_list[GKI_NUM_TOTAL_BUF_POOLS]; /* buffer pools arranged in the order of size */
+ int curr_total_no_of_pools;
+} tGKI_CB;
+
+
+void gki_buffer_init(void);
+BOOLEAN gki_chk_buf_damage(void *p_buf);
+void *gki_reserve_os_memory (UINT32 size);
+void gki_release_os_memory (void *p_mem);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _BT_DYNAMIC_MEMORY
+extern tGKI_CB gki_cb;
+#else
+extern tGKI_CB *gp_gki_cb;
+#define gki_cb (*gp_gki_cb)
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/hcidefs.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/hcidefs.h.svn-base
new file mode 100755
index 0000000..ec2e802
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/hcidefs.h.svn-base
@@ -0,0 +1,1819 @@
+/*
+*
+* hcidefs.h
+*
+*
+*
+* Copyright (C) 2011 Broadcom Corporation.
+*
+*
+*
+* This software is licensed under the terms of the GNU General Public License,
+* version 2, as published by the Free Software Foundation (the "GPL"), and may
+* be copied, distributed, and modified under those terms.
+*
+* 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 GPL for more details.
+*
+*
+* A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+* or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA
+*
+*
+*/
+
+#ifndef HCIDEFS_H
+#define HCIDEFS_H
+
+#define HCI_PROTO_VERSION 0x01 /* Version for BT spec 1.1 */
+#define HCI_PROTO_VERSION_1_2 0x02 /* Version for BT spec 1.2 */
+#define HCI_PROTO_VERSION_2_0 0x03 /* Version for BT spec 2.0 */
+#define HCI_PROTO_VERSION_2_1 0x04 /* Version for BT spec 2.1 [Lisbon] */
+#define HCI_PROTO_REVISION 0x000C /* Current implementation version */
+/*
+** Definitions for HCI groups
+*/
+#define HCI_GRP_LINK_CONTROL_CMDS (0x01 << 10)
+#define HCI_GRP_LINK_POLICY_CMDS (0x02 << 10)
+#define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10)
+#define HCI_GRP_INFORMATIONAL_PARAMS (0x04 << 10)
+#define HCI_GRP_STATUS_PARAMS (0x05 << 10)
+#define HCI_GRP_TESTING_CMDS (0x06 << 10)
+#define HCI_GRP_L2CAP_CMDS (0x07 << 10)
+#define HCI_GRP_L2CAP_HCI_EVTS (0x08 << 10)
+
+#define HCI_GRP_VENDOR_SPECIFIC (0x3F << 10)
+
+/* Group occupies high 6 bits of the HCI command rest is opcode itself */
+#define HCI_OGF(p) (UINT8)((0xFC00 & (p)) >> 10)
+#define HCI_OCF(p) ( 0x3FF & (p))
+
+/*
+** Defentions for Link Control Commands
+*/
+/* Following opcode is used only in command complete event for flow control */
+#define HCI_COMMAND_NONE 0x0000
+
+/* Commands of HCI_GRP_LINK_CONTROL_CMDS group */
+#define HCI_INQUIRY (0x0001 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_INQUIRY_CANCEL (0x0002 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_PERIODIC_INQUIRY_MODE (0x0003 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_EXIT_PERIODIC_INQUIRY_MODE (0x0004 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CREATE_CONNECTION (0x0005 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_DISCONNECT (0x0006 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ADD_SCO_CONNECTION (0x0007 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CREATE_CONNECTION_CANCEL (0x0008 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ACCEPT_CONNECTION_REQUEST (0x0009 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REJECT_CONNECTION_REQUEST (0x000A | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_LINK_KEY_REQUEST_REPLY (0x000B | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_LINK_KEY_REQUEST_NEG_REPLY (0x000C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_PIN_CODE_REQUEST_REPLY (0x000D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_PIN_CODE_REQUEST_NEG_REPLY (0x000E | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CHANGE_CONN_PACKET_TYPE (0x000F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_AUTHENTICATION_REQUESTED (0x0011 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_SET_CONN_ENCRYPTION (0x0013 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CHANGE_CONN_LINK_KEY (0x0015 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_MASTER_LINK_KEY (0x0017 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RMT_NAME_REQUEST (0x0019 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RMT_NAME_REQUEST_CANCEL (0x001A | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_FEATURES (0x001B | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_EXT_FEATURES (0x001C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_VERSION_INFO (0x001D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_CLOCK_OFFSET (0x001F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_LMP_HANDLE (0x0020 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_SETUP_ESCO_CONNECTION (0x0028 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ACCEPT_ESCO_CONNECTION (0x0029 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REJECT_ESCO_CONNECTION (0x002A | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_IO_CAPABILITY_RESPONSE (0x002B | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_CONF_REQUEST_REPLY (0x002C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_CONF_VALUE_NEG_REPLY (0x002D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_PASSKEY_REQ_REPLY (0x002E | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_PASSKEY_REQ_NEG_REPLY (0x002F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REM_OOB_DATA_REQ_REPLY (0x0030 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REM_OOB_DATA_REQ_NEG_REPLY (0x0033 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_IO_CAP_REQ_NEG_REPLY (0x0034 | HCI_GRP_LINK_CONTROL_CMDS)
+
+#define HCI_LINK_CTRL_CMDS_FIRST HCI_INQUIRY
+#define HCI_LINK_CTRL_CMDS_LAST HCI_IO_CAP_REQ_NEG_REPLY
+
+/* Commands of HCI_GRP_LINK_POLICY_CMDS */
+#define HCI_HOLD_MODE (0x0001 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_SNIFF_MODE (0x0003 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_EXIT_SNIFF_MODE (0x0004 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_PARK_MODE (0x0005 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_EXIT_PARK_MODE (0x0006 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_QOS_SETUP (0x0007 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_ROLE_DISCOVERY (0x0009 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_SWITCH_ROLE (0x000B | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_READ_POLICY_SETTINGS (0x000C | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_WRITE_POLICY_SETTINGS (0x000D | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_READ_DEF_POLICY_SETTINGS (0x000E | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_WRITE_DEF_POLICY_SETTINGS (0x000F | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_FLOW_SPECIFICATION (0x0010 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_SNIFF_SUB_RATE (0x0011 | HCI_GRP_LINK_POLICY_CMDS)
+
+#define HCI_LINK_POLICY_CMDS_FIRST HCI_HOLD_MODE
+#define HCI_LINK_POLICY_CMDS_LAST HCI_SNIFF_SUB_RATE
+
+
+/* Commands of HCI_GRP_HOST_CONT_BASEBAND_CMDS */
+#define HCI_SET_EVENT_MASK (0x0001 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_EVENT_FILTER (0x0005 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_FLUSH (0x0008 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PIN_TYPE (0x0009 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PIN_TYPE (0x000A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_CREATE_NEW_UNIT_KEY (0x000B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_STORED_LINK_KEY (0x000D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_STORED_LINK_KEY (0x0011 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_DELETE_STORED_LINK_KEY (0x0012 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_CHANGE_LOCAL_NAME (0x0013 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_LOCAL_NAME (0x0014 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_CONN_ACCEPT_TOUT (0x0015 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CONN_ACCEPT_TOUT (0x0016 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGE_TOUT (0x0017 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGE_TOUT (0x0018 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SCAN_ENABLE (0x0019 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SCAN_ENABLE (0x001A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_CFG (0x001B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_CFG (0x001C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_INQUIRYSCAN_CFG (0x001D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQUIRYSCAN_CFG (0x001E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_AUTHENTICATION_ENABLE (0x001F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_AUTHENTICATION_ENABLE (0x0020 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_ENCRYPTION_MODE (0x0021 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_ENCRYPTION_MODE (0x0022 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_CLASS_OF_DEVICE (0x0023 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CLASS_OF_DEVICE (0x0024 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_VOICE_SETTINGS (0x0025 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_VOICE_SETTINGS (0x0026 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_AUTO_FLUSH_TOUT (0x0027 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_AUTO_FLUSH_TOUT (0x0028 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_NUM_BCAST_REXMITS (0x0029 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_NUM_BCAST_REXMITS (0x002A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_HOLD_MODE_ACTIVITY (0x002B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_HOLD_MODE_ACTIVITY (0x002C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_TRANSMIT_POWER_LEVEL (0x002D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SCO_FLOW_CTRL_ENABLE (0x002E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SCO_FLOW_CTRL_ENABLE (0x002F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_HC_TO_HOST_FLOW_CTRL (0x0031 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_HOST_BUFFER_SIZE (0x0033 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_HOST_NUM_PACKETS_DONE (0x0035 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_LINK_SUPER_TOUT (0x0036 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_LINK_SUPER_TOUT (0x0037 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_NUM_SUPPORTED_IAC (0x0038 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_CURRENT_IAC_LAP (0x0039 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CURRENT_IAC_LAP (0x003A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_PERIOD_MODE (0x003B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_PERIOD_MODE (0x003C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_MODE (0x003D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_MODE (0x003E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_AFH_CHANNELS (0x003F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+#define HCI_READ_INQSCAN_TYPE (0x0042 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQSCAN_TYPE (0x0043 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_INQUIRY_MODE (0x0044 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQUIRY_MODE (0x0045 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_TYPE (0x0046 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_TYPE (0x0047 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_AFH_ASSESSMENT_MODE (0x0048 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_AFH_ASSESSMENT_MODE (0x0049 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_EXT_INQ_RESPONSE (0x0051 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_EXT_INQ_RESPONSE (0x0052 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_REFRESH_ENCRYPTION_KEY (0x0053 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SIMPLE_PAIRING_MODE (0x0055 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SIMPLE_PAIRING_MODE (0x0056 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_LOCAL_OOB_DATA (0x0057 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_INQ_TX_POWER_LEVEL (0x0058 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQ_TX_POWER_LEVEL (0x0059 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SEND_KEYPRESS_NOTIF (0x0060 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+#define HCI_ENHANCED_FLUSH (0x005F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+#define HCI_CONT_BASEBAND_CMDS_FIRST HCI_SET_EVENT_MASK
+#define HCI_CONT_BASEBAND_CMDS_LAST HCI_SEND_KEYPRESS_NOTIF
+
+
+/* Commands of HCI_GRP_INFORMATIONAL_PARAMS group */
+#define HCI_READ_LOCAL_VERSION_INFO (0x0001 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_SUPPORTED_CMDS (0x0002 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_FEATURES (0x0003 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_EXT_FEATURES (0x0004 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_BUFFER_SIZE (0x0005 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_COUNTRY_CODE (0x0007 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_BD_ADDR (0x0009 | HCI_GRP_INFORMATIONAL_PARAMS)
+
+#define HCI_INFORMATIONAL_CMDS_FIRST HCI_READ_LOCAL_VERSION_INFO
+#define HCI_INFORMATIONAL_CMDS_LAST HCI_READ_BD_ADDR
+
+
+/* Commands of HCI_GRP_STATUS_PARAMS group */
+#define HCI_READ_FAILED_CONTACT_COUNT (0x0001 | HCI_GRP_STATUS_PARAMS)
+#define HCI_RESET_FAILED_CONTACT_COUNT (0x0002 | HCI_GRP_STATUS_PARAMS)
+#define HCI_GET_LINK_QUALITY (0x0003 | HCI_GRP_STATUS_PARAMS)
+#define HCI_READ_RSSI (0x0005 | HCI_GRP_STATUS_PARAMS)
+#define HCI_READ_AFH_CH_MAP (0x0006 | HCI_GRP_STATUS_PARAMS)
+#define HCI_READ_CLOCK (0x0007 | HCI_GRP_STATUS_PARAMS)
+
+#define HCI_STATUS_PARAMS_CMDS_FIRST HCI_READ_FAILED_CONTACT_COUNT
+#define HCI_STATUS_PARAMS_CMDS_LAST HCI_READ_CLOCK
+
+/* Commands of HCI_GRP_TESTING_CMDS group */
+#define HCI_READ_LOOPBACK_MODE (0x0001 | HCI_GRP_TESTING_CMDS)
+#define HCI_WRITE_LOOPBACK_MODE (0x0002 | HCI_GRP_TESTING_CMDS)
+#define HCI_ENABLE_DEV_UNDER_TEST_MODE (0x0003 | HCI_GRP_TESTING_CMDS)
+#define HCI_WRITE_SIMP_PAIR_DEBUG_MODE (0x0004 | HCI_GRP_TESTING_CMDS)
+
+#define HCI_TESTING_CMDS_FIRST HCI_READ_LOOPBACK_MODE
+#define HCI_TESTING_CMDS_LAST HCI_WRITE_SIMP_PAIR_DEBUG_MODE
+
+#define HCI_VENDOR_CMDS_FIRST 0x0001
+#define HCI_VENDOR_CMDS_LAST 0xFFFF
+
+
+/* Vendor specific commands for BRCM chipset */
+#define HCI_BRCM_UPDATE_BAUD_RATE_ENCODED_LENGTH 0x02
+#define HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH 0x06
+#define HCI_BRCM_WRITE_SLEEP_MODE_LENGTH 10
+#define HCI_BRCM_FM_OPCODE (0x0015 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_UPDATE_BAUDRATE_CMD (0x0018 | HCI_GRP_VENDOR_SPECIFIC) /* set baudrate of BCM2035 */
+#define HCI_BRCM_WRITE_SLEEP_MODE (0x0027 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_READ_SLEEP_MODE (0x0028 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_H4IBSS_CMD (0x0029 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_DOWNLOAD_MINI_DRV (0x002E | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_READ_USER_DEFINED_NVRAM (0x0033 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_ENABLE_RADIO (0x0034 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_READ_DIAGNOSTIC_VALUE (0x0035 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_GET_HID_DEVICE_LIST (0x0036 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_ADD_HID_DEVICE (0x0037 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_WRITE_HID_DEVICE_NVRAM (0x0038 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_DELETE_HID_DEVICE (0x0039 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_ENABLE_USB_HID_EMULATION (0x003B | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_BTW_STARTUP (0x0053 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_SET_ACL_PRIORITY (0x0057 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_WRITE_RAM (0x004C | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_LAUNCH_RAM (0x004E | HCI_GRP_VENDOR_SPECIFIC)
+
+/* Dual Stack */
+#define HCI_BRCM_PAUSE_TRANSPORT (0x007A | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_TRANSPORT_RESUME (0x007B | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_TRANSPORT_ERROR_EVT 0x0C
+
+/* Parameter information for HCI_BRCM_SET_ACL_PRIORITY */
+#define HCI_BRCM_ACL_PRIORITY_PARAM_SIZE 3
+#define HCI_BRCM_ACL_PRIORITY_LOW 0x00
+#define HCI_BRCM_ACL_PRIORITY_HIGH 0xFF
+
+#define HCI_BRCM_UPDATE_BAUD_RATE_ENCODED_LENGTH 0x02
+#define HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH 0x06
+#define HCI_BRCM_WRITE_SLEEP_MODE_LENGTH 10
+#define HCI_BRCM_PAUSE_TRANSPORT_LENGTH 6
+
+/* Broadcom-specific SCO routing */
+#define HCI_BRCM_Write_SCO_PCM_Int_Params (0x001c | HCI_GRP_VENDOR_SPECIFIC)
+#define BRCM_SCO_PCM_Int_Params_ROUTING_PCM 0
+#define BRCM_SCO_PCM_Int_Params_ROUTING_TRANSPORT 1
+
+#define HCI_BRCM_SYNC_PACKET_TYPE (0x006B | HCI_GRP_VENDOR_SPECIFIC)
+
+#define HCI_BRCM_UIPC_OVER_HCI (0x008B | HCI_GRP_VENDOR_SPECIFIC)
+
+/*
+** Definitions for HCI Events
+*/
+#define HCI_INQUIRY_COMP_EVT 0x01
+#define HCI_INQUIRY_RESULT_EVT 0x02
+#define HCI_CONNECTION_COMP_EVT 0x03
+#define HCI_CONNECTION_REQUEST_EVT 0x04
+#define HCI_DISCONNECTION_COMP_EVT 0x05
+#define HCI_AUTHENTICATION_COMP_EVT 0x06
+#define HCI_RMT_NAME_REQUEST_COMP_EVT 0x07
+#define HCI_ENCRYPTION_CHANGE_EVT 0x08
+#define HCI_CHANGE_CONN_LINK_KEY_EVT 0x09
+#define HCI_MASTER_LINK_KEY_COMP_EVT 0x0A
+#define HCI_READ_RMT_FEATURES_COMP_EVT 0x0B
+#define HCI_READ_RMT_VERSION_COMP_EVT 0x0C
+#define HCI_QOS_SETUP_COMP_EVT 0x0D
+#define HCI_COMMAND_COMPLETE_EVT 0x0E
+#define HCI_COMMAND_STATUS_EVT 0x0F
+#define HCI_HARDWARE_ERROR_EVT 0x10
+#define HCI_FLUSH_OCCURED_EVT 0x11
+#define HCI_ROLE_CHANGE_EVT 0x12
+#define HCI_NUM_COMPL_DATA_PKTS_EVT 0x13
+#define HCI_MODE_CHANGE_EVT 0x14
+#define HCI_RETURN_LINK_KEYS_EVT 0x15
+#define HCI_PIN_CODE_REQUEST_EVT 0x16
+#define HCI_LINK_KEY_REQUEST_EVT 0x17
+#define HCI_LINK_KEY_NOTIFICATION_EVT 0x18
+#define HCI_LOOPBACK_COMMAND_EVT 0x19
+#define HCI_DATA_BUF_OVERFLOW_EVT 0x1A
+#define HCI_MAX_SLOTS_CHANGED_EVT 0x1B
+#define HCI_READ_CLOCK_OFF_COMP_EVT 0x1C
+#define HCI_CONN_PKT_TYPE_CHANGE_EVT 0x1D
+#define HCI_QOS_VIOLATION_EVT 0x1E
+#define HCI_PAGE_SCAN_MODE_CHANGE_EVT 0x1F
+#define HCI_PAGE_SCAN_REP_MODE_CHNG_EVT 0x20
+#define HCI_FLOW_SPECIFICATION_COMP_EVT 0x21
+#define HCI_INQUIRY_RSSI_RESULT_EVT 0x22
+#define HCI_READ_RMT_EXT_FEATURES_COMP_EVT 0x23
+#define HCI_ESCO_CONNECTION_COMP_EVT 0x2C
+#define HCI_ESCO_CONNECTION_CHANGED_EVT 0x2D
+#define HCI_SNIFF_SUB_RATE_EVT 0x2E
+#define HCI_EXTENDED_INQUIRY_RESULT_EVT 0x2F
+#define HCI_ENCRYPTION_KEY_REFRESH_COMP_EVT 0x30
+#define HCI_IO_CAPABILITY_REQUEST_EVT 0x31
+#define HCI_IO_CAPABILITY_RESPONSE_EVT 0x32
+#define HCI_USER_CONFIRMATION_REQUEST_EVT 0x33
+#define HCI_USER_PASSKEY_REQUEST_EVT 0x34
+#define HCI_REMOTE_OOB_DATA_REQUEST_EVT 0x35
+#define HCI_SIMPLE_PAIRING_COMPLETE_EVT 0x36
+#define HCI_LINK_SUPER_TOUT_CHANGED_EVT 0x38
+#define HCI_ENHANCED_FLUSH_COMPLETE_EVT 0x39
+#define HCI_USER_PASSKEY_NOTIFY_EVT 0x3B
+#define HCI_KEYPRESS_NOTIFY_EVT 0x3C
+#define HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT 0x3D
+
+#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT
+#define HCI_EVENT_RSP_LAST HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT
+
+#define HCI_BRCM_H4IBSS_EVT 0xEF /* Vendor specific events for H4IBSS */
+#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */
+#define HCI_NAP_TRACE_EVT 0xFF /* was define 0xFE, 0xFD, change to 0xFF
+ because conflict w/ TCI_EVT and per
+ specification compliant */
+
+/*
+** Defentions for HCI Error Codes that are past in the events
+*/
+#define HCI_SUCCESS 0x00
+#define HCI_PENDING 0x00
+#define HCI_ERR_ILLEGAL_COMMAND 0x01
+#define HCI_ERR_NO_CONNECTION 0x02
+#define HCI_ERR_HW_FAILURE 0x03
+#define HCI_ERR_PAGE_TIMEOUT 0x04
+#define HCI_ERR_AUTH_FAILURE 0x05
+#define HCI_ERR_KEY_MISSING 0x06
+#define HCI_ERR_MEMORY_FULL 0x07
+#define HCI_ERR_CONNECTION_TOUT 0x08
+#define HCI_ERR_MAX_NUM_OF_CONNECTIONS 0x09
+#define HCI_ERR_MAX_NUM_OF_SCOS 0x0A
+#define HCI_ERR_CONNECTION_EXISTS 0x0B
+#define HCI_ERR_COMMAND_DISALLOWED 0x0C
+#define HCI_ERR_HOST_REJECT_RESOURCES 0x0D
+#define HCI_ERR_HOST_REJECT_SECURITY 0x0E
+#define HCI_ERR_HOST_REJECT_DEVICE 0x0F
+#define HCI_ERR_HOST_TIMEOUT 0x10
+#define HCI_ERR_UNSUPPORTED_VALUE 0x11
+#define HCI_ERR_ILLEGAL_PARAMETER_FMT 0x12
+#define HCI_ERR_PEER_USER 0x13
+#define HCI_ERR_PEER_LOW_RESOURCES 0x14
+#define HCI_ERR_PEER_POWER_OFF 0x15
+#define HCI_ERR_CONN_CAUSE_LOCAL_HOST 0x16
+#define HCI_ERR_REPEATED_ATTEMPTS 0x17
+#define HCI_ERR_PAIRING_NOT_ALLOWED 0x18
+#define HCI_ERR_UNKNOWN_LMP_PDU 0x19
+#define HCI_ERR_UNSUPPORTED_REM_FEATURE 0x1A
+#define HCI_ERR_SCO_OFFSET_REJECTED 0x1B
+#define HCI_ERR_SCO_INTERVAL_REJECTED 0x1C
+#define HCI_ERR_SCO_AIR_MODE 0x1D
+#define HCI_ERR_INVALID_LMP_PARAM 0x1E
+#define HCI_ERR_UNSPECIFIED 0x1F
+#define HCI_ERR_UNSUPPORTED_LMP_FEATURE 0x20
+#define HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21
+#define HCI_ERR_LMP_RESPONSE_TIMEOUT 0x22
+#define HCI_ERR_LMP_ERR_TRANS_COLLISION 0x23
+#define HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24
+#define HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE 0x25
+#define HCI_ERR_UNIT_KEY_USED 0x26
+#define HCI_ERR_QOS_NOT_SUPPORTED 0x27
+#define HCI_ERR_INSTANT_PASSED 0x28
+#define HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED 0x29
+#define HCI_ERR_DIFF_TRANSACTION_COLLISION 0x2A
+#define HCI_ERR_UNDEFINED_0x2B 0x2B
+#define HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2C
+#define HCI_ERR_QOS_REJECTED 0x2D
+#define HCI_ERR_CHAN_CLASSIF_NOT_SUPPORTED 0x2E
+#define HCI_ERR_INSUFFCIENT_SECURITY 0x2F
+#define HCI_ERR_PARAM_OUT_OF_RANGE 0x30
+#define HCI_ERR_UNDEFINED_0x31 0x31
+#define HCI_ERR_ROLE_SWITCH_PENDING 0x32
+#define HCI_ERR_UNDEFINED_0x33 0x33
+#define HCI_ERR_RESERVED_SLOT_VIOLATION 0x34
+#define HCI_ERR_ROLE_SWITCH_FAILED 0x35
+#define HCI_ERR_INQ_RSP_DATA_TOO_LARGE 0x36
+#define HCI_ERR_SIMPLE_PAIRING_NOT_SUPPORTED 0x37
+#define HCI_ERR_HOST_BUSY_PAIRING 0x38
+
+#define HCI_ERR_MAX_ERR 0x38
+
+/*
+** Definitions for HCI enable event
+*/
+#define HCI_INQUIRY_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000001)
+#define HCI_INQUIRY_RESULT_EV(p) (*((UINT32 *)(p)) & 0x00000002)
+#define HCI_CONNECTION_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000004)
+#define HCI_CONNECTION_REQUEST_EV(p) (*((UINT32 *)(p)) & 0x00000008)
+#define HCI_DISCONNECTION_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000010)
+#define HCI_AUTHENTICATION_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000020)
+#define HCI_RMT_NAME_REQUEST_COMPL_EV(p) (*((UINT32 *)(p)) & 0x00000040)
+#define HCI_CHANGE_CONN_ENCRPT_ENABLE_EV(p) (*((UINT32 *)(p)) & 0x00000080)
+#define HCI_CHANGE_CONN_LINK_KEY_EV(p) (*((UINT32 *)(p)) & 0x00000100)
+#define HCI_MASTER_LINK_KEY_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000200)
+#define HCI_READ_RMT_FEATURES_COMPL_EV(p) (*((UINT32 *)(p)) & 0x00000400)
+#define HCI_READ_RMT_VERSION_COMPL_EV(p) (*((UINT32 *)(p)) & 0x00000800)
+#define HCI_QOS_SETUP_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00001000)
+#define HCI_COMMAND_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00002000)
+#define HCI_COMMAND_STATUS_EV(p) (*((UINT32 *)(p)) & 0x00004000)
+#define HCI_HARDWARE_ERROR_EV(p) (*((UINT32 *)(p)) & 0x00008000)
+#define HCI_FLASH_OCCURED_EV(p) (*((UINT32 *)(p)) & 0x00010000)
+#define HCI_ROLE_CHANGE_EV(p) (*((UINT32 *)(p)) & 0x00020000)
+#define HCI_NUM_COMPLETED_PKTS_EV(p) (*((UINT32 *)(p)) & 0x00040000)
+#define HCI_MODE_CHANGE_EV(p) (*((UINT32 *)(p)) & 0x00080000)
+#define HCI_RETURN_LINK_KEYS_EV(p) (*((UINT32 *)(p)) & 0x00100000)
+#define HCI_PIN_CODE_REQUEST_EV(p) (*((UINT32 *)(p)) & 0x00200000)
+#define HCI_LINK_KEY_REQUEST_EV(p) (*((UINT32 *)(p)) & 0x00400000)
+#define HCI_LINK_KEY_NOTIFICATION_EV(p) (*((UINT32 *)(p)) & 0x00800000)
+#define HCI_LOOPBACK_COMMAND_EV(p) (*((UINT32 *)(p)) & 0x01000000)
+#define HCI_DATA_BUF_OVERFLOW_EV(p) (*((UINT32 *)(p)) & 0x02000000)
+#define HCI_MAX_SLOTS_CHANGE_EV(p) (*((UINT32 *)(p)) & 0x04000000)
+#define HCI_READ_CLOCK_OFFSET_COMP_EV(p) (*((UINT32 *)(p)) & 0x08000000)
+#define HCI_CONN_PKT_TYPE_CHANGED_EV(p) (*((UINT32 *)(p)) & 0x10000000)
+#define HCI_QOS_VIOLATION_EV(p) (*((UINT32 *)(p)) & 0x20000000)
+#define HCI_PAGE_SCAN_MODE_CHANGED_EV(p) (*((UINT32 *)(p)) & 0x40000000)
+#define HCI_PAGE_SCAN_REP_MODE_CHNG_EV(p) (*((UINT32 *)(p)) & 0x80000000)
+
+/* the default event mask for 2.1+EDR (Lisbon) does not include Lisbon events */
+#define HCI_DEFAULT_EVENT_MASK_0 0xFFFFFFFF
+#define HCI_DEFAULT_EVENT_MASK_1 0x00001FFF
+
+/* the event mask for 2.1+EDR include Lisbon events */
+#define HCI_LISBON_EVENT_MASK_0 0xFFFFFFFF
+#define HCI_LISBON_EVENT_MASK_1 0x1DBFFFFF
+#define HCI_LISBON_EVENT_MASK "\x0D\xBF\xFF\xFF\xFF\xFF\xFF\xFF"
+#define HCI_LISBON_EVENT_MASK_EXT "\x1D\xBF\xFF\xFF\xFF\xFF\xFF\xFF"
+/* 0x00001FFF FFFFFFFF Default - no Lisbon events
+ 0x00002000 00000000 Sniff Subrate Event
+ 0x00004000 00000000 Extended Inquiry Result Event
+ 0x00008000 00000000 Encryption Key Refresh Complete Event
+ 0x00010000 00000000 IO Capability Request Event
+ 0x00020000 00000000 IO Capability Response Event
+ 0x00040000 00000000 User Confirmation Request Event
+ 0x00080000 00000000 User Passkey Request Event
+ 0x00100000 00000000 Remote OOB Data Request Event
+ 0x00200000 00000000 Simple Pairing Complete Event
+ 0x00800000 00000000 Link Supervision Timeout Changed Event
+ 0x01000000 00000000 Enhanced Flush Complete Event
+ 0x04000000 00000000 User Passkey Notification Event
+ 0x08000000 00000000 Keypress Notification Event
+ 0x10000000 00000000 Remote Host Supported Features Notification Event
+ */
+
+/*
+** Definitions for packet type masks (BT1.2 and BT2.0 definitions)
+*/
+#define HCI_PKT_TYPES_MASK_NO_2_DH1 0x0002
+#define HCI_PKT_TYPES_MASK_NO_3_DH1 0x0004
+#define HCI_PKT_TYPES_MASK_DM1 0x0008
+#define HCI_PKT_TYPES_MASK_DH1 0x0010
+#define HCI_PKT_TYPES_MASK_HV1 0x0020
+#define HCI_PKT_TYPES_MASK_HV2 0x0040
+#define HCI_PKT_TYPES_MASK_HV3 0x0080
+#define HCI_PKT_TYPES_MASK_NO_2_DH3 0x0100
+#define HCI_PKT_TYPES_MASK_NO_3_DH3 0x0200
+#define HCI_PKT_TYPES_MASK_DM3 0x0400
+#define HCI_PKT_TYPES_MASK_DH3 0x0800
+#define HCI_PKT_TYPES_MASK_NO_2_DH5 0x1000
+#define HCI_PKT_TYPES_MASK_NO_3_DH5 0x2000
+#define HCI_PKT_TYPES_MASK_DM5 0x4000
+#define HCI_PKT_TYPES_MASK_DH5 0x8000
+
+/* Packet type should be one of valid but at least one should be specified */
+#define HCI_VALID_SCO_PKT_TYPE(t) (((((t) & ~(HCI_PKT_TYPES_MASK_HV1 \
+ | HCI_PKT_TYPES_MASK_HV2 \
+ | HCI_PKT_TYPES_MASK_HV3)) == 0)) \
+ && ((t) != 0))
+
+
+
+
+
+/* Packet type should not be invalid and at least one should be specified */
+#define HCI_VALID_ACL_PKT_TYPE(t) (((((t) & ~(HCI_PKT_TYPES_MASK_DM1 \
+ | HCI_PKT_TYPES_MASK_DH1 \
+ | HCI_PKT_TYPES_MASK_DM3 \
+ | HCI_PKT_TYPES_MASK_DH3 \
+ | HCI_PKT_TYPES_MASK_DM5 \
+ | HCI_PKT_TYPES_MASK_DH5 \
+ | HCI_PKT_TYPES_MASK_NO_2_DH1 \
+ | HCI_PKT_TYPES_MASK_NO_3_DH1 \
+ | HCI_PKT_TYPES_MASK_NO_2_DH3 \
+ | HCI_PKT_TYPES_MASK_NO_3_DH3 \
+ | HCI_PKT_TYPES_MASK_NO_2_DH5 \
+ | HCI_PKT_TYPES_MASK_NO_3_DH5 )) == 0)) \
+ && (((t) & (HCI_PKT_TYPES_MASK_DM1 \
+ | HCI_PKT_TYPES_MASK_DH1 \
+ | HCI_PKT_TYPES_MASK_DM3 \
+ | HCI_PKT_TYPES_MASK_DH3 \
+ | HCI_PKT_TYPES_MASK_DM5 \
+ | HCI_PKT_TYPES_MASK_DH5)) != 0))
+
+
+
+/*
+** Definitions for eSCO packet type masks (BT1.2 and BT2.0 definitions)
+*/
+#define HCI_ESCO_PKT_TYPES_MASK_HV1 0x0001
+#define HCI_ESCO_PKT_TYPES_MASK_HV2 0x0002
+#define HCI_ESCO_PKT_TYPES_MASK_HV3 0x0004
+#define HCI_ESCO_PKT_TYPES_MASK_EV3 0x0008
+#define HCI_ESCO_PKT_TYPES_MASK_EV4 0x0010
+#define HCI_ESCO_PKT_TYPES_MASK_EV5 0x0020
+#define HCI_ESCO_PKT_TYPES_MASK_NO_2_EV3 0x0040
+#define HCI_ESCO_PKT_TYPES_MASK_NO_3_EV3 0x0080
+#define HCI_ESCO_PKT_TYPES_MASK_NO_2_EV5 0x0100
+#define HCI_ESCO_PKT_TYPES_MASK_NO_3_EV5 0x0200
+
+/* Packet type should be one of valid but at least one should be specified for 1.2 */
+#define HCI_VALID_ESCO_PKT_TYPE(t) (((((t) & ~(HCI_ESCO_PKT_TYPES_MASK_EV3 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV4 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV5)) == 0)) \
+ && ((t) != 0))/* Packet type should be one of valid but at least one should be specified */
+
+#define HCI_VALID_ESCO_SCOPKT_TYPE(t) (((((t) & ~(HCI_ESCO_PKT_TYPES_MASK_HV1 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV2 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV3)) == 0)) \
+ && ((t) != 0))
+
+#define HCI_VALID_SCO_ALL_PKT_TYPE(t) (((((t) & ~(HCI_ESCO_PKT_TYPES_MASK_HV1 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV2 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV3 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV3 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV4 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV5)) == 0)) \
+ && ((t) != 0))
+
+/*
+** Define parameters to allow role switch during create connection
+*/
+#define HCI_CR_CONN_NOT_ALLOW_SWITCH 0x00
+#define HCI_CR_CONN_ALLOW_SWITCH 0x01
+
+/*
+** Hold Mode command destination
+*/
+#define HOLD_MODE_DEST_LOCAL_DEVICE 0x00
+#define HOLD_MODE_DEST_RMT_DEVICE 0x01
+
+/*
+** Defentions for different HCI parameters
+*/
+#define HCI_PER_INQ_MIN_MAX_PERIOD 0x0003
+#define HCI_PER_INQ_MAX_MAX_PERIOD 0xFFFF
+#define HCI_PER_INQ_MIN_MIN_PERIOD 0x0002
+#define HCI_PER_INQ_MAX_MIN_PERIOD 0xFFFE
+
+#define HCI_MAX_INQUIRY_LENGTH 0x30
+
+#define HCI_MIN_INQ_LAP 0x9E8B00
+#define HCI_MAX_INQ_LAP 0x9E8B3F
+
+/* HCI role defenitions */
+#define HCI_ROLE_MASTER 0x00
+#define HCI_ROLE_SLAVE 0x01
+#define HCI_ROLE_UNKNOWN 0xff
+
+/* HCI mode defenitions */
+#define HCI_MODE_ACTIVE 0x00
+#define HCI_MODE_HOLD 0x01
+#define HCI_MODE_SNIFF 0x02
+#define HCI_MODE_PARK 0x03
+
+/* Define Packet types as requested by the Host */
+#define HCI_ACL_PKT_TYPE_NONE 0x0000
+#define HCI_ACL_PKT_TYPE_DM1 0x0008
+#define HCI_ACL_PKT_TYPE_DH1 0x0010
+#define HCI_ACL_PKT_TYPE_AUX1 0x0200
+#define HCI_ACL_PKT_TYPE_DM3 0x0400
+#define HCI_ACL_PKT_TYPE_DH3 0x0800
+#define HCI_ACL_PKT_TYPE_DM5 0x4000
+#define HCI_ACL_PKT_TYPE_DH5 0x8000
+
+/* Define key type in the Master Link Key command */
+#define HCI_USE_SEMI_PERMANENT_KEY 0x00
+#define HCI_USE_TEMPORARY_KEY 0x01
+
+/* Page scan period modes */
+#define HCI_PAGE_SCAN_REP_MODE_R0 0x00
+#define HCI_PAGE_SCAN_REP_MODE_R1 0x01
+#define HCI_PAGE_SCAN_REP_MODE_R2 0x02
+
+/* Define limits for page scan repetition modes */
+#define HCI_PAGE_SCAN_R1_LIMIT 0x0800
+#define HCI_PAGE_SCAN_R2_LIMIT 0x1000
+
+/* Page scan period modes */
+#define HCI_PAGE_SCAN_PER_MODE_P0 0x00
+#define HCI_PAGE_SCAN_PER_MODE_P1 0x01
+#define HCI_PAGE_SCAN_PER_MODE_P2 0x02
+
+/* Page scan modes */
+#define HCI_MANDATARY_PAGE_SCAN_MODE 0x00
+#define HCI_OPTIONAL_PAGE_SCAN_MODE1 0x01
+#define HCI_OPTIONAL_PAGE_SCAN_MODE2 0x02
+#define HCI_OPTIONAL_PAGE_SCAN_MODE3 0x03
+
+/* Page and inquiry scan types */
+#define HCI_SCAN_TYPE_STANDARD 0x00
+#define HCI_SCAN_TYPE_INTERLACED 0x01 /* 1.2 devices or later */
+#define HCI_DEF_SCAN_TYPE HCI_SCAN_TYPE_STANDARD
+
+/* Definitions for quality of service service types */
+#define HCI_SERVICE_NO_TRAFFIC 0x00
+#define HCI_SERVICE_BEST_EFFORT 0x01
+#define HCI_SERVICE_GUARANTEED 0x02
+
+#define HCI_QOS_LATENCY_DO_NOT_CARE 0xFFFFFFFF
+#define HCI_QOS_DELAY_DO_NOT_CARE 0xFFFFFFFF
+
+/* Definitions for Flow Specification */
+#define HCI_FLOW_SPEC_LATENCY_DO_NOT_CARE 0xFFFFFFFF
+
+/* Definitions for AFH Channel Map */
+#define HCI_AFH_CHANNEL_MAP_LEN 10
+
+/* Definitions for Extended Inquiry Response */
+#define HCI_EXT_INQ_RESPONSE_LEN 240
+#define HCI_EIR_FLAGS_TYPE 0x01
+#define HCI_EIR_MORE_16BITS_UUID_TYPE 0x02
+#define HCI_EIR_COMPLETE_16BITS_UUID_TYPE 0x03
+#define HCI_EIR_MORE_32BITS_UUID_TYPE 0x04
+#define HCI_EIR_COMPLETE_32BITS_UUID_TYPE 0x05
+#define HCI_EIR_MORE_128BITS_UUID_TYPE 0x06
+#define HCI_EIR_COMPLETE_128BITS_UUID_TYPE 0x07
+#define HCI_EIR_SHORTENED_LOCAL_NAME_TYPE 0x08
+#define HCI_EIR_COMPLETE_LOCAL_NAME_TYPE 0x09
+#define HCI_EIR_TX_POWER_LEVEL_TYPE 0x0A
+#define HCI_EIR_MANUFACTURER_SPECIFIC_TYPE 0xFF
+
+/* Definitions for Write Simple Pairing Mode */
+#define HCI_SP_MODE_UNDEFINED 0x00
+#define HCI_SP_MODE_ENABLED 0x01
+
+/* Definitions for Write Simple Pairing Debug Mode */
+#define HCI_SPD_MODE_DISABLED 0x00
+#define HCI_SPD_MODE_ENABLED 0x01
+
+/* Definitions for IO Capability Response/Command */
+#define HCI_IO_CAP_DISPLAY_ONLY 0x00
+#define HCI_IO_CAP_DISPLAY_YESNO 0x01
+#define HCI_IO_CAP_KEYBOARD_ONLY 0x02
+#define HCI_IO_CAP_NO_IO 0x03
+
+#define HCI_OOB_AUTH_DATA_NOT_PRESENT 0x00
+#define HCI_OOB_REM_AUTH_DATA_PRESENT 0x01
+
+#define HCI_MITM_PROTECT_NOT_REQUIRED 0x00
+#define HCI_MITM_PROTECT_REQUIRED 0x01
+
+
+/* Policy settings status */
+#define HCI_DISABLE_ALL_LM_MODES 0x0000
+#define HCI_ENABLE_MASTER_SLAVE_SWITCH 0x0001
+#define HCI_ENABLE_HOLD_MODE 0x0002
+#define HCI_ENABLE_SNIFF_MODE 0x0004
+#define HCI_ENABLE_PARK_MODE 0x0008
+
+/* By default allow switch, because host can not allow that */
+/* that until he created the connection */
+#define HCI_DEFAULT_POLICY_SETTINGS HCI_DISABLE_ALL_LM_MODES
+
+/* Filters that are sent in set filter command */
+#define HCI_FILTER_TYPE_CLEAR_ALL 0x00
+#define HCI_FILTER_INQUIRY_RESULT 0x01
+#define HCI_FILTER_CONNECTION_SETUP 0x02
+
+#define HCI_FILTER_COND_NEW_DEVICE 0x00
+#define HCI_FILTER_COND_DEVICE_CLASS 0x01
+#define HCI_FILTER_COND_BD_ADDR 0x02
+
+#define HCI_DO_NOT_AUTO_ACCEPT_CONNECT 1
+#define HCI_DO_AUTO_ACCEPT_CONNECT 2 /* role switch disabled */
+#define HCI_DO_AUTO_ACCEPT_CONNECT_RS 3 /* role switch enabled (1.1 errata 1115) */
+
+/* Auto accept flags */
+#define HCI_AUTO_ACCEPT_OFF 0x00
+#define HCI_AUTO_ACCEPT_ACL_CONNECTIONS 0x01
+#define HCI_AUTO_ACCEPT_SCO_CONNECTIONS 0x02
+
+/* PIN type */
+#define HCI_PIN_TYPE_VARIABLE 0
+#define HCI_PIN_TYPE_FIXED 1
+
+/* Loopback Modes */
+#define HCI_LOOPBACK_MODE_DISABLED 0
+#define HCI_LOOPBACK_MODE_LOCAL 1
+#define HCI_LOOPBACK_MODE_REMOTE 2
+
+#define SLOTS_PER_10MS 16 /* 0.625 ms slots in a 10 ms tick */
+
+/* Maximum connection accept timeout in 0.625msec */
+#define HCI_MAX_CONN_ACCEPT_TOUT 0xB540 /* 29 sec */
+#define HCI_DEF_CONN_ACCEPT_TOUT 0x1FA0 /* 5 sec */
+
+/* Page timeout is used in LC only and LC is counting down slots not using OS */
+#define HCI_DEFAULT_PAGE_TOUT 0x2000 /* 5.12 sec (in slots) */
+
+/* Scan enable flags */
+#define HCI_NO_SCAN_ENABLED 0x00
+#define HCI_INQUIRY_SCAN_ENABLED 0x01
+#define HCI_PAGE_SCAN_ENABLED 0x02
+
+/* Pagescan timer definitions in 0.625 ms */
+#define HCI_MIN_PAGESCAN_INTERVAL 0x12 /* 11.25 ms */
+#define HCI_MAX_PAGESCAN_INTERVAL 0x1000 /* 2.56 sec */
+#define HCI_DEF_PAGESCAN_INTERVAL 0x0800 /* 1.28 sec */
+
+/* Parameter for pagescan window is passed to LC and is kept in slots */
+#define HCI_MIN_PAGESCAN_WINDOW 0x12 /* 11.25 ms */
+#define HCI_MAX_PAGESCAN_WINDOW 0x1000 /* 2.56 sec */
+#define HCI_DEF_PAGESCAN_WINDOW 0x12 /* 11.25 ms */
+
+/* Inquiryscan timer definitions in 0.625 ms */
+#define HCI_MIN_INQUIRYSCAN_INTERVAL 0x12 /* 11.25 ms */
+#define HCI_MAX_INQUIRYSCAN_INTERVAL 0x1000 /* 2.56 sec */
+#define HCI_DEF_INQUIRYSCAN_INTERVAL 0x0800 /* 1.28 sec */
+
+/* Parameter for inquiryscan window is passed to LC and is kept in slots */
+#define HCI_MIN_INQUIRYSCAN_WINDOW 0x12 /* 11.25 ms */
+#define HCI_MAX_INQUIRYSCAN_WINDOW 0x1000 /* 2.56 sec */
+#define HCI_DEF_INQUIRYSCAN_WINDOW 0x12 /* 11.25 ms */
+
+/* Encryption modes */
+#define HCI_ENCRYPT_MODE_DISABLED 0x00
+#define HCI_ENCRYPT_MODE_POINT_TO_POINT 0x01
+#define HCI_ENCRYPT_MODE_ALL 0x02
+
+/* Voice settings */
+#define HCI_INP_CODING_LINEAR 0x0000 /* 0000000000 */
+#define HCI_INP_CODING_U_LAW 0x0100 /* 0100000000 */
+#define HCI_INP_CODING_A_LAW 0x0200 /* 1000000000 */
+#define HCI_INP_CODING_MASK 0x0300 /* 1100000000 */
+
+#define HCI_INP_DATA_FMT_1S_COMPLEMENT 0x0000 /* 0000000000 */
+#define HCI_INP_DATA_FMT_2S_COMPLEMENT 0x0040 /* 0001000000 */
+#define HCI_INP_DATA_FMT_SIGN_MAGNITUDE 0x0080 /* 0010000000 */
+#define HCI_INP_DATA_FMT_UNSIGNED 0x00c0 /* 0011000000 */
+#define HCI_INP_DATA_FMT_MASK 0x00c0 /* 0011000000 */
+
+#define HCI_INP_SAMPLE_SIZE_8BIT 0x0000 /* 0000000000 */
+#define HCI_INP_SAMPLE_SIZE_16BIT 0x0020 /* 0000100000 */
+#define HCI_INP_SAMPLE_SIZE_MASK 0x0020 /* 0000100000 */
+
+#define HCI_INP_LINEAR_PCM_BIT_POS_MASK 0x001c /* 0000011100 */
+#define HCI_INP_LINEAR_PCM_BIT_POS_OFFS 2
+
+#define HCI_AIR_CODING_FORMAT_CVSD 0x0000 /* 0000000000 */
+#define HCI_AIR_CODING_FORMAT_U_LAW 0x0001 /* 0000000001 */
+#define HCI_AIR_CODING_FORMAT_A_LAW 0x0002 /* 0000000010 */
+#define HCI_AIR_CODING_FORMAT_TRANSPNT 0x0003 /* 0000000011 */
+#define HCI_AIR_CODING_FORMAT_MASK 0x0003 /* 0000000011 */
+
+/* default 0001100000 */
+#define HCI_DEFAULT_VOICE_SETTINGS (HCI_INP_CODING_LINEAR \
+ | HCI_INP_DATA_FMT_2S_COMPLEMENT \
+ | HCI_INP_SAMPLE_SIZE_16BIT \
+ | HCI_AIR_CODING_FORMAT_CVSD)
+
+#define HCI_CVSD_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_CVSD)
+#define HCI_U_LAW_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_U_LAW)
+#define HCI_A_LAW_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_A_LAW)
+#define HCI_TRANSPNT_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_TRANSPNT)
+
+/* Retransmit timer definitions in 0.625 */
+#define HCI_MAX_AUTO_FLUSH_TOUT 0x07FF
+#define HCI_DEFAULT_AUTO_FLUSH_TOUT 0 /* No auto flush */
+
+/* Broadcast retransmitions */
+#define HCI_DEFAULT_NUM_BCAST_RETRAN 1
+
+/* Define broadcast data types as passed in the hci data packet */
+#define HCI_DATA_POINT_TO_POINT 0x00
+#define HCI_DATA_ACTIVE_BCAST 0x01
+#define HCI_DATA_PICONET_BCAST 0x02
+
+/* Hold mode activity */
+#define HCI_MAINTAIN_CUR_POWER_STATE 0x00
+#define HCI_SUSPEND_PAGE_SCAN 0x01
+#define HCI_SUSPEND_INQUIRY_SCAN 0x02
+#define HCI_SUSPEND_PERIODIC_INQUIRIES 0x04
+
+/* Default Link Supervision timeoout */
+#define HCI_DEFAULT_INACT_TOUT 0x7D00 /* 20 seconds */
+
+/* Read transmit power level parameter */
+#define HCI_READ_CURRENT 0x00
+#define HCI_READ_MAXIMUM 0x01
+
+/* Link types for connection complete event */
+#define HCI_LINK_TYPE_SCO 0x00
+#define HCI_LINK_TYPE_ACL 0x01
+#define HCI_LINK_TYPE_ESCO 0x02
+
+/* Link Key Notification Event (Key Type) definitions */
+#define HCI_LKEY_TYPE_COMBINATION 0x00
+#define HCI_LKEY_TYPE_LOCAL_UNIT 0x01
+#define HCI_LKEY_TYPE_REMOTE_UNIT 0x02
+#define HCI_LKEY_TYPE_DEBUG_COMB 0x03
+#define HCI_LKEY_TYPE_UNAUTH_COMB 0x04
+#define HCI_LKEY_TYPE_AUTH_COMB 0x05
+#define HCI_LKEY_TYPE_CHANGED_COMB 0x06
+
+/* Read Local Version HCI Version return values (Command Complete Event) */
+#define HCI_VERSION_1_0B 0x00
+#define HCI_VERSION_1_1 0x01
+
+/* Define an invalid value for a handle */
+#define HCI_INVALID_HANDLE 0xFFFF
+
+/* Define max amount of data in the HCI command */
+#define HCI_COMMAND_SIZE 255
+
+/* Define the preamble length for all HCI Commands.
+** This is 2-bytes for opcode and 1 byte for length
+*/
+#define HCIC_PREAMBLE_SIZE 3
+
+/* Define the preamble length for all HCI Events
+** This is 1-byte for opcode and 1 byte for length
+*/
+#define HCIE_PREAMBLE_SIZE 2
+#define HCI_SCO_PREAMBLE_SIZE 3
+#define HCI_DATA_PREAMBLE_SIZE 4
+
+
+/* HCI message type definitions (for H4 messages) */
+#define HCIT_TYPE_COMMAND 1
+#define HCIT_TYPE_ACL_DATA 2
+#define HCIT_TYPE_SCO_DATA 3
+#define HCIT_TYPE_EVENT 4
+#define HCIT_TYPE_LM_DIAG 7
+
+#define HCIT_LM_DIAG_LENGTH 63
+
+/* Define values for LMP Test Control parameters
+** Test Scenario, Hopping Mode, Power Control Mode
+*/
+#define LMP_TESTCTL_TESTSC_PAUSE 0
+#define LMP_TESTCTL_TESTSC_TXTEST_0 1
+#define LMP_TESTCTL_TESTSC_TXTEST_1 2
+#define LMP_TESTCTL_TESTSC_TXTEST_1010 3
+#define LMP_TESTCTL_TESTSC_PSRND_BITSEQ 4
+#define LMP_TESTCTL_TESTSC_CLOSEDLB_ACL 5
+#define LMP_TESTCTL_TESTSC_CLOSEDLB_SCO 6
+#define LMP_TESTCTL_TESTSC_ACL_NOWHIT 7
+#define LMP_TESTCTL_TESTSC_SCO_NOWHIT 8
+#define LMP_TESTCTL_TESTSC_TXTEST_11110000 9
+#define LMP_TESTCTL_TESTSC_EXITTESTMODE 255
+
+#define LMP_TESTCTL_HOPMOD_RXTX1FREQ 0
+#define LMP_TESTCTL_HOPMOD_HOP_EURUSA 1
+#define LMP_TESTCTL_HOPMOD_HOP_JAPAN 2
+#define LMP_TESTCTL_HOPMOD_HOP_FRANCE 3
+#define LMP_TESTCTL_HOPMOD_HOP_SPAIN 4
+#define LMP_TESTCTL_HOPMOD_REDUCED_HOP 5
+
+#define LMP_TESTCTL_POWCTL_FIXEDTX_OP 0
+#define LMP_TESTCTL_POWCTL_ADAPTIVE 1
+
+
+/*
+** Define company IDs (from Bluetooth Assigned Numbers v1.1, section 2.2)
+*/
+#define LMP_COMPID_ERICSSON 0
+#define LMP_COMPID_NOKIA 1
+#define LMP_COMPID_INTEL 2
+#define LMP_COMPID_IBM 3
+#define LMP_COMPID_TOSHIBA 4
+#define LMP_COMPID_3COM 5
+#define LMP_COMPID_MICROSOFT 6
+#define LMP_COMPID_LUCENT 7
+#define LMP_COMPID_MOTOROLA 8
+#define LMP_COMPID_INFINEON 9
+#define LMP_COMPID_CSR 10
+#define LMP_COMPID_SILICON_WAVE 11
+#define LMP_COMPID_DIGIANSWER 12
+#define LMP_COMPID_TEXAS_INSTRUMENTS 13
+#define LMP_COMPID_PARTHUS 14
+#define LMP_COMPID_BROADCOM 15
+#define LMP_COMPID_MITEL_SEMI 16
+#define LMP_COMPID_WIDCOMM 17
+#define LMP_COMPID_ZEEVO 18
+#define LMP_COMPID_ATMEL 19
+#define LMP_COMPID_MITSUBISHI 20
+#define LMP_COMPID_RTX_TELECOM 21
+#define LMP_COMPID_KC_TECH 22
+#define LMP_COMPID_NEWLOGIC 23
+#define LMP_COMPID_TRANSILICA 24
+#define LMP_COMPID_ROHDE_SCHWARZ 25
+#define LMP_COMPID_TTPCOM 26
+#define LMP_COMPID_SIGNIA 27
+#define LMP_COMPID_CONEXANT 28
+#define LMP_COMPID_QUALCOMM 29
+#define LMP_COMPID_INVENTEL 30
+#define LMP_COMPID_AVM 31
+#define LMP_COMPID_BANDSPEED 32
+#define LMP_COMPID_MANSELLA 33
+#define LMP_COMPID_NEC_CORP 34
+#define LMP_COMPID_WAVEPLUS 35
+#define LMP_COMPID_ALCATEL 36
+#define LMP_COMPID_PHILIPS 37
+#define LMP_COMPID_C_TECHNOLOGIES 38
+#define LMP_COMPID_OPEN_INTERFACE 39
+#define LMP_COMPID_RF_MICRO 40
+#define LMP_COMPID_HITACHI 41
+#define LMP_COMPID_SYMBOL_TECH 42
+#define LMP_COMPID_TENOVIS 43
+#define LMP_COMPID_MACRONIX 44
+#define LMP_COMPID_GCT_SEMI 45
+#define LMP_COMPID_NORWOOD_SYSTEMS 46
+#define LMP_COMPID_MEWTEL_TECH 47
+#define LMP_COMPID_STM 48
+#define LMP_COMPID_SYNOPSYS 49
+#define LMP_COMPID_RED_M_LTD 50
+#define LMP_COMPID_COMMIL_LTD 51
+#define LMP_COMPID_CATC 52
+#define LMP_COMPID_ECLIPSE 53
+#define LMP_COMPID_RENESAS_TECH 54
+#define LMP_COMPID_MOBILIAN_CORP 55
+#define LMP_COMPID_TERAX 56
+#define LMP_COMPID_ISSC 57
+#define LMP_COMPID_MATSUSHITA 58
+#define LMP_COMPID_GENNUM_CORP 59
+#define LMP_COMPID_RESEARCH_IN_MOTION 60
+#define LMP_COMPID_IPEXTREME 61
+#define LMP_COMPID_SYSTEMS_AND_CHIPS 62
+#define LMP_COMPID_BLUETOOTH_SIG 63
+#define LMP_COMPID_SEIKO_EPSON_CORP 64
+#define LMP_COMPID_ISS_TAIWAN 65
+#define LMP_COMPID_CONWISE_TECHNOLOGIES 66
+#define LMP_COMPID_PARROT_SA 67
+#define LMP_COMPID_SOCKET_COMM 68
+#define LMP_COMPID_MAX_ID 69 /* this is a place holder */
+#define LMP_COMPID_INTERNAL 65535
+
+#define MAX_LMP_COMPID (LMP_COMPID_MAX_ID)
+/*
+** Define the packet types in the packet header, and a couple extra
+*/
+#define PKT_TYPE_NULL 0x00
+#define PKT_TYPE_POLL 0x01
+#define PKT_TYPE_FHS 0x02
+#define PKT_TYPE_DM1 0x03
+
+#define PKT_TYPE_DH1 0x04
+#define PKT_TYPE_HV1 0x05
+#define PKT_TYPE_HV2 0x06
+#define PKT_TYPE_HV3 0x07
+#define PKT_TYPE_DV 0x08
+#define PKT_TYPE_AUX1 0x09
+
+#define PKT_TYPE_DM3 0x0a
+#define PKT_TYPE_DH3 0x0b
+
+#define PKT_TYPE_DM5 0x0e
+#define PKT_TYPE_DH5 0x0f
+
+
+#define PKT_TYPE_ID 0x10 /* Internally used packet types */
+#define PKT_TYPE_BAD 0x11
+#define PKT_TYPE_NONE 0x12
+
+/*
+** Define packet size
+*/
+#define HCI_DM1_PACKET_SIZE 17
+#define HCI_DH1_PACKET_SIZE 27
+#define HCI_DM3_PACKET_SIZE 121
+#define HCI_DH3_PACKET_SIZE 183
+#define HCI_DM5_PACKET_SIZE 224
+#define HCI_DH5_PACKET_SIZE 339
+#define HCI_AUX1_PACKET_SIZE 29
+#define HCI_HV1_PACKET_SIZE 10
+#define HCI_HV2_PACKET_SIZE 20
+#define HCI_HV3_PACKET_SIZE 30
+#define HCI_DV_PACKET_SIZE 9
+#define HCI_EDR2_DH1_PACKET_SIZE 54
+#define HCI_EDR2_DH3_PACKET_SIZE 367
+#define HCI_EDR2_DH5_PACKET_SIZE 679
+#define HCI_EDR3_DH1_PACKET_SIZE 83
+#define HCI_EDR3_DH3_PACKET_SIZE 552
+#define HCI_EDR3_DH5_PACKET_SIZE 1021
+
+/*
+** Features encoding - page 0
+*/
+#define HCI_NUM_FEATURE_BYTES 8
+#define HCI_FEATURES_KNOWN(x) ((x[0] | x[1] | x[2] | x[3] | x[4] | x[5] | x[6] | x[7]) != 0)
+
+#define HCI_FEATURE_3_SLOT_PACKETS_MASK 0x01
+#define HCI_FEATURE_3_SLOT_PACKETS_OFF 0
+#define HCI_3_SLOT_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_3_SLOT_PACKETS_OFF] & HCI_FEATURE_3_SLOT_PACKETS_MASK)
+
+#define HCI_FEATURE_5_SLOT_PACKETS_MASK 0x02
+#define HCI_FEATURE_5_SLOT_PACKETS_OFF 0
+#define HCI_5_SLOT_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_5_SLOT_PACKETS_OFF] & HCI_FEATURE_5_SLOT_PACKETS_MASK)
+
+#define HCI_FEATURE_ENCRYPTION_MASK 0x04
+#define HCI_FEATURE_ENCRYPTION_OFF 0
+#define HCI_ENCRYPTION_SUPPORTED(x) ((x)[HCI_FEATURE_ENCRYPTION_OFF] & HCI_FEATURE_ENCRYPTION_MASK)
+
+#define HCI_FEATURE_SLOT_OFFSET_MASK 0x08
+#define HCI_FEATURE_SLOT_OFFSET_OFF 0
+#define HCI_SLOT_OFFSET_SUPPORTED(x) ((x)[HCI_FEATURE_SLOT_OFFSET_OFF] & HCI_FEATURE_SLOT_OFFSET_MASK)
+
+#define HCI_FEATURE_TIMING_ACC_MASK 0x10
+#define HCI_FEATURE_TIMING_ACC_OFF 0
+#define HCI_TIMING_ACC_SUPPORTED(x) ((x)[HCI_FEATURE_TIMING_ACC_OFF] & HCI_FEATURE_TIMING_ACC_MASK)
+
+#define HCI_FEATURE_SWITCH_MASK 0x20
+#define HCI_FEATURE_SWITCH_OFF 0
+#define HCI_SWITCH_SUPPORTED(x) ((x)[HCI_FEATURE_SWITCH_OFF] & HCI_FEATURE_SWITCH_MASK)
+
+#define HCI_FEATURE_HOLD_MODE_MASK 0x40
+#define HCI_FEATURE_HOLD_MODE_OFF 0
+#define HCI_HOLD_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_HOLD_MODE_OFF] & HCI_FEATURE_HOLD_MODE_MASK)
+
+#define HCI_FEATURE_SNIFF_MODE_MASK 0x80
+#define HCI_FEATURE_SNIFF_MODE_OFF 0
+#define HCI_SNIFF_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_SNIFF_MODE_OFF] & HCI_FEATURE_SNIFF_MODE_MASK)
+
+#define HCI_FEATURE_PARK_MODE_MASK 0x01
+#define HCI_FEATURE_PARK_MODE_OFF 1
+#define HCI_PARK_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_PARK_MODE_OFF] & HCI_FEATURE_PARK_MODE_MASK)
+
+#define HCI_FEATURE_RSSI_MASK 0x02
+#define HCI_FEATURE_RSSI_OFF 1
+#define HCI_RSSI_SUPPORTED(x) ((x)[HCI_FEATURE_RSSI_OFF] & HCI_FEATURE_RSSI_MASK)
+
+#define HCI_FEATURE_CQM_DATA_RATE_MASK 0x04
+#define HCI_FEATURE_CQM_DATA_RATE_OFF 1
+#define HCI_CQM_DATA_RATE_SUPPORTED(x) ((x)[HCI_FEATURE_CQM_DATA_RATE_OFF] & HCI_FEATURE_CQM_DATA_RATE_MASK)
+
+#define HCI_FEATURE_SCO_LINK_MASK 0x08
+#define HCI_FEATURE_SCO_LINK_OFF 1
+#define HCI_SCO_LINK_SUPPORTED(x) ((x)[HCI_FEATURE_SCO_LINK_OFF] & HCI_FEATURE_SCO_LINK_MASK)
+
+#define HCI_FEATURE_HV2_PACKETS_MASK 0x10
+#define HCI_FEATURE_HV2_PACKETS_OFF 1
+#define HCI_HV2_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_HV2_PACKETS_OFF] & HCI_FEATURE_HV2_PACKETS_MASK)
+
+#define HCI_FEATURE_HV3_PACKETS_MASK 0x20
+#define HCI_FEATURE_HV3_PACKETS_OFF 1
+#define HCI_HV3_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_HV3_PACKETS_OFF] & HCI_FEATURE_HV3_PACKETS_MASK)
+
+#define HCI_FEATURE_U_LAW_MASK 0x40
+#define HCI_FEATURE_U_LAW_OFF 1
+#define HCI_LMP_U_LAW_SUPPORTED(x) ((x)[HCI_FEATURE_U_LAW_OFF] & HCI_FEATURE_U_LAW_MASK)
+
+#define HCI_FEATURE_A_LAW_MASK 0x80
+#define HCI_FEATURE_A_LAW_OFF 1
+#define HCI_LMP_A_LAW_SUPPORTED(x) ((x)[HCI_FEATURE_A_LAW_OFF] & HCI_FEATURE_A_LAW_MASK)
+
+#define HCI_FEATURE_CVSD_MASK 0x01
+#define HCI_FEATURE_CVSD_OFF 2
+#define HCI_LMP_CVSD_SUPPORTED(x) ((x)[HCI_FEATURE_CVSD_OFF] & HCI_FEATURE_CVSD_MASK)
+
+#define HCI_FEATURE_PAGING_SCHEME_MASK 0x02
+#define HCI_FEATURE_PAGING_SCHEME_OFF 2
+#define HCI_PAGING_SCHEME_SUPPORTED(x) ((x)[HCI_FEATURE_PAGING_SCHEME_OFF] & HCI_FEATURE_PAGING_SCHEME_MASK)
+
+#define HCI_FEATURE_POWER_CTRL_MASK 0x04
+#define HCI_FEATURE_POWER_CTRL_OFF 2
+#define HCI_POWER_CTRL_SUPPORTED(x) ((x)[HCI_FEATURE_POWER_CTRL_OFF] & HCI_FEATURE_POWER_CTRL_MASK)
+
+#define HCI_FEATURE_TRANSPNT_MASK 0x08
+#define HCI_FEATURE_TRANSPNT_OFF 2
+#define HCI_LMP_TRANSPNT_SUPPORTED(x) ((x)[HCI_FEATURE_TRANSPNT_OFF] & HCI_FEATURE_TRANSPNT_MASK)
+
+#define HCI_FEATURE_FLOW_CTRL_LAG_MASK 0x70
+#define HCI_FEATURE_FLOW_CTRL_LAG_OFF 2
+#define HCI_FLOW_CTRL_LAG_VALUE(x) (((x)[HCI_FEATURE_FLOW_CTRL_LAG_OFF] & HCI_FEATURE_FLOW_CTRL_LAG_MASK) >> 4)
+
+#define HCI_FEATURE_BROADCAST_ENC_MASK 0x80
+#define HCI_FEATURE_BROADCAST_ENC_OFF 2
+#define HCI_LMP_BCAST_ENC_SUPPORTED(x) ((x)[HCI_FEATURE_BROADCAST_ENC_OFF] & HCI_FEATURE_BROADCAST_ENC_MASK)
+
+#define HCI_FEATURE_SCATTER_MODE_MASK 0x01
+#define HCI_FEATURE_SCATTER_MODE_OFF 3
+#define HCI_LMP_SCATTER_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_SCATTER_MODE_OFF] & HCI_FEATURE_SCATTER_MODE_MASK)
+
+#define HCI_FEATURE_EDR_ACL_2MPS_MASK 0x02
+#define HCI_FEATURE_EDR_ACL_2MPS_OFF 3
+#define HCI_EDR_ACL_2MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ACL_2MPS_OFF] & HCI_FEATURE_EDR_ACL_2MPS_MASK)
+
+#define HCI_FEATURE_EDR_ACL_3MPS_MASK 0x04
+#define HCI_FEATURE_EDR_ACL_3MPS_OFF 3
+#define HCI_EDR_ACL_3MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ACL_3MPS_OFF] & HCI_FEATURE_EDR_ACL_3MPS_MASK)
+
+#define HCI_FEATURE_ENHANCED_INQ_MASK 0x08
+#define HCI_FEATURE_ENHANCED_INQ_OFF 3
+#define HCI_ENHANCED_INQ_SUPPORTED(x) ((x)[HCI_FEATURE_ENHANCED_INQ_OFF] & HCI_FEATURE_ENHANCED_INQ_MASK)
+
+#define HCI_FEATURE_INTERLACED_INQ_SCAN_MASK 0x10
+#define HCI_FEATURE_INTERLACED_INQ_SCAN_OFF 3
+#define HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(x) ((x)[HCI_FEATURE_INTERLACED_INQ_SCAN_OFF] & HCI_FEATURE_INTERLACED_INQ_SCAN_MASK)
+
+#define HCI_FEATURE_INTERLACED_PAGE_SCAN_MASK 0x20
+#define HCI_FEATURE_INTERLACED_PAGE_SCAN_OFF 3
+#define HCI_LMP_INTERLACED_PAGE_SCAN_SUPPORTED(x) ((x)[HCI_FEATURE_INTERLACED_PAGE_SCAN_OFF] & HCI_FEATURE_INTERLACED_PAGE_SCAN_MASK)
+
+#define HCI_FEATURE_INQ_RSSI_MASK 0x40
+#define HCI_FEATURE_INQ_RSSI_OFF 3
+#define HCI_LMP_INQ_RSSI_SUPPORTED(x) ((x)[HCI_FEATURE_INQ_RSSI_OFF] & HCI_FEATURE_INQ_RSSI_MASK)
+
+#define HCI_FEATURE_ESCO_EV3_MASK 0x80
+#define HCI_FEATURE_ESCO_EV3_OFF 3
+#define HCI_ESCO_EV3_SUPPORTED(x) ((x)[HCI_FEATURE_ESCO_EV3_OFF] & HCI_FEATURE_ESCO_EV3_MASK)
+
+#define HCI_FEATURE_ESCO_EV4_MASK 0x01
+#define HCI_FEATURE_ESCO_EV4_OFF 4
+#define HCI_ESCO_EV4_SUPPORTED(x) ((x)[HCI_FEATURE_ESCO_EV4_OFF] & HCI_FEATURE_ESCO_EV4_MASK)
+
+#define HCI_FEATURE_ESCO_EV5_MASK 0x02
+#define HCI_FEATURE_ESCO_EV5_OFF 4
+#define HCI_ESCO_EV5_SUPPORTED(x) ((x)[HCI_FEATURE_ESCO_EV5_OFF] & HCI_FEATURE_ESCO_EV5_MASK)
+
+#define HCI_FEATURE_ABSENCE_MASKS_MASK 0x04
+#define HCI_FEATURE_ABSENCE_MASKS_OFF 4
+#define HCI_LMP_ABSENCE_MASKS_SUPPORTED(x) ((x)[HCI_FEATURE_ABSENCE_MASKS_OFF] & HCI_FEATURE_ABSENCE_MASKS_MASK)
+
+#define HCI_FEATURE_AFH_CAP_SLAVE_MASK 0x08
+#define HCI_FEATURE_AFH_CAP_SLAVE_OFF 4
+#define HCI_LMP_AFH_CAP_SLAVE_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CAP_SLAVE_OFF] & HCI_FEATURE_AFH_CAP_SLAVE_MASK)
+
+#define HCI_FEATURE_AFH_CLASS_SLAVE_MASK 0x10
+#define HCI_FEATURE_AFH_CLASS_SLAVE_OFF 4
+#define HCI_LMP_AFH_CLASS_SLAVE_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CLASS_SLAVE_OFF] & HCI_FEATURE_AFH_CLASS_SLAVE_MASK)
+
+#define HCI_FEATURE_ALIAS_AUTH_MASK 0x20
+#define HCI_FEATURE_ALIAS_AUTH_OFF 4
+#define HCI_LMP_ALIAS_AUTH_SUPPORTED(x) ((x)[HCI_FEATURE_ALIAS_AUTH_OFF] & HCI_FEATURE_ALIAS_AUTH_MASK)
+
+#define HCI_FEATURE_ANON_MODE_MASK 0x40
+#define HCI_FEATURE_ANON_MODE_OFF 4
+#define HCI_LMP_ANON_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_ANON_MODE_OFF] & HCI_FEATURE_ANON_MODE_MASK)
+
+#define HCI_FEATURE_3_SLOT_EDR_ACL_MASK 0x80
+#define HCI_FEATURE_3_SLOT_EDR_ACL_OFF 4
+#define HCI_3_SLOT_EDR_ACL_SUPPORTED(x) ((x)[HCI_FEATURE_3_SLOT_EDR_ACL_OFF] & HCI_FEATURE_3_SLOT_EDR_ACL_MASK)
+
+#define HCI_FEATURE_5_SLOT_EDR_ACL_MASK 0x01
+#define HCI_FEATURE_5_SLOT_EDR_ACL_OFF 5
+#define HCI_5_SLOT_EDR_ACL_SUPPORTED(x) ((x)[HCI_FEATURE_5_SLOT_EDR_ACL_OFF] & HCI_FEATURE_5_SLOT_EDR_ACL_MASK)
+
+#define HCI_FEATURE_SNIFF_SUB_RATE_MASK 0x02
+#define HCI_FEATURE_SNIFF_SUB_RATE_OFF 5
+#define HCI_SNIFF_SUB_RATE_SUPPORTED(x) ((x)[HCI_FEATURE_SNIFF_SUB_RATE_OFF] & HCI_FEATURE_SNIFF_SUB_RATE_MASK)
+
+#define HCI_FEATURE_ATOMIC_ENCRYPT_MASK 0x04
+#define HCI_FEATURE_ATOMIC_ENCRYPT_OFF 5
+#define HCI_ATOMIC_ENCRYPT_SUPPORTED(x) ((x)[HCI_FEATURE_ATOMIC_ENCRYPT_OFF] & HCI_FEATURE_ATOMIC_ENCRYPT_MASK)
+
+#define HCI_FEATURE_AFH_CAP_MASTR_MASK 0x08
+#define HCI_FEATURE_AFH_CAP_MASTR_OFF 5
+#define HCI_LMP_AFH_CAP_MASTR_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CAP_MASTR_OFF] & HCI_FEATURE_AFH_CAP_MASTR_MASK)
+
+#define HCI_FEATURE_AFH_CLASS_MASTR_MASK 0x10
+#define HCI_FEATURE_AFH_CLASS_MASTR_OFF 5
+#define HCI_LMP_AFH_CLASS_MASTR_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CLASS_MASTR_OFF] & HCI_FEATURE_AFH_CLASS_MASTR_MASK)
+
+#define HCI_FEATURE_EDR_ESCO_2MPS_MASK 0x20
+#define HCI_FEATURE_EDR_ESCO_2MPS_OFF 5
+#define HCI_EDR_ESCO_2MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ESCO_2MPS_OFF] & HCI_FEATURE_EDR_ESCO_2MPS_MASK)
+
+#define HCI_FEATURE_EDR_ESCO_3MPS_MASK 0x40
+#define HCI_FEATURE_EDR_ESCO_3MPS_OFF 5
+#define HCI_EDR_ESCO_3MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ESCO_3MPS_OFF] & HCI_FEATURE_EDR_ESCO_3MPS_MASK)
+
+#define HCI_FEATURE_3_SLOT_EDR_ESCO_MASK 0x80
+#define HCI_FEATURE_3_SLOT_EDR_ESCO_OFF 5
+#define HCI_3_SLOT_EDR_ESCO_SUPPORTED(x) ((x)[HCI_FEATURE_3_SLOT_EDR_ESCO_OFF] & HCI_FEATURE_3_SLOT_EDR_ESCO_MASK)
+
+#define HCI_FEATURE_EXT_INQ_RSP_MASK 0x01
+#define HCI_FEATURE_EXT_INQ_RSP_OFF 6
+#define HCI_EXT_INQ_RSP_SUPPORTED(x) ((x)[HCI_FEATURE_EXT_INQ_RSP_OFF] & HCI_FEATURE_EXT_INQ_RSP_MASK)
+
+#define HCI_FEATURE_ANUM_PIN_AWARE_MASK 0x02
+#define HCI_FEATURE_ANUM_PIN_AWARE_OFF 6
+#define HCI_ANUM_PIN_AWARE_SUPPORTED(x) ((x)[HCI_FEATURE_ANUM_PIN_AWARE_OFF] & HCI_FEATURE_ANUM_PIN_AWARE_MASK)
+
+#define HCI_FEATURE_ANUM_PIN_CAP_MASK 0x04
+#define HCI_FEATURE_ANUM_PIN_CAP_OFF 6
+#define HCI_ANUM_PIN_CAP_SUPPORTED(x) ((x)[HCI_FEATURE_ANUM_PIN_CAP_OFF] & HCI_FEATURE_ANUM_PIN_CAP_MASK)
+
+#define HCI_FEATURE_SIMPLE_PAIRING_MASK 0x08
+#define HCI_FEATURE_SIMPLE_PAIRING_OFF 6
+#define HCI_SIMPLE_PAIRING_SUPPORTED(x) ((x)[HCI_FEATURE_SIMPLE_PAIRING_OFF] & HCI_FEATURE_SIMPLE_PAIRING_MASK)
+
+#define HCI_FEATURE_ENCAP_PDU_MASK 0x10
+#define HCI_FEATURE_ENCAP_PDU_OFF 6
+#define HCI_ENCAP_PDU_SUPPORTED(x) ((x)[HCI_FEATURE_ENCAP_PDU_OFF] & HCI_FEATURE_ENCAP_PDU_MASK)
+
+#define HCI_FEATURE_ERROR_DATA_MASK 0x20
+#define HCI_FEATURE_ERROR_DATA_OFF 6
+#define HCI_ERROR_DATA_SUPPORTED(x) ((x)[HCI_FEATURE_ERROR_DATA_OFF] & HCI_FEATURE_ERROR_DATA_MASK)
+
+#define HCI_FEATURE_NON_FLUSHABLE_PB_MASK 0x40
+#define HCI_FEATURE_NON_FLUSHABLE_PB_OFF 6
+#define HCI_NON_FLUSHABLE_PB_SUPPORTED(x) ((x)[HCI_FEATURE_NON_FLUSHABLE_PB_OFF] & HCI_FEATURE_NON_FLUSHABLE_PB_MASK)
+
+#define HCI_FEATURE_LINK_SUP_TO_EVT_MASK 0x01
+#define HCI_FEATURE_LINK_SUP_TO_EVT_OFF 7
+#define HCI_LINK_SUP_TO_EVT_SUPPORTED(x) ((x)[HCI_FEATURE_LINK_SUP_TO_EVT_OFF] & HCI_FEATURE_LINK_SUP_TO_EVT_MASK)
+
+#define HCI_FEATURE_INQ_RESP_TX_MASK 0x02
+#define HCI_FEATURE_INQ_RESP_TX_OFF 7
+#define HCI_INQ_RESP_TX_SUPPORTED(x) ((x)[HCI_FEATURE_INQ_RESP_TX_OFF] & HCI_FEATURE_INQ_RESP_TX_MASK)
+
+#define HCI_FEATURE_EXTENDED_MASK 0x80
+#define HCI_FEATURE_EXTENDED_OFF 7
+#define HCI_LMP_EXTENDED_SUPPORTED(x) ((x)[HCI_FEATURE_EXTENDED_OFF] & HCI_FEATURE_EXTENDED_MASK)
+
+/*
+** Features encoding - page 1
+*/
+#define HCI_EXT_FEATURE_SSP_HOST_MASK 0x01
+#define HCI_EXT_FEATURE_SSP_HOST_OFF 0
+#define HCI_SSP_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SSP_HOST_OFF] & HCI_EXT_FEATURE_SSP_HOST_MASK)
+
+/*
+** Local Supported Commands encoding
+*/
+#define HCI_NUM_SUPP_COMMANDS_BYTES 64
+
+#define HCI_SUPP_COMMANDS_INQUIRY_MASK 0x01
+#define HCI_SUPP_COMMANDS_INQUIRY_OFF 0
+#define HCI_INQUIRY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_INQUIRY_OFF] & HCI_SUPP_COMMANDS_INQUIRY_MASK)
+
+#define HCI_SUPP_COMMANDS_INQUIRY_CANCEL_MASK 0x02
+#define HCI_SUPP_COMMANDS_INQUIRY_CANCEL_OFF 0
+#define HCI_INQUIRY_CANCEL_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_INQUIRY_CANCEL_OFF] & HCI_SUPP_COMMANDS_INQUIRY_CANCEL_MASK)
+
+#define HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_MASK 0x04
+#define HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_OFF 0
+#define HCI_PERIODIC_INQUIRY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_OFF] & HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_MASK)
+
+#define HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_MASK 0x08
+#define HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_OFF 0
+#define HCI_EXIT_PERIODIC_INQUIRY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_OFF] & HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_MASK)
+
+#define HCI_SUPP_COMMANDS_CREATE_CONN_MASK 0x10
+#define HCI_SUPP_COMMANDS_CREATE_CONN_OFF 0
+#define HCI_CREATE_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CREATE_CONN_OFF] & HCI_SUPP_COMMANDS_CREATE_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_DISCONNECT_MASK 0x20
+#define HCI_SUPP_COMMANDS_DISCONNECT_OFF 0
+#define HCI_DISCONNECT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_DISCONNECT_OFF] & HCI_SUPP_COMMANDS_DISCONNECT_MASK)
+
+#define HCI_SUPP_COMMANDS_ADD_SCO_CONN_MASK 0x40
+#define HCI_SUPP_COMMANDS_ADD_SCO_CONN_OFF 0
+#define HCI_ADD_SCO_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ADD_SCO_CONN_OFF] & HCI_SUPP_COMMANDS_ADD_SCO_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_MASK 0x80
+#define HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_OFF 0
+#define HCI_CANCEL_CREATE_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_OFF] & HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_MASK 0x01
+#define HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_OFF 1
+#define HCI_ACCEPT_CONN_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_OFF] & HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_MASK 0x02
+#define HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_OFF 1
+#define HCI_REJECT_CONN_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_OFF] & HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_MASK 0x04
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_OFF 1
+#define HCI_LINK_KEY_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_MASK 0x08
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_OFF 1
+#define HCI_LINK_KEY_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_MASK 0x10
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_OFF 1
+#define HCI_PIN_CODE_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_MASK 0x20
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_OFF 1
+#define HCI_PIN_CODE_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_MASK 0x40
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_OFF 1
+#define HCI_CHANGE_CONN_PKT_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_OFF] & HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_AUTH_REQUEST_MASK 0x80
+#define HCI_SUPP_COMMANDS_AUTH_REQUEST_OFF 1
+#define HCI_AUTH_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_AUTH_REQUEST_OFF] & HCI_SUPP_COMMANDS_AUTH_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_MASK 0x01
+#define HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_OFF 2
+#define HCI_SET_CONN_ENCRYPTION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_OFF] & HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_MASK)
+
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_MASK 0x02
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_OFF 2
+#define HCI_CHANGE_CONN_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_MASTER_LINK_KEY_MASK 0x04
+#define HCI_SUPP_COMMANDS_MASTER_LINK_KEY_OFF 2
+#define HCI_MASTER_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_MASTER_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_MASTER_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_MASK 0x08
+#define HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_OFF 2
+#define HCI_REMOTE_NAME_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_OFF] & HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_MASK 0x10
+#define HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_OFF 2
+#define HCI_CANCEL_REMOTE_NAME_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_OFF] & HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_OFF 2
+#define HCI_READ_REMOTE_SUPP_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_OFF 2
+#define HCI_READ_REMOTE_EXT_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_OFF 2
+#define HCI_READ_REMOTE_VER_INFO_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_OFF] & HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_OFF 3
+#define HCI_READ_CLOCK_OFFSET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_OFF] & HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LMP_HANDLE_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_LMP_HANDLE_OFF 3
+#define HCI_READ_LMP_HANDLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LMP_HANDLE_OFF] & HCI_SUPP_COMMANDS_READ_LMP_HANDLE_MASK)
+
+#define HCI_SUPP_COMMANDS_HOLD_MODE_CMD_MASK 0x02
+#define HCI_SUPP_COMMANDS_HOLD_MODE_CMD_OFF 4
+#define HCI_HOLD_MODE_CMD_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_HOLD_MODE_CMD_OFF] & HCI_SUPP_COMMANDS_HOLD_MODE_CMD_MASK)
+
+#define HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_MASK 0x04
+#define HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_OFF 4
+#define HCI_SNIFF_MODE_CMD_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_OFF] & HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_MASK)
+
+#define HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_MASK 0x08
+#define HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_OFF 4
+#define HCI_EXIT_SNIFF_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_OFF] & HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_PARK_STATE_MASK 0x10
+#define HCI_SUPP_COMMANDS_PARK_STATE_OFF 4
+#define HCI_PARK_STATE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PARK_STATE_OFF] & HCI_SUPP_COMMANDS_PARK_STATE_MASK)
+
+#define HCI_SUPP_COMMANDS_EXIT_PARK_STATE_MASK 0x20
+#define HCI_SUPP_COMMANDS_EXIT_PARK_STATE_OFF 4
+#define HCI_EXIT_PARK_STATE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_EXIT_PARK_STATE_OFF] & HCI_SUPP_COMMANDS_EXIT_PARK_STATE_MASK)
+
+#define HCI_SUPP_COMMANDS_QOS_SETUP_MASK 0x40
+#define HCI_SUPP_COMMANDS_QOS_SETUP_OFF 4
+#define HCI_QOS_SETUP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_QOS_SETUP_OFF] & HCI_SUPP_COMMANDS_QOS_SETUP_MASK)
+
+#define HCI_SUPP_COMMANDS_ROLE_DISCOVERY_MASK 0x80
+#define HCI_SUPP_COMMANDS_ROLE_DISCOVERY_OFF 4
+#define HCI_ROLE_DISCOVERY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ROLE_DISCOVERY_OFF] & HCI_SUPP_COMMANDS_ROLE_DISCOVERY_MASK)
+
+#define HCI_SUPP_COMMANDS_SWITCH_ROLE_MASK 0x01
+#define HCI_SUPP_COMMANDS_SWITCH_ROLE_OFF 5
+#define HCI_SWITCH_ROLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SWITCH_ROLE_OFF] & HCI_SUPP_COMMANDS_SWITCH_ROLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_OFF 5
+#define HCI_READ_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_MASK 0x04
+#define HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_OFF 5
+#define HCI_WRITE_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_OFF 5
+#define HCI_READ_DEF_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_MASK 0x10
+#define HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_OFF 5
+#define HCI_WRITE_DEF_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_MASK 0x20
+#define HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_OFF 5
+#define HCI_FLOW_SPECIFICATION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_OFF] & HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_EVENT_MASK_MASK 0x40
+#define HCI_SUPP_COMMANDS_SET_EVENT_MASK_OFF 5
+#define HCI_SET_EVENT_MASK_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_EVENT_MASK_OFF] & HCI_SUPP_COMMANDS_SET_EVENT_MASK_MASK)
+
+#define HCI_SUPP_COMMANDS_RESET_MASK 0x80
+#define HCI_SUPP_COMMANDS_RESET_OFF 5
+#define HCI_RESET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_RESET_OFF] & HCI_SUPP_COMMANDS_RESET_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_EVENT_FILTER_MASK 0x01
+#define HCI_SUPP_COMMANDS_SET_EVENT_FILTER_OFF 6
+#define HCI_SET_EVENT_FILTER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_EVENT_FILTER_OFF] & HCI_SUPP_COMMANDS_SET_EVENT_FILTER_MASK)
+
+#define HCI_SUPP_COMMANDS_FLUSH_MASK 0x02
+#define HCI_SUPP_COMMANDS_FLUSH_OFF 6
+#define HCI_FLUSH_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_FLUSH_OFF] & HCI_SUPP_COMMANDS_FLUSH_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PIN_TYPE_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_PIN_TYPE_OFF 6
+#define HCI_READ_PIN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PIN_TYPE_OFF] & HCI_SUPP_COMMANDS_READ_PIN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_OFF 6
+#define HCI_WRITE_PIN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_OFF] & HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_MASK 0x10
+#define HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_OFF 6
+#define HCI_CREATE_NEW_UNIT_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_OFF] & HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_OFF 6
+#define HCI_READ_STORED_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_MASK 0x40
+#define HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_OFF 6
+#define HCI_WRITE_STORED_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_MASK 0x80
+#define HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_OFF 6
+#define HCI_DELETE_STORED_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_MASK 0x01
+#define HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_OFF 7
+#define HCI_WRITE_LOCAL_NAME_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_OFF] & HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_NAME_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_LOCAL_NAME_OFF 7
+#define HCI_READ_LOCAL_NAME_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_NAME_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_NAME_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_OFF 7
+#define HCI_READ_CONN_ACCEPT_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_OFF 7
+#define HCI_WRITE_CONN_ACCEPT_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_TOUT_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_PAGE_TOUT_OFF 7
+#define HCI_READ_PAGE_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_OFF 7
+#define HCI_WRITE_PAGE_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_OFF 7
+#define HCI_READ_SCAN_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_OFF 7
+#define HCI_WRITE_SCAN_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_OFF 8
+#define HCI_READ_PAGE_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_OFF 8
+#define HCI_WRITE_PAGE_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_OFF 8
+#define HCI_READ_INQURIY_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_OFF 8
+#define HCI_WRITE_INQURIY_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_OFF 8
+#define HCI_READ_AUTH_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_OFF 8
+#define HCI_WRITE_AUTH_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_OFF 8
+#define HCI_READ_ENCRYPT_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_OFF 8
+#define HCI_WRITE_ENCRYPT_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_OFF 9
+#define HCI_READ_CLASS_DEVICE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_OFF] & HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_OFF 9
+#define HCI_WRITE_CLASS_DEVICE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_OFF] & HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_VOICE_SETTING_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_VOICE_SETTING_OFF 9
+#define HCI_READ_VOICE_SETTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_VOICE_SETTING_OFF] & HCI_SUPP_COMMANDS_READ_VOICE_SETTING_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_OFF 9
+#define HCI_WRITE_VOICE_SETTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_OFF] & HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_OFF 9
+#define HCI_READ_AUTO_FLUSH_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_OFF 9
+#define HCI_WRITE_AUTO_FLUSH_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_OFF 9
+#define HCI_READ_NUM_BROAD_RETRANS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_OFF] & HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_OFF 9
+#define HCI_WRITE_NUM_BROAD_RETRANS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_OFF] & HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_OFF 10
+#define HCI_READ_HOLD_MODE_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_OFF 10
+#define HCI_WRITE_HOLD_MODE_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_OFF 10
+#define HCI_READ_TRANS_PWR_LEVEL_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_OFF] & HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_OFF 10
+#define HCI_READ_SYNCH_FLOW_CTRL_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_MASK 0x10
+#define HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_OFF 10
+#define HCI_WRITE_SYNCH_FLOW_CTRL_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_MASK 0x20
+#define HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_OFF 10
+#define HCI_SET_HOST_CTRLR_TO_HOST_FC_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_OFF] & HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_MASK)
+
+#define HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_MASK 0x40
+#define HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_OFF 10
+#define HCI_HOST_BUFFER_SIZE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_OFF] & HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_MASK)
+
+#define HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_MASK 0x80
+#define HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_OFF 10
+#define HCI_HOST_NUM_COMPLETED_PKTS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_OFF] & HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_OFF 11
+#define HCI_READ_LINK_SUP_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_OFF 11
+#define HCI_WRITE_LINK_SUP_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_OFF 11
+#define HCI_READ_NUM_SUPP_IAC_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_OFF] & HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_OFF 11
+#define HCI_READ_CURRENT_IAC_LAP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_OFF] & HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_MASK 0x10
+#define HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_OFF 11
+#define HCI_WRITE_CURRENT_IAC_LAP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_OFF] & HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_OFF 11
+#define HCI_READ_PAGE_SCAN_PER_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_MASK 0x40
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_OFF 11
+#define HCI_WRITE_PAGE_SCAN_PER_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_OFF 11
+#define HCI_READ_PAGE_SCAN_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_MASK 0x01
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_OFF 12
+#define HCI_WRITE_PAGE_SCAN_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_MASK 0x02
+#define HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_OFF 12
+#define HCI_SET_AFH_CHNL_CLASS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_OFF] & HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_OFF 12
+#define HCI_READ_INQUIRY_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_OFF 12
+#define HCI_WRITE_INQUIRY_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_OFF 12
+#define HCI_READ_INQUIRY_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_OFF] & HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_OFF 12
+#define HCI_WRITE_INQUIRY_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_OFF 13
+#define HCI_READ_PAGE_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_OFF 13
+#define HCI_WRITE_PAGE_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_OFF 13
+#define HCI_READ_AFH_CHNL_ASSESS_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_OFF] & HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_OFF 13
+#define HCI_WRITE_AFH_CHNL_ASSESS_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_OFF 14
+#define HCI_READ_LOCAL_VER_INFO_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_OFF 14
+#define HCI_READ_LOCAL_SUP_CMDS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_OFF 14
+#define HCI_READ_LOCAL_SUPP_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_OFF 14
+#define HCI_READ_LOCAL_EXT_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_OFF 14
+#define HCI_READ_BUFFER_SIZE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_OFF] & HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_OFF 15
+#define HCI_READ_COUNTRY_CODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_OFF] & HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_BD_ADDR_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_BD_ADDR_OFF 15
+#define HCI_READ_BD_ADDR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_BD_ADDR_OFF] & HCI_SUPP_COMMANDS_READ_BD_ADDR_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_OFF 15
+#define HCI_READ_FAIL_CONTACT_CNTR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_OFF] & HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_MASK)
+
+#define HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_MASK 0x08
+#define HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_OFF 15
+#define HCI_RESET_FAIL_CONTACT_CNTR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_OFF] & HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_MASK)
+
+#define HCI_SUPP_COMMANDS_GET_LINK_QUALITY_MASK 0x10
+#define HCI_SUPP_COMMANDS_GET_LINK_QUALITY_OFF 15
+#define HCI_GET_LINK_QUALITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_GET_LINK_QUALITY_OFF] & HCI_SUPP_COMMANDS_GET_LINK_QUALITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_RSSI_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_RSSI_OFF 15
+#define HCI_READ_RSSI_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_RSSI_OFF] & HCI_SUPP_COMMANDS_READ_RSSI_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_OFF 15
+#define HCI_READ_AFH_CH_MAP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_OFF] & HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_BD_CLOCK_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_BD_CLOCK_OFF 15
+#define HCI_READ_BD_CLOCK_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_BD_CLOCK_OFF] & HCI_SUPP_COMMANDS_READ_BD_CLOCK_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_OFF 16
+#define HCI_READ_LOOPBACK_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_OFF] & HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_OFF 16
+#define HCI_WRITE_LOOPBACK_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_MASK 0x04
+#define HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_OFF 16
+#define HCI_ENABLE_DEV_UNDER_TEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_OFF] & HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_MASK)
+
+#define HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_MASK 0x08
+#define HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_OFF 16
+#define HCI_SETUP_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_MASK 0x10
+#define HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_OFF 16
+#define HCI_ACCEPT_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_MASK 0x20
+#define HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_OFF 16
+#define HCI_REJECT_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_OFF 17
+#define HCI_READ_EXT_INQUIRY_RESP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_OFF] & HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_OFF 17
+#define HCI_WRITE_EXT_INQUIRY_RESP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_OFF] & HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_MASK)
+
+#define HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_MASK 0x04
+#define HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_OFF 17
+#define HCI_REFRESH_ENCRYPTION_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_OFF] & HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_MASK)
+
+/* Octet 17, bit 3 is reserved */
+
+#define HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_MASK 0x10
+#define HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_OFF 17
+#define HCI_SNIFF_SUB_RATE_CMD_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_OFF] & HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_OFF 17
+#define HCI_READ_SIMPLE_PAIRING_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_OFF] & HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_MASK 0x40
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_OFF 17
+#define HCI_WRITE_SIMPLE_PAIRING_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_OFF 17
+#define HCI_READ_LOCAL_OOB_DATA_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_OFF 18
+#define HCI_READ_INQUIRY_RESPONSE_TX_POWER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_OFF] & HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_OFF 18
+#define HCI_WRITE_INQUIRY_RESPONSE_TX_POWER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_OFF] & HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF 18
+#define HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF] & HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF 18
+#define HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF] & HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK)
+
+#define HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_MASK 0x80
+#define HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_OFF 18
+#define HCI_IO_CAPABILITY_RESPONSE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_OFF] & HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_MASK 0x01
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_OFF 19
+#define HCI_USER_CONFIRMATION_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_MASK 0x02
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_OFF 19
+#define HCI_USER_CONFIRMATION_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_MASK 0x04
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_OFF 19
+#define HCI_USER_PASSKEY_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_MASK 0x08
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_OFF 19
+#define HCI_USER_PASSKEY_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_MASK 0x10
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_OFF 19
+#define HCI_REMOTE_OOB_DATA_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_OFF 19
+#define HCI_WRITE_SIMPLE_PAIRING_DBG_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_ENHANCED_FLUSH_MASK 0x40
+#define HCI_SUPP_COMMANDS_ENHANCED_FLUSH_OFF 19
+#define HCI_ENHANCED_FLUSH_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENHANCED_FLUSH_OFF] & HCI_SUPP_COMMANDS_ENHANCED_FLUSH_MASK)
+
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_MASK 0x80
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_OFF 19
+#define HCI_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_MASK 0x04
+#define HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_OFF 20
+#define HCI_SEND_NOTIF_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_OFF] & HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_MASK)
+
+#define HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_MASK 0x08
+#define HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_OFF 20
+#define HCI_IO_CAP_REQ_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_MASK)
+
+#endif
+
diff --git a/btusb_1_6_29_1/inc/.svn/text-base/target.h.svn-base b/btusb_1_6_29_1/inc/.svn/text-base/target.h.svn-base
new file mode 100755
index 0000000..32b5bf9
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/.svn/text-base/target.h.svn-base
@@ -0,0 +1,121 @@
+/*
+ *
+ * target.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef _TARGET_H
+#define _TARGET_H
+
+#include <linux/usb.h>
+
+#define BT_API
+#define RFC_API
+#define L2C_API
+
+#define INT int
+#define UINT unsigned int
+#define DWORD unsigned long
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+#ifndef USHORT
+#define USHORT unsigned short
+#endif
+
+#ifndef ULONG
+#define ULONG unsigned long
+#endif
+
+#ifndef VOID
+#define VOID void
+#endif
+
+#define _vsnprintf vsnprintf
+
+#define __cdecl
+
+#define GKI_USE_DYNAMIC_BUFFERS TRUE /* TRUE if using dynamic buffers */
+
+#define GKI_NUM_FIXED_BUF_POOLS 1
+#define GKI_DEF_BUFPOOL_PERM_MASK 0xfffc /* Pool ID 0 is public */
+
+/* Define the total number of buffer pools used, fixed and dynamic (Maximum is 16) */
+#define GKI_NUM_TOTAL_BUF_POOLS 1
+
+#define GKI_BUF0_SIZE 1740
+#ifdef BTUSB_LITE
+#define GKI_BUF0_MAX 10
+#else
+#define GKI_BUF0_MAX 5
+#endif
+
+#define GKI_POOL_ID_0 0
+
+#define HCI_SCO_POOL_ID GKI_POOL_ID_0 // all SCO data to/from the device
+
+/* Set this flag to non zero if you want to do buffer corruption checks.
+** If set, GKI will check buffer tail corruption every time it processes
+** a buffer. This is very useful for debug, and is minimal overhead in
+** a running system.
+*/
+#define GKI_ENABLE_BUF_CORRUPTION_CHECK 1
+
+#define L2CAP_MTU_SIZE 1691
+//#define L2CAP_MTU_SIZE 200
+
+/* Maximum size in bytes of the codec capabilities information element. */
+#ifndef AVDT_CODEC_SIZE
+#define AVDT_CODEC_SIZE 10
+#endif
+
+/* Number of streams for dual stack */
+#ifndef BTM_SYNC_INFO_NUM_STR
+#define BTM_SYNC_INFO_NUM_STR 2
+#endif
+
+/* Number of streams for dual stack in BT Controller (simulation) */
+#ifndef BTM_SYNC_INFO_NUM_STR_BTC
+#define BTM_SYNC_INFO_NUM_STR_BTC 2
+#endif
+
+#ifndef BTA_AV_NUM_STRS
+#define BTA_AV_NUM_STRS 2
+#endif
+
+#define BTU_STACK_LITE_ENABLED TRUE
+#define BTU_MULTI_AV_INCLUDED TRUE
+
+/* Number of simultaneous links to different peer devices. */
+#ifndef AVDT_NUM_LINKS
+#define AVDT_NUM_LINKS 2
+#endif
+
+/* Number of simultaneous stream endpoints. */
+#ifndef AVDT_NUM_SEPS
+#define AVDT_NUM_SEPS 2
+#endif
+
+#endif
diff --git a/btusb_1_6_29_1/inc/bt_target.h b/btusb_1_6_29_1/inc/bt_target.h
new file mode 100755
index 0000000..e69de29
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/bt_target.h
diff --git a/btusb_1_6_29_1/inc/bt_types.h b/btusb_1_6_29_1/inc/bt_types.h
new file mode 100755
index 0000000..f214d54
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/bt_types.h
@@ -0,0 +1,78 @@
+/*
+*
+* bt_types.h
+*
+*
+*
+* Copyright (C) 2011-2013 Broadcom Corporation.
+*
+*
+*
+* This software is licensed under the terms of the GNU General Public License,
+* version 2, as published by the Free Software Foundation (the "GPL"), and may
+* be copied, distributed, and modified under those terms.
+*
+* 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 GPL for more details.
+*
+*
+* A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+* or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA
+*
+*
+*/
+
+#ifndef BT_TYPES_H
+#define BT_TYPES_H
+
+#include "data_types.h"
+
+/* READ WELL !!
+**
+** This section defines global events. These are events that cross layers.
+** Any event that passes between layers MUST be one of these events. Tasks
+** can use their own events internally, but a FUNDAMENTAL design issue is
+** that global events MUST be one of these events defined below.
+**
+** The convention used is the the event name contains the layer that the
+** event is going to.
+*/
+#define BT_EVT_TO_BTU_HCI_EVT 0x1000 /* HCI Event */
+
+#define BT_EVT_TO_BTU_HCI_SCO 0x1200 /* SCO Data from HCI */
+
+#define BT_EVT_TO_LM_HCI_CMD 0x2000 /* HCI Command */
+#define BT_EVT_TO_LM_HCI_ACL 0x2100 /* HCI ACL Data */
+#define BT_EVT_TO_LM_DIAG 0x2c00 /* LM Diagnostics commands */
+
+
+#define BT_EVT_BTU_IPC_EVT 0x9000
+#define BT_EVT_BTU_IPC_LOGMSG_EVT (0x0000 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_ACL_EVT (0x0001 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BTU_EVT (0x0002 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_L2C_EVT (0x0003 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_L2C_MSG_EVT (0x0004 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BTM_EVT (0x0005 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_AVDT_EVT (0x0006 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_SLIP_EVT (0x0007 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_MGMT_EVT (0x0008 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BTTRC_EVT (0x0009 | BT_EVT_BTU_IPC_EVT)
+#define BT_EVT_BTU_IPC_BURST_EVT (0x000A | BT_EVT_BTU_IPC_EVT)
+
+
+/* Define the header of each buffer used in the Bluetooth stack.
+*/
+typedef struct
+{
+ UINT16 event;
+ UINT16 len;
+ UINT16 offset;
+ UINT16 layer_specific;
+} BT_HDR;
+
+#define BT_HDR_SIZE (sizeof (BT_HDR))
+
+
+#endif
diff --git a/btusb_1_6_29_1/inc/btusb.h b/btusb_1_6_29_1/inc/btusb.h
new file mode 100755
index 0000000..aa7534d
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/btusb.h
@@ -0,0 +1,367 @@
+/*
+ *
+ * btusb.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef BTUSB_H
+#define BTUSB_H
+
+#include <linux/version.h>
+#include <linux/usb.h>
+#include <linux/tty.h>
+#include <linux/time.h>
+
+#include "bt_types.h"
+#include "gki_int.h"
+#include "btusbext.h"
+
+#ifdef BTUSB_LITE
+#include "btusb_lite.h"
+#endif
+
+/* Linux kernel compatibility abstraction */
+#if LINUX_VERSION_CODE <= KERNEL_VERSION(2, 6, 34)
+#define BTUSB_USHRT_MAX USHORT_MAX
+#else
+#define BTUSB_USHRT_MAX USHRT_MAX
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(3, 10, 0)
+#define BTUSB_PDE_DATA(inode) PDE(inode)->data
+#else
+#define BTUSB_PDE_DATA(inode) PDE_DATA(inode)
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 34)
+#define BTUSB_BUFFER_ALLOC usb_buffer_alloc
+#define BTUSB_BUFFER_FREE usb_buffer_free
+#else
+#define BTUSB_BUFFER_ALLOC usb_alloc_coherent
+#define BTUSB_BUFFER_FREE usb_free_coherent
+#endif
+
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2, 6, 30)
+#define BTUSB_EP_TYPE(ep) (ep->bmAttributes & USB_ENDPOINT_XFERTYPE_MASK)
+#define BTUSB_EP_DIR_IN(ep) ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_IN)
+#define BTUSB_EP_DIR_OUT(ep) ((ep->bEndpointAddress & USB_ENDPOINT_DIR_MASK) == USB_DIR_OUT)
+#else
+#define BTUSB_EP_TYPE(ep) usb_endpoint_type(ep)
+#define BTUSB_EP_DIR_IN(ep) usb_endpoint_dir_in(ep)
+#define BTUSB_EP_DIR_OUT(ep) usb_endpoint_dir_out(ep)
+#endif
+
+// debug information flags. one-hot encoded:
+// bit0 : enable printk(KERN_DEBUG)
+// bit1 : enable printk(KERN_INFO)
+// bit16 : enable all message dumps in printk
+// bit18 : enable GKI buffer check
+// bit19 : enable RX ACL size check
+#define BTUSB_DBG_MSG 0x0001
+#define BTUSB_INFO_MSG 0x0002
+#define BTUSB_DUMP_MSG 0x0100
+#define BTUSB_GKI_CHK_MSG 0x0400
+//#define BTUSB_DBGFLAGS (BTUSB_DBG_MSG | BTUSB_INFO_MSG | BTUSB_DUMP_MSG | BTUSB_GKI_CHK_MSG)
+#define BTUSB_DBGFLAGS 0
+
+extern int dbgflags;
+
+#define BTUSB_DBG(fmt, ...) if (unlikely(dbgflags & BTUSB_DBG_MSG)) \
+ printk(KERN_DEBUG "BTUSB %s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+
+#define BTUSB_INFO(fmt, ...) if (unlikely(dbgflags & BTUSB_INFO_MSG))\
+ printk(KERN_INFO "BTUSB %s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+
+#define BTUSB_ERR(fmt, ...) \
+ printk(KERN_ERR "BTUSB %s: " fmt, __FUNCTION__, ##__VA_ARGS__)
+
+// TBD: how do we assign the minor range?
+#define BTUSB_MINOR_BASE 194
+
+// 1025 = size(con_hdl) + size(acl_len) + size(3-dh5) = 2 + 2 + 1021
+#define BTUSB_HCI_MAX_ACL_SIZE 1025
+// Maximum size of command and events packets (events = 255 + 2, commands = 255 + 3)
+#define BTUSB_HCI_MAX_CMD_SIZE 258
+#define BTUSB_HCI_MAX_EVT_SIZE 258
+
+// Maximum HCI H4 size = HCI type + ACL packet
+#define BTUSB_H4_MAX_SIZE (1 + BTUSB_HCI_MAX_ACL_SIZE)
+
+#define BTUSB_NUM_OF_ACL_RX_BUFFERS 12
+#define BTUSB_NUM_OF_ACL_TX_BUFFERS 12
+#define BTUSB_NUM_OF_DIAG_RX_BUFFERS 2 // must not be less than 2
+#define BTUSB_NUM_OF_DIAG_TX_BUFFERS 2
+#define BTUSB_NUM_OF_EVENT_BUFFERS 8 // should not be less than 2
+#define BTUSB_NUM_OF_CMD_BUFFERS 8
+#define BTUSB_MAXIMUM_TX_VOICE_SIZE 192
+#define BTUSB_NUM_OF_VOICE_RX_BUFFERS 2 // for now should match 2 urbs
+#define BTUSB_NUM_OF_VOICE_TX_BUFFERS 32
+
+#define SCO_RX_BUFF_SIZE 360
+#define SCO_RX_MAX_LEN 240
+
+#define BTUSB_VOICE_BURST_SIZE 48
+#define BTUSB_VOICE_HEADER_SIZE 3
+#define BTUSB_VOICE_FRAMES_PER_URB 9
+#define BTUSB_VOICE_BUFFER_MAXSIZE (BTUSB_VOICE_FRAMES_PER_URB * \
+ ALIGN(BTUSB_VOICE_BURST_SIZE + BTUSB_VOICE_HEADER_SIZE, 4))
+
+
+#ifndef UINT8_TO_STREAM
+#define UINT8_TO_STREAM(p, u8) {*(p)++ = (UINT8)(u8);}
+#define UINT16_TO_STREAM(p, u16) {*(p)++ = (UINT8)(u16); *(p)++ = (UINT8)((u16) >> 8);}
+#define BDADDR_TO_STREAM(p, a) {register int ijk; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *(p)++ = (UINT8) a[BD_ADDR_LEN - 1 - ijk];}
+#define ARRAY_TO_STREAM(p, a, len) {register int ijk; for (ijk = 0; ijk < len; ijk++) *(p)++ = (UINT8) a[ijk];}
+
+#define STREAM_TO_UINT8(u8, p) {u8 = (UINT8)(*(p)); (p) += 1;}
+#define STREAM_TO_UINT16(u16, p) {u16 = (UINT16)((*(p)) + ((*((p) + 1)) << 8)); (p) += 2;}
+#define STREAM_TO_UINT32(u32, p) {u32 = (((UINT32)(*(p))) + ((((UINT32)(*((p) + 1)))) << 8) + ((((UINT32)(*((p) + 2)))) << 16) + ((((UINT32)(*((p) + 3)))) << 24)); (p) += 4;}
+#define STREAM_TO_BDADDR(a, p) {register int ijk; register UINT8 *pbda = (UINT8 *)a + BD_ADDR_LEN - 1; for (ijk = 0; ijk < BD_ADDR_LEN; ijk++) *pbda-- = *p++;}
+#define STREAM_TO_ARRAY(a, p, len) {register int ijk; for (ijk = 0; ijk < len; ijk++) ((UINT8 *) a)[ijk] = *p++;}
+#endif
+
+#define UINT32_TO_BE_STREAM(p, u32) {*(p)++ = (UINT8)((u32) >> 24); *(p)++ = (UINT8)((u32) >> 16); *(p)++ = (UINT8)((u32) >> 8); *(p)++ = (UINT8)(u32); }
+#define UINT24_TO_BE_STREAM(p, u24) {*(p)++ = (UINT8)((u24) >> 16); *(p)++ = (UINT8)((u24) >> 8); *(p)++ = (UINT8)(u24);}
+#define UINT16_TO_BE_STREAM(p, u16) {*(p)++ = (UINT8)((u16) >> 8); *(p)++ = (UINT8)(u16);}
+#define UINT8_TO_BE_STREAM(p, u8) {*(p)++ = (UINT8)(u8);}
+
+// macro that helps parsing arrays
+#define BTUSB_ARRAY_FOR_EACH_TRANS(__a) \
+ for (idx = 0, p_trans = &__a[0]; idx < ARRAY_SIZE(__a); idx++, p_trans = &__a[idx])
+
+/* Layer Specific field: Used to send packet to User Space */
+#define BTUSB_LS_H4_TYPE_SENT (1<<0) /* H4 HCI Type already sent */
+#define BTUSB_LS_GKI_BUFFER (1<<1) /* Locally allocated buffer-not to resubmit */
+
+//
+// Container used to copy the URB to sniff the SCO
+//
+struct btusb_scosniff
+{
+ struct list_head lh; // to add element to a list
+ int s; // start frame
+ unsigned int n; // number of descriptors
+ unsigned int l; // buffer length
+ struct usb_iso_packet_descriptor d[0]; // descriptors
+};
+
+//
+// This data structure is used for isochronous transfers
+//
+typedef struct
+{
+ // These two must go in sequence
+ void *dev;
+ unsigned char *packet;
+ int length;
+ unsigned long index;
+ int used;
+
+ // URB & related info must be the last fields
+ struct urb urb;
+ // enough to cover the longest request
+ struct usb_iso_packet_descriptor IsoPacket[(BTUSB_MAXIMUM_TX_VOICE_SIZE /9) + 1];
+} tBTUSB_ISO_ELEMENT;
+
+// BTUSB transaction
+typedef struct
+{
+ /* This is mapped to a GKI buffer to allow queuing */
+ BUFFER_HDR_T gki_hdr;
+ /* Sharing queue with other packets -> needs BT header to multiplex */
+ BT_HDR bt_hdr;
+ /* Pointer to the location where the USB data is received */
+ UINT8 *dma_buffer;
+ /* DMA structure */
+ dma_addr_t dma;
+ /* URB for this transaction */
+ struct urb *p_urb;
+ void *context;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ /* Magic number */
+ UINT32 magic;
+#endif
+} tBTUSB_TRANSACTION;
+
+// Voice channel descriptor
+typedef struct
+{
+ unsigned short sco_handle;
+ unsigned char burst;
+} tBTUSB_SCO_INFO;
+
+typedef struct
+{
+ int used;
+ BT_HDR *p_msg;
+ tBTUSB_SCO_INFO info;
+} tBTUSB_VOICE_CHANNEL;
+
+#define BTUSB_QUIRK_ZLP_TX_REQ (1 << 0)
+#define BTUSB_QUIRK_ZLP_RX_WA (1 << 1)
+
+// Define the main structure
+typedef struct btusb_cb
+{
+ struct usb_device *p_udev; // the usb device for this device
+ const struct usb_device_id *p_id; // Device Id from probe
+ struct usb_interface *p_main_intf; // Main Interface reference
+ struct usb_interface *p_voice_intf; // VOICE Interface reference
+ struct usb_interface *p_dfu_intf; // DFU Interface reference
+ struct usb_interface *p_diag_intf; // Diag Interface reference
+
+ struct usb_host_endpoint *p_acl_in; // the acl bulk in endpoint
+ struct usb_host_endpoint *p_acl_out; // the acl bulk out endpoint
+ struct usb_host_endpoint *p_diag_in; // the diag bulk in endpoint
+ struct usb_host_endpoint *p_diag_out; // the diag bulk out endpoint
+ struct usb_host_endpoint *p_event_in; // the interrupt in endpoint
+ struct usb_host_endpoint *p_voice_out; // iso out endpoint
+ struct usb_host_endpoint *p_voice_in; // voice in endpoint
+ struct ktermios kterm; // TTY emulation
+ struct mutex open_mutex; // protect concurrent open accesses
+ spinlock_t tasklet_lock;
+ struct kref kref;
+ tBTUSB_STATS stats;
+ bool opened;
+ bool issharedusb;
+ unsigned int quirks;
+
+ // reception queue
+ wait_queue_head_t rx_wait_q;
+
+ // tx tasklet
+ struct tasklet_struct tx_task;
+
+ // proc filesystem entry to retrieve info from driver environment
+ struct proc_dir_entry *p_debug_pde;
+ bool scosniff_active;
+ struct proc_dir_entry *p_scosniff_pde;
+ struct list_head scosniff_list;
+ struct completion scosniff_completion;
+
+ // Command transmit path
+ tBTUSB_TRANSACTION cmd_array[BTUSB_NUM_OF_CMD_BUFFERS];
+ struct usb_ctrlrequest cmd_req_array[BTUSB_NUM_OF_CMD_BUFFERS];
+ struct usb_anchor cmd_submitted;
+
+ // Event receive path
+ tBTUSB_TRANSACTION event_array[BTUSB_NUM_OF_EVENT_BUFFERS];
+ struct usb_anchor event_submitted;
+
+ // ACL receive path
+ tBTUSB_TRANSACTION acl_rx_array[BTUSB_NUM_OF_ACL_RX_BUFFERS];
+ struct usb_anchor acl_rx_submitted;
+
+ // ACL transmit path
+ tBTUSB_TRANSACTION acl_tx_array[BTUSB_NUM_OF_ACL_TX_BUFFERS];
+ struct usb_anchor acl_tx_submitted;
+
+ // Diagnostics receive path
+ tBTUSB_TRANSACTION diag_rx_array[BTUSB_NUM_OF_DIAG_RX_BUFFERS];
+ struct usb_anchor diag_rx_submitted;
+
+ // Diagnostics transmit path
+ tBTUSB_TRANSACTION diag_tx_array[BTUSB_NUM_OF_DIAG_TX_BUFFERS];
+ struct usb_anchor diag_tx_submitted;
+
+ // Voice
+ tBTUSB_TRANSACTION voice_rx_array[BTUSB_NUM_OF_VOICE_RX_BUFFERS];
+ struct usb_anchor voice_rx_submitted;
+
+ tBTUSB_VOICE_CHANNEL voice_channels[3];
+ unsigned short desired_packet_size;
+ unsigned int pending_bytes;
+ BT_HDR **pp_pending_msg;
+ unsigned char pending_hdr[BTUSB_VOICE_HEADER_SIZE];
+ unsigned int pending_hdr_size;
+
+ BT_HDR *p_write_msg;
+
+ unsigned long room_for_device_object; // must be here before the pending buffer
+ tBTUSB_ISO_ELEMENT *p_voicetxIrpList;
+ unsigned long voicetxIrpIndex;
+
+ BUFFER_Q rx_queue;
+ BT_HDR *p_rx_msg;
+ BUFFER_Q tx_queue;
+
+#ifdef BTUSB_LITE
+ struct btusb_lite_cb lite_cb;
+#endif
+} tBTUSB_CB;
+
+
+//
+// Function prototypes
+//
+void btusb_delete(struct kref *kref);
+
+void btusb_tx_task(unsigned long arg);
+
+void btusb_cancel_voice(tBTUSB_CB *p_dev);
+void btusb_cancel_urbs(tBTUSB_CB *p_dev);
+
+void btusb_voice_stats(unsigned long *p_max, unsigned long *p_min,
+ struct timeval *p_result, struct timeval *p_last_time);
+
+/* URB submit */
+int btusb_submit(tBTUSB_CB *p_dev, struct usb_anchor *p_anchor, tBTUSB_TRANSACTION *p_trans, int mem_flags);
+void btusb_submit_voice_rx(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, int mem_flags);
+
+/* bt controller to host routines */
+void btusb_enqueue(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, UINT8 hcitype);
+void btusb_dequeued(tBTUSB_CB *p_dev, BT_HDR *p_msg);
+
+void btusb_dump_data(const UINT8 *p, int len, const char *p_title);
+
+void btusb_cmd_complete(struct urb *p_urb);
+void btusb_write_complete(struct urb *p_urb);
+void btusb_voicerx_complete(struct urb *p_urb);
+
+// USB device interface
+int btusb_open(struct inode *inode, struct file *file);
+int btusb_release(struct inode *inode, struct file *file);
+ssize_t btusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos);
+ssize_t btusb_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos);
+unsigned int btusb_poll(struct file *file, struct poll_table_struct *p_pt);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+long btusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg);
+#else
+int btusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg);
+#endif
+
+// proc standard interface
+int btusb_debug_open(struct inode *inode, struct file *file);
+ssize_t btusb_debug_write(struct file *file, const char *buf, size_t count, loff_t *pos);
+
+ssize_t btusb_scosniff_read(struct file *file, char __user *buf, size_t size, loff_t *ppos);
+int btusb_scosniff_open(struct inode *inode, struct file *file);
+int btusb_scosniff_release(struct inode *inode, struct file *file);
+
+//
+// Globals
+//
+extern struct usb_driver btusb_driver;
+extern bool autopm;
+
+#endif // BTUSB_H
diff --git a/btusb_1_6_29_1/inc/btusb_lite.h b/btusb_1_6_29_1/inc/btusb_lite.h
new file mode 100755
index 0000000..66faaaa
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/btusb_lite.h
@@ -0,0 +1,198 @@
+/*
+ *
+ * btusb_lite.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_H
+#define BTUSB_LITE_H
+
+/* Forward declaration of BTUSB CB */
+struct btusb_cb;
+
+#include "bt_target.h"
+#include "hcidefs.h"
+#include "bd.h"
+#include "uipc_msg.h"
+#include "btusb_lite_av.h"
+#include "btusb_lite_avdt.h"
+#include "btusb_lite_l2c.h"
+#include "btusb_lite_hci.h"
+
+/*
+ * Definitions
+ */
+/* IPC Length Header Size (16 bits) */
+#define BTUSB_LITE_IPC_HDR_LEN_SIZE (sizeof(UINT16))
+
+/* IPC Event Header Size (16 bits) */
+#define BTUSB_LITE_IPC_HDR_EVT_SIZE (sizeof(UINT16))
+
+/* IPC Header contains a Length and an Event code */
+#define BTUSB_LITE_IPC_HDR_SIZE (BTUSB_LITE_IPC_HDR_LEN_SIZE + BTUSB_LITE_IPC_HDR_EVT_SIZE)
+
+struct btusb_lite_mgt_cb
+{
+ int opened;
+};
+
+struct btusb_lite_stat
+{
+ unsigned long event_bytes;
+ unsigned long event_completed;
+};
+
+struct btusb_lite_from_app
+{
+ BT_HDR *p_rx_msg;
+ UINT8 rx_header[BTUSB_LITE_IPC_HDR_SIZE];
+ UINT8 rx_header_len;
+ UINT16 rx_len; /* Decoded Rx Payload length */
+};
+
+struct btusb_lite_to_app
+{
+ BUFFER_Q ipc_queue; /* IPC message queue */
+ BT_HDR *p_ipc_msg;
+ BT_HDR *p_hdr_msg;
+ BT_HDR *p_hci_msg;
+};
+
+/* Lite Stack mode */
+#define BTU_FULL_STACK_ACTIVE 0
+#define BTU_LITE_STACK_ACTIVE 1
+#define BTU_TRANSPORT_HOLD 2
+#define BTU_FULL_TRANSPORT_ACTIVE 3
+#define BTU_LITE_TRANSPORT_ACTIVE 4
+
+#define BTU_IPC_CMD_SET_TRANSPORT_STATE 0 /* Set transport state (param=transprt state) */
+#define BTU_IPC_CMD_DISABLE_TRANSPORT 1 /* Set transport hardware (param=1 to disable) */
+
+struct btusb_lite_btu_cb
+{
+ UINT8 transport_state;
+ UINT8 transport_disabled;
+};
+
+typedef enum
+{
+ BTPCM_LITE_PCM_CLOSED = 0,
+ BTPCM_LITE_PCM_OPENED,
+ BTPCM_LITE_PCM_CONFIGURED,
+ BTPCM_LITE_PCM_STARTED
+} btusb_lite_pcm_state_t;
+
+struct btusb_lite_pcm_ccb
+{
+ btusb_lite_pcm_state_t state;
+ int channel;
+ int frequency;
+};
+
+struct btusb_lite_encoder_ccb
+{
+ int channel;
+ int opened;
+ int encoded_frame_size;
+ int pcm_frame_size;
+ int header_size;
+ int type; /* SBC, SEC, etc. */
+ tBTA_AV_AUDIO_CODEC_INFO encoder;
+};
+
+struct btusb_lite_av_cb
+{
+ UINT8 audio_open_cnt;
+ UINT16 curr_mtu;
+ UINT8 multi_av;
+ struct btusb_lite_pcm_ccb pcm;
+ struct btusb_lite_encoder_ccb encoder;
+ struct btusb_lite_av_scb scb[BTA_AV_NUM_STRS];
+ BT_HDR *p_buf_working;
+ UINT8 option;
+ UINT8 m_pt;
+ int header_len;
+ int payload_len;
+ UINT32 timestamp;
+};
+
+/* Main Lite Control Block */
+struct btusb_lite_cb
+{
+ struct proc_dir_entry *p_lite_pde;
+ int opened;
+ struct btusb_lite_stat stat;
+ struct btusb_lite_from_app from_app;
+ struct btusb_lite_to_app to_app;
+ struct btusb_lite_mgt_cb mgt; /* Management */
+ struct btusb_lite_btu_cb btu; /* BTU */
+ struct btusb_lite_l2c_cb l2c; /* L2C */
+ struct btusb_lite_av_cb av; /* AV */
+ struct btusb_lite_avdt_cb avdt;
+};
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_create
+ **
+ ** Description Create BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+int btusb_lite_create(struct btusb_cb *p_dev, struct usb_interface *p_interface);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_delete
+ **
+ ** Description Delete BTUSB Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+void btusb_lite_delete(struct btusb_cb *p_dev, struct usb_interface *p_interface);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_stop_all
+ **
+ ** Description Stop all sound streams
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_lite_stop_all(struct btusb_cb *p_dev);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_is_hci_over_ipc
+ **
+ ** Description Check if HCI is over IPC (Lite Interface).
+ **
+ ** Returns int (1 if HCI is over IPC otherwise 0)
+ **
+ *******************************************************************************/
+int btusb_lite_is_hci_over_ipc(struct btusb_cb *p_dev);
+
+#endif /* BTUSB_LITE_H*/
+
diff --git a/btusb_1_6_29_1/inc/btusb_lite_av.h b/btusb_1_6_29_1/inc/btusb_lite_av.h
new file mode 100755
index 0000000..f19ad0b
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/btusb_lite_av.h
@@ -0,0 +1,135 @@
+/*
+ *
+ * btusb_lite_av.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_AV_H
+#define BTUSB_LITE_AV_H
+
+typedef UINT8 tBTA_AV_CODEC; /* codec type */
+typedef UINT8 tBTA_AV_CHNL; /* the channel: audio/video */
+typedef UINT8 tBTA_AV_HNDL; /* the handle: ((hdi + 1)|chnl) */
+
+/* data type for the Audio Codec Information*/
+typedef struct
+{
+ UINT16 bit_rate; /* SBC encoder bit rate in kbps */
+ UINT16 bit_rate_busy; /* SBC encoder bit rate in kbps */
+ UINT16 bit_rate_swampd;/* SBC encoder bit rate in kbps */
+ UINT8 busy_level; /* Busy level indicating the bit-rate to be used */
+ UINT8 codec_info[AVDT_CODEC_SIZE];
+ UINT8 codec_type; /* Codec type */
+} tBTA_AV_AUDIO_CODEC_INFO;
+
+/* type for AV stream control block on Lite stack*/
+struct btusb_lite_av_scb
+{
+ BUFFER_Q out_q; /* used for audio channels only */
+ BD_ADDR peer_addr; /* peer BD address */
+ UINT16 l2c_cid; /* L2CAP channel ID */
+ tBTA_AV_CODEC codec_type; /* codec type */
+ BOOLEAN cong; /* TRUE if AVDTP congested */
+ tBTA_AV_CHNL chnl; /* the channel: audio/video */
+ tBTA_AV_HNDL hndl; /* the handle: ((hdi + 1)|chnl) */
+ UINT8 avdt_handle; /* AVDTP handle */
+ UINT8 hdi; /* the index to SCB[] */
+ UINT8 l2c_bufs; /* the number of buffers queued to L2CAP */
+ BOOLEAN started; /* TRUE if stream started from call-out perspective */
+ BOOLEAN start_stop_flag;/* TRUE when snk is INT and bta_av_start_ok() decides that */
+};
+
+/* these bits are defined for btusb_lite_av_cb.multi_av */
+#define BTA_AV_MULTI_AV_SUPPORTED 0x01
+#define BTA_AV_MULTI_AV_IN_USE 0x02
+
+/*
+ * Globals
+ */
+extern int pcm0_mute;
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_add
+**
+** Description Add (Sync) an AV channel.
+**
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_add(struct btusb_cb *p_dev, tBTA_AV_SYNC_INFO *p_sync_info,
+ UINT8 multi_av_supported, UINT16 curr_mtu);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_remove
+**
+** Description Remove (Cleanup) an AV channel.
+**
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_remove(struct btusb_cb *p_dev, UINT8 scb_idx,
+ UINT8 audio_open_cnt, UINT16 curr_mtu);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_start
+**
+** Description Start AV
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+void btusb_lite_av_start(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 start_stop_flag,
+ UINT8 audio_open_cnt, tBTA_AV_AUDIO_CODEC_INFO *p_codec_cfg);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_stop
+**
+** Description Start AV
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+void btusb_lite_av_stop(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt);
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_suspend
+**
+** Description Suspend AV
+**
+** Returns none.
+**
+*******************************************************************************/
+void btusb_lite_av_suspend(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt);
+
+#endif /* BTUSB_LITE_AV_H*/
+
diff --git a/btusb_1_6_29_1/inc/btusb_lite_avdt.h b/btusb_1_6_29_1/inc/btusb_lite_avdt.h
new file mode 100755
index 0000000..3538cc7
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/btusb_lite_avdt.h
@@ -0,0 +1,148 @@
+/*
+ *
+ * btusb_lite_avdt.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_AVDT_H
+#define BTUSB_LITE_AVDT_H
+
+/* AVDT Option */
+#define BTUSB_LITE_AVDT_OPT_NO_RTP 0x01 /* No RTP Header */
+#define BTUSB_LITE_AVDT_OPT_NO_MPH 0x02 /* No Media Payload Header */
+
+/* Definitions for A2DP packets */
+#define BTUSB_LITE_RTP_SIZE 12 /* RTP Header size */
+#define BTUSB_LITE_MEDIA_SIZE 1 /* Media Header size */
+#define BTUSB_LITE_SCMS_SIZE 1 /* SCMS Header size */
+
+/* Some A2DP Definitions */
+#define AVDT_MEDIA_OCTET1 0x80 /* First byte of media packet header */
+
+#define AVDT_MARKER_SET 0x80
+#define AVDT_RTP_PAYLOAD_TYPE 0x60 /* First Dynamic Payload type */
+
+/* AVDT Header size */
+#define BTUSB_LITE_AVDT_HDR_SIZE (BTUSB_LITE_RTP_SIZE + BTUSB_LITE_MEDIA_SIZE)
+
+/* A2DP Definitions */
+#define A2D_SBC_HDR_NUM_MSK 0x0F /* A2DP Media Header Frame Mask */
+
+
+/* channel control block type */
+struct btusb_lite_avdt_ccb
+{
+ BD_ADDR peer_addr; /* BD address of peer */
+ BOOLEAN allocated; /* Whether ccb is allocated */
+ UINT16 lcid; /* local L2CAP channel ID */
+ UINT16 peer_mtu; /* L2CAP mtu of the peer device */
+};
+
+/* SCMS information */
+struct btusb_lite_avdt_scms
+{
+ BOOLEAN enable; /* Indicates if SCMS is enabled */
+ UINT8 header; /* SCMS Header */
+};
+
+
+/* stream control block type */
+struct btusb_lite_avdt_scb
+{
+ BT_HDR *p_pkt; /* packet waiting to be sent */
+ struct btusb_lite_avdt_ccb *p_ccb; /* ccb associated with this scb */
+ UINT16 media_seq; /* media packet sequence number */
+ BOOLEAN allocated; /* whether scb is allocated or unused */
+ BOOLEAN in_use; /* whether stream being used by peer */
+ BOOLEAN cong; /* Whether media transport channel is congested */
+ UINT8 handle;
+ UINT8 mux_tsid_media; /* TSID for media transport session */
+ struct btusb_lite_avdt_scms scms;
+};
+
+struct btusb_lite_avdt_cb
+{
+ struct btusb_lite_avdt_ccb ccb[AVDT_NUM_LINKS]; /* channel control blocks */
+ struct btusb_lite_avdt_scb scb[AVDT_NUM_SEPS]; /* stream control blocks */
+
+};
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_scb_by_hdl
+**
+** Description Given an scb handle (or seid), return a pointer to the scb.
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+struct btusb_lite_avdt_scb *btusb_lite_avdt_scb_by_hdl(struct btusb_cb *p_dev, UINT8 hdl);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_init_scb
+**
+** Description allocate and initialize SCB/CCB with received sync info
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_init_scb(struct btusb_cb *p_dev, tAVDT_SCB_SYNC_INFO *p_scb_info);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_remove_scb
+**
+** Description deallocate SCB and CCB
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_remove_scb(struct btusb_cb *p_dev, UINT8 handle, tAVDT_SCB_SYNC_INFO *p_scb_info);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_send
+**
+** Description AVDT packet send
+**
+** Returns None
+**
+*******************************************************************************/
+void btusb_lite_avdt_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT8 avdt_handle,
+ UINT8 m_pt, UINT8 option, UINT32 timestamp);
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_cp_set_scms
+**
+** Description Set SCMS Content Protection for a channel
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_cp_set_scms(struct btusb_cb *p_dev, UINT8 avdt_handle,
+ BOOLEAN enable, UINT8 scms_hdr);
+
+#endif /* BTUSB_LITE_AVDT_H*/
+
diff --git a/btusb_1_6_29_1/inc/btusb_lite_hci.h b/btusb_1_6_29_1/inc/btusb_lite_hci.h
new file mode 100755
index 0000000..bb88d26
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/btusb_lite_hci.h
@@ -0,0 +1,71 @@
+/*
+ *
+ * btusb_lite_hci.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef BTUSB_LITE_HCI_H
+#define BTUSB_LITE_HCI_H
+
+/* Definitions for HCI ACL packets */
+
+/* HCI ACL Packet: HCI_Type, ConHdl, Length */
+#define BTUSB_LITE_HCI_ACL_HDR_SIZE (sizeof(UINT8) + sizeof(UINT16) + sizeof(UINT16))
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_acl_send
+ **
+ ** Description Send an ACL packet to HCI
+ **
+ ** Returns Status
+ **
+ *******************************************************************************/
+int btusb_lite_hci_acl_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 con_hdl);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_cmd_filter
+ **
+ ** Description Check if the Sent HCI Command need to be handled/caught (not
+ ** sent to BT controller).
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+int btusb_lite_hci_cmd_filter(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_event_filter
+ **
+ ** Description Handle/Filter HCI Events received from BT controller
+ **
+ ** Returns int (1 if HCI is over IPC otherwise 0)
+ **
+ *******************************************************************************/
+int btusb_lite_hci_event_filter(struct btusb_cb *p_dev, UINT8 *p_data, int length);
+
+#endif /* BTUSB_LITE_HCI_H */
+
diff --git a/btusb_1_6_29_1/inc/btusb_lite_l2c.h b/btusb_1_6_29_1/inc/btusb_lite_l2c.h
new file mode 100755
index 0000000..bf5aa6a
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/btusb_lite_l2c.h
@@ -0,0 +1,105 @@
+/*
+ *
+ * btusb_lite_l2c.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#ifndef BTUSB_LITE_L2C_H
+#define BTUSB_LITE_L2C_H
+
+/* L2CAP Header Definition (Length, CID) */
+#define BTUSB_LITE_L2CAP_HDR_SIZE (sizeof(UINT16) + sizeof(UINT16))
+
+struct btusb_lite_l2c_ccb
+{
+ BOOLEAN in_use;
+ UINT16 local_cid;
+ UINT16 remote_cid;
+ UINT16 out_mtu;
+ UINT16 handle;
+ UINT16 link_xmit_quota;
+ UINT8 is_flushable;
+
+ UINT16 tx_pending;
+};
+
+struct btusb_lite_l2c_cb
+{
+ /* Req */
+ UINT16 light_xmit_quota;
+ UINT16 acl_data_size;
+ UINT16 non_flushable_pbf;
+ UINT8 multi_av_data_cong_start;
+ UINT8 multi_av_data_cong_end;
+ UINT8 multi_av_data_cong_discard;
+ struct btusb_lite_l2c_ccb ccb[BTM_SYNC_INFO_NUM_STR];
+
+ /* Status */
+ UINT16 light_xmit_unacked;
+};
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_add
+**
+** Description Synchronize (Add) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_add(struct btusb_cb *p_dev, tL2C_STREAM_INFO *p_l2c_stream);
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_remove
+**
+** Description Synchronize (Remove) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_remove(struct btusb_cb *p_dev, UINT16 local_cid);
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_send
+**
+** Description Send L2CAP packet
+**
+** Returns Status
+**
+*******************************************************************************/
+int btusb_lite_l2c_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 local_cid);
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_l2c_nocp_hdlr
+ **
+ ** Description L2CAP NumberOfcompletePacket Handler function
+ **
+ ** Returns Number Of Complete Packet caught
+ **
+ *******************************************************************************/
+UINT16 btusb_lite_l2c_nocp_hdlr(struct btusb_cb *p_dev, UINT16 con_hdl, UINT16 num_cplt_pck);
+
+#endif /* BTUSB_LITE_L2C_H*/
+
diff --git a/btusb_1_6_29_1/inc/btusbext.h b/btusb_1_6_29_1/inc/btusbext.h
new file mode 100755
index 0000000..ccdff66
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/btusbext.h
@@ -0,0 +1,169 @@
+/*
+ *
+ * btusbext.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef BTUSBEXT_H
+#define BTUSBEXT_H
+
+#include <linux/time.h>
+
+// BTUSB Statistics structure
+typedef struct
+{
+ // All URB submit counter
+ unsigned long urb_submit_ok;
+ unsigned long urb_submit_err;
+
+ // ACL RX counters
+ unsigned long acl_rx_submit_ok;
+ unsigned long acl_rx_submit_err;
+ unsigned long acl_rx_completed;
+ unsigned long acl_rx_resubmit;
+ unsigned long acl_rx_bytes;
+
+ // DIAG RX counters
+ unsigned long diag_rx_submit_ok;
+ unsigned long diag_rx_submit_err;
+ unsigned long diag_rx_completed;
+ unsigned long diag_rx_resubmit;
+ unsigned long diag_rx_bytes;
+
+ // EVENT counters
+ unsigned long event_submit_ok;
+ unsigned long event_submit_err;
+ unsigned long event_completed;
+ unsigned long event_resubmit;
+ unsigned long event_bytes;
+
+ // Number of Write IRPs submitted
+ unsigned long writes_submitted;
+
+ // Number of Write IRPs submitted in error
+ unsigned long writes_submitted_error;
+
+ // Number of Write IRPs completed
+ unsigned long writes_completed;
+
+ // Number of Write IRPs completed in error
+ unsigned long writes_completed_error;
+
+ // Number of Command IRPs submitted
+ unsigned long commands_submitted;
+
+ // Number of Command IRPs submitted in error
+ unsigned long commands_submitted_error;
+
+ // Number of Command IRPs completed
+ unsigned long commands_completed;
+
+ // Number of Command IRPs completed in error
+ unsigned long commands_completed_error;
+
+ // Number of voice reqs submitted to the USB software stack
+ unsigned long voicerx_submitted;
+
+ // Number of voice rx submitted in error
+ unsigned long voicerx_submitted_error;
+
+ // Number of voice req completions from the USB software stack
+ unsigned long voicerx_completed;
+
+ // Number of Voice req completions in error
+ unsigned long voicerx_completed_error;
+
+ // Number of bad voice RX packets received
+ unsigned long voicerx_bad_packets;
+
+ // Bytes received altogether
+ unsigned long voicerx_raw_bytes;
+
+ // Bytes skipped
+ unsigned long voicerx_skipped_bytes;
+
+ // SCO headers split across packets
+ unsigned long voicerx_split_hdr;
+
+ // Voice frames discarded due to no headers in data
+ unsigned long voicerx_disc_nohdr;
+
+ // Number of Voice Tx reqs submitted
+ unsigned long voicetx_submitted;
+
+ // Number of voice tx submitted in error
+ unsigned long voicetx_submitted_error;
+
+ // Number of Voice Tx reqs completed
+ unsigned long voicetx_completed;
+
+ // Number of Voice Tx reqs completed in error
+ unsigned long voicetx_completed_error;
+
+ // Number of Voice Tx not submitted due to no room on the tx queue
+ unsigned long voicetx_disc_nobuf;
+
+ // Number of Voice tx not submitted due to too long data
+ unsigned long voicetx_disc_toolong;
+
+ /* number of Voice packet pending */
+ unsigned long voice_tx_cnt;
+
+ /* max number of Voice packet pending */
+ unsigned long voice_max_tx_cnt;
+
+ /* max delta time between 2 consecutive tx done routine in us */
+ unsigned long voice_max_tx_done_delta_time;
+ unsigned long voice_min_tx_done_delta_time;
+ struct timeval voice_tx_done_delta_time;
+ struct timeval voice_last_tx_done_ts;
+
+ /* max delta time between 2 consecutive tx done routine in us */
+ unsigned long voice_max_rx_rdy_delta_time;
+ unsigned long voice_min_rx_rdy_delta_time;
+ struct timeval voice_rx_rdy_delta_time;
+ struct timeval voice_last_rx_rdy_ts;
+
+ /* max delta time between 2 consecutive tx done routine in us */
+ unsigned long voice_max_rx_feeding_interval;
+ unsigned long voice_min_rx_feeding_interval;
+ struct timeval voice_rx_feeding_interval;
+ struct timeval voice_last_rx_feeding_ts;
+} tBTUSB_STATS;
+
+//
+// IOCTL definitions (shared among all user mode applications, do not modify)
+//
+#define IOCTL_BTWUSB_GET_STATS 0x1001
+#define IOCTL_BTWUSB_CLEAR_STATS 0x1002
+#define IOCTL_BTWUSB_PUT 0x1003
+#define IOCTL_BTWUSB_PUT_CMD 0x1004
+#define IOCTL_BTWUSB_GET 0x1005
+#define IOCTL_BTWUSB_GET_EVENT 0x1006
+#define IOCTL_BTWUSB_PUT_VOICE 0x1007
+#define IOCTL_BTWUSB_GET_VOICE 0x1008
+#define IOCTL_BTWUSB_ADD_VOICE_CHANNEL 0x1009
+#define IOCTL_BTWUSB_REMOVE_VOICE_CHANNEL 0x100a
+#define IOCTL_BTWUSB_DEV_RESET 0x100b
+
+#endif // BTUSBEXT_H
diff --git a/btusb_1_6_29_1/inc/data_types.h b/btusb_1_6_29_1/inc/data_types.h
new file mode 100755
index 0000000..e8ccf4b
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/data_types.h
@@ -0,0 +1,79 @@
+/*
+*
+* data_types.h
+*
+*
+*
+* Copyright (C) 2011 Broadcom Corporation.
+*
+*
+*
+* This software is licensed under the terms of the GNU General Public License,
+* version 2, as published by the Free Software Foundation (the "GPL"), and may
+* be copied, distributed, and modified under those terms.
+*
+* 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 GPL for more details.
+*
+*
+* A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+* or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA
+*
+*
+*/
+
+#ifndef DATA_TYPES_H
+#define DATA_TYPES_H
+
+#ifndef NULL
+#define NULL 0
+#endif
+
+#ifndef FALSE
+#define FALSE 0
+#endif
+
+typedef unsigned char UINT8;
+typedef unsigned short UINT16;
+typedef unsigned int UINT32, *PUINT32;
+typedef signed int INT32, *PINT32;
+typedef signed char INT8;
+typedef signed short INT16;
+
+
+#if defined(_WIDE_CHAR) || defined(_UNICODE)
+typedef unsigned short WIDECHAR; /* for _BT_WIN32 possibly use wchar_t */
+#define WIDE_NULL_CHAR ((WIDECHAR)0)
+#else
+typedef unsigned char WIDECHAR;
+#define WIDE_NULL_CHAR '\0'
+#endif
+
+typedef UINT32 TIME_STAMP;
+
+
+#ifndef _WINDOWS_VXD
+typedef unsigned char BOOLEAN;
+
+#ifndef TRUE
+#define TRUE (!FALSE)
+#endif
+#endif
+
+typedef unsigned char UBYTE;
+
+#define PACKED
+#define INLINE
+
+#ifndef BIG_ENDIAN
+#define BIG_ENDIAN FALSE
+#endif
+
+#define UINT16_LOW_BYTE(x) ((x) & 0xff)
+#define UINT16_HI_BYTE(x) ((x) >> 8)
+
+#define ARRAY_SIZEOF(x) (sizeof(x)/sizeof(x[0]))
+
+#endif
diff --git a/btusb_1_6_29_1/inc/gki.h b/btusb_1_6_29_1/inc/gki.h
new file mode 100755
index 0000000..8b04756
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/gki.h
@@ -0,0 +1,190 @@
+/*
+ *
+ * gki.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef GKI_H
+#define GKI_H
+
+#include "target.h"
+#include "data_types.h"
+
+//#define TRACE_GKI_BUFFERS
+
+/* Error codes */
+#define GKI_SUCCESS 0x00
+#define GKI_FAILURE 0x01
+#define GKI_INVALID_TASK 0xF0
+#define GKI_INVALID_POOL 0xFF
+
+
+
+/************************************************************************
+** Mailbox definitions. Each task has 4 mailboxes that are used to
+** send buffers to the task.
+*/
+#define TASK_MBOX_0 0
+#define TASK_MBOX_1 1
+#define TASK_MBOX_2 2
+#define TASK_MBOX_3 3
+
+#define NUM_TASK_MBOX 4
+
+/************************************************************************
+** Event definitions.
+**
+** There are 4 reserved events used to signal messages rcvd in task mailboxes.
+** There are 4 reserved events used to signal timeout events.
+** There are 8 general purpose events available for applications.
+*/
+#define MAX_EVENTS 16
+
+#define TASK_MBOX_0_EVT_MASK 0x0001
+#define TASK_MBOX_1_EVT_MASK 0x0002
+#define TASK_MBOX_2_EVT_MASK 0x0004
+#define TASK_MBOX_3_EVT_MASK 0x0008
+
+
+#define TIMER_0 0
+#define TIMER_1 1
+#define TIMER_2 2
+#define TIMER_3 3
+
+#define TIMER_0_EVT_MASK 0x0010
+#define TIMER_1_EVT_MASK 0x0020
+#define TIMER_2_EVT_MASK 0x0040
+#define TIMER_3_EVT_MASK 0x0080
+
+#define APPL_EVT_0 8
+#define APPL_EVT_1 9
+#define APPL_EVT_2 10
+#define APPL_EVT_3 11
+#define APPL_EVT_4 12
+#define APPL_EVT_5 13
+#define APPL_EVT_6 14
+#define APPL_EVT_7 15
+
+#define EVENT_MASK(evt) ((UINT16)(0x0001 << (evt)))
+
+/***********************************************************************
+** This queue is a general purpose buffer queue, for application use.
+*/
+typedef struct
+{
+ void *p_first;
+ void *p_last;
+ UINT16 count;
+} BUFFER_Q;
+
+#define GKI_IS_QUEUE_EMPTY(p_q) ((p_q)->count == 0)
+
+/* Task constants
+*/
+#ifndef TASKPTR_DEF
+#define TASKPTR_DEF
+#if defined (LINUX_KERNEL)
+typedef int (*TASKPTR)(UINT32);
+#else
+typedef void (*TASKPTR)(UINT32);
+#endif
+#endif
+
+#define GKI_PUBLIC_POOL 0 /* General pool accessible to GKI_getbuf() */
+#define GKI_RESTRICTED_POOL 1 /* Inaccessible pool to GKI_getbuf() */
+
+/***********************************************************************
+** Function prototypes
+*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Task management */
+BT_API extern void GKI_init(void);
+BT_API extern void GKI_shutdown(void);
+
+/* To get and release buffers, change owner and get size
+*/
+BT_API extern void GKI_change_buf_owner (void *, UINT8);
+BT_API extern UINT8 GKI_create_pool (UINT16, UINT16, UINT8, void *);
+BT_API extern void GKI_delete_pool (UINT8);
+BT_API extern void *GKI_find_buf_start (void *);
+BT_API extern void GKI_freebuf (void *);
+#ifdef TRACE_GKI_BUFFERS
+BT_API extern void *GKI_getbuf_trace (UINT16, char *, int);
+#define GKI_getbuf(_size) GKI_getbuf_trace(_size,__FILE__,__LINE__)
+#else
+BT_API extern void *GKI_getbuf (UINT16);
+#endif
+
+BT_API extern UINT16 GKI_get_buf_size (void *);
+BT_API extern UINT16 GKI_get_pool_bufsize (UINT8 pool_id);
+
+// For compatibility with BTE
+#define GKI_POOL_SIZE(x) GKI_get_pool_bufsize(x)
+
+
+#ifdef TRACE_GKI_BUFFERS
+BT_API extern void *GKI_getpoolbuf_trace (UINT8, char *, int);
+#define GKI_getpoolbuf(_pool) GKI_getpoolbuf_trace(_pool,__FILE__,__LINE__)
+#else
+BT_API extern void *GKI_getpoolbuf (UINT8);
+#endif
+
+BT_API extern UINT16 GKI_poolfreecount (UINT8);
+BT_API extern UINT16 GKI_poolutilization (UINT8);
+BT_API extern UINT8 GKI_set_pool_permission(UINT8, UINT8);
+
+
+/* User buffer queue management
+*/
+BT_API extern void *GKI_dequeue (BUFFER_Q *);
+BT_API extern UINT8 GKI_buffer_status(void *p_buf);
+BT_API extern void GKI_enqueue (BUFFER_Q *, void *);
+BT_API extern void GKI_enqueue_head (BUFFER_Q *, void *);
+BT_API extern void *GKI_getfirst (BUFFER_Q *);
+BT_API extern void *GKI_getnext (void *);
+BT_API extern void GKI_init_q (BUFFER_Q *);
+BT_API extern BOOLEAN GKI_queue_is_empty(BUFFER_Q *);
+BT_API extern void *GKI_remove_from_queue (BUFFER_Q *, void *);
+
+BT_API extern BOOLEAN GKI_chk_buf_pool_damage(UINT8 pool_id);
+
+/* Disable Interrupts, Enable Interrupts
+*/
+BT_API extern void GKI_enable(void);
+BT_API extern void GKI_disable(void);
+
+/* Exception handling
+*/
+BT_API extern void GKI_exception (UINT16, const char *msg, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#endif
+
diff --git a/btusb_1_6_29_1/inc/gki_int.h b/btusb_1_6_29_1/inc/gki_int.h
new file mode 100755
index 0000000..f210e58
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/gki_int.h
@@ -0,0 +1,197 @@
+/*
+ *
+ * gki_int.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef GKI_INT_H
+#define GKI_INT_H
+
+#include "gki.h"
+
+/* Task States: (For OSRdyTbl) */
+// TASK_DEAD is already defined by Linux => undefine it
+#ifdef TASK_DEAD
+#undef TASK_DEAD
+#endif
+
+#define TASK_DEAD 0 /* b0000 */
+#define TASK_READY 1 /* b0001 */
+#define TASK_WAIT 2 /* b0010 */
+#define TASK_DELAY 4 /* b0100 */
+#define TASK_SUSPEND 8 /* b1000 */
+
+
+/********************************************************************
+** Internal Error codes
+*********************************************************************/
+#define GKI_ERROR_BUF_CORRUPTED 0xFFFF
+#define GKI_ERROR_NOT_BUF_OWNER 0xFFFE
+#define GKI_ERROR_FREEBUF_BAD_QID 0xFFFD
+#define GKI_ERROR_FREEBUF_BUF_LINKED 0xFFFC
+#define GKI_ERROR_SEND_MSG_BAD_DEST 0xFFFB
+#define GKI_ERROR_SEND_MSG_BUF_LINKED 0xFFFA
+#define GKI_ERROR_ENQUEUE_BUF_LINKED 0xFFF9
+#define GKI_ERROR_DELETE_POOL_BAD_QID 0xFFF8
+#define GKI_ERROR_BUF_SIZE_TOOBIG 0xFFF7
+#define GKI_ERROR_BUF_SIZE_ZERO 0xFFF6
+#define GKI_ERROR_ADDR_NOT_IN_BUF 0xFFF5
+#define GKI_ERROR_BUF_POOL_CORRUPT 0xFFF4
+#define GKI_ERROR_BUFFER_TRACE_ON 0xFFF3
+#define GKI_ERROR_SEGS_EXCEEDED 0xFFF2
+#define GKI_ERROR_NO_MEMORY_FOR_SEG 0xFFF1
+
+
+/********************************************************************
+** Buffer Management Data Structures
+*********************************************************************/
+
+typedef struct _buffer_hdr
+{
+ struct _buffer_hdr *p_next;
+ UINT8 q_id;
+ UINT8 task_id;
+ UINT8 status;
+ UINT8 Type;
+#ifdef TRACE_GKI_BUFFERS
+ struct _buffer_hdr *p_next_all;
+ char *pFile;
+ int linenum;
+ UINT32 times_alloc;
+#endif
+} BUFFER_HDR_T;
+
+/* Allocate each buffer pool in up to 4 memory segments, for efficiency
+*/
+#define MAX_BUFFPOOL_SEGS 4
+
+typedef struct _free_queue
+{
+ UINT8 *seg_start[MAX_BUFFPOOL_SEGS];
+ UINT8 *seg_end[MAX_BUFFPOOL_SEGS];
+
+ BUFFER_HDR_T *p_first;
+ BUFFER_HDR_T *p_last;
+ UINT16 total;
+ UINT16 cur_cnt;
+ UINT16 max_cnt;
+#ifdef TRACE_GKI_BUFFERS
+ BUFFER_HDR_T *p_first_all;
+#endif
+} FREE_QUEUE_T;
+
+
+/* Buffer related defines
+*/
+#define BUFFER_HDR_SIZE (sizeof(BUFFER_HDR_T)) /* Offset past header */
+#define BUFFER_PADDING_SIZE (sizeof(BUFFER_HDR_T) + sizeof(UINT32)) /* Header + Magic Number */
+#define MAX_USER_BUF_SIZE ((UINT16)0xffff - BUFFER_PADDING_SIZE) /* pool size must allow for header */
+#define MAGIC_NO 0xDDBADDBA
+
+#define BUF_STATUS_FREE 0
+#define BUF_STATUS_UNLINKED 1
+#define BUF_STATUS_QUEUED 2
+
+/* Exception related structures
+*/
+#define MAX_EXCEPTION 8
+#define MAX_EXCEPTION_MSGLEN 64
+
+typedef struct
+{
+ UINT16 type;
+ UINT8 taskid;
+ UINT8 msg[MAX_EXCEPTION_MSGLEN];
+} EXCEPTION_T;
+
+
+/* Put all GKI variables into one control block
+*/
+typedef struct
+{
+ /* Task management variables
+ */
+ /* The stack and stack size are not used on Windows
+ */
+#if (GKI_USE_DYNAMIC_BUFFERS == FALSE)
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ UINT8 bufpool0[(GKI_BUF0_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF0_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ UINT8 bufpool1[(GKI_BUF1_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF1_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ UINT8 bufpool2[(GKI_BUF2_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF2_MAX];
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ UINT8 bufpool3[(GKI_BUF3_SIZE + BUFFER_PADDING_SIZE) * GKI_BUF3_MAX];
+#endif
+
+#endif
+
+ INT IsRunning;
+
+ /* Define the buffer pool management variables
+ */
+ FREE_QUEUE_T freeq[GKI_NUM_TOTAL_BUF_POOLS];
+
+ UINT16 pool_buf_size[GKI_NUM_TOTAL_BUF_POOLS];
+ UINT16 pool_max_count[GKI_NUM_TOTAL_BUF_POOLS];
+ UINT16 pool_additions[GKI_NUM_TOTAL_BUF_POOLS];
+
+ UINT16 ExceptionCnt;
+ EXCEPTION_T Exception[MAX_EXCEPTION];
+
+ /* Define the buffer pool access control variables */
+ UINT16 pool_access_mask;
+ UINT8 pool_list[GKI_NUM_TOTAL_BUF_POOLS]; /* buffer pools arranged in the order of size */
+ int curr_total_no_of_pools;
+} tGKI_CB;
+
+
+void gki_buffer_init(void);
+BOOLEAN gki_chk_buf_damage(void *p_buf);
+void *gki_reserve_os_memory (UINT32 size);
+void gki_release_os_memory (void *p_mem);
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _BT_DYNAMIC_MEMORY
+extern tGKI_CB gki_cb;
+#else
+extern tGKI_CB *gp_gki_cb;
+#define gki_cb (*gp_gki_cb)
+#endif
+
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/btusb_1_6_29_1/inc/hcidefs.h b/btusb_1_6_29_1/inc/hcidefs.h
new file mode 100755
index 0000000..ec2e802
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/hcidefs.h
@@ -0,0 +1,1819 @@
+/*
+*
+* hcidefs.h
+*
+*
+*
+* Copyright (C) 2011 Broadcom Corporation.
+*
+*
+*
+* This software is licensed under the terms of the GNU General Public License,
+* version 2, as published by the Free Software Foundation (the "GPL"), and may
+* be copied, distributed, and modified under those terms.
+*
+* 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 GPL for more details.
+*
+*
+* A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+* or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+* Boston, MA 02111-1307, USA
+*
+*
+*/
+
+#ifndef HCIDEFS_H
+#define HCIDEFS_H
+
+#define HCI_PROTO_VERSION 0x01 /* Version for BT spec 1.1 */
+#define HCI_PROTO_VERSION_1_2 0x02 /* Version for BT spec 1.2 */
+#define HCI_PROTO_VERSION_2_0 0x03 /* Version for BT spec 2.0 */
+#define HCI_PROTO_VERSION_2_1 0x04 /* Version for BT spec 2.1 [Lisbon] */
+#define HCI_PROTO_REVISION 0x000C /* Current implementation version */
+/*
+** Definitions for HCI groups
+*/
+#define HCI_GRP_LINK_CONTROL_CMDS (0x01 << 10)
+#define HCI_GRP_LINK_POLICY_CMDS (0x02 << 10)
+#define HCI_GRP_HOST_CONT_BASEBAND_CMDS (0x03 << 10)
+#define HCI_GRP_INFORMATIONAL_PARAMS (0x04 << 10)
+#define HCI_GRP_STATUS_PARAMS (0x05 << 10)
+#define HCI_GRP_TESTING_CMDS (0x06 << 10)
+#define HCI_GRP_L2CAP_CMDS (0x07 << 10)
+#define HCI_GRP_L2CAP_HCI_EVTS (0x08 << 10)
+
+#define HCI_GRP_VENDOR_SPECIFIC (0x3F << 10)
+
+/* Group occupies high 6 bits of the HCI command rest is opcode itself */
+#define HCI_OGF(p) (UINT8)((0xFC00 & (p)) >> 10)
+#define HCI_OCF(p) ( 0x3FF & (p))
+
+/*
+** Defentions for Link Control Commands
+*/
+/* Following opcode is used only in command complete event for flow control */
+#define HCI_COMMAND_NONE 0x0000
+
+/* Commands of HCI_GRP_LINK_CONTROL_CMDS group */
+#define HCI_INQUIRY (0x0001 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_INQUIRY_CANCEL (0x0002 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_PERIODIC_INQUIRY_MODE (0x0003 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_EXIT_PERIODIC_INQUIRY_MODE (0x0004 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CREATE_CONNECTION (0x0005 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_DISCONNECT (0x0006 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ADD_SCO_CONNECTION (0x0007 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CREATE_CONNECTION_CANCEL (0x0008 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ACCEPT_CONNECTION_REQUEST (0x0009 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REJECT_CONNECTION_REQUEST (0x000A | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_LINK_KEY_REQUEST_REPLY (0x000B | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_LINK_KEY_REQUEST_NEG_REPLY (0x000C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_PIN_CODE_REQUEST_REPLY (0x000D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_PIN_CODE_REQUEST_NEG_REPLY (0x000E | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CHANGE_CONN_PACKET_TYPE (0x000F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_AUTHENTICATION_REQUESTED (0x0011 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_SET_CONN_ENCRYPTION (0x0013 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_CHANGE_CONN_LINK_KEY (0x0015 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_MASTER_LINK_KEY (0x0017 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RMT_NAME_REQUEST (0x0019 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_RMT_NAME_REQUEST_CANCEL (0x001A | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_FEATURES (0x001B | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_EXT_FEATURES (0x001C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_VERSION_INFO (0x001D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_RMT_CLOCK_OFFSET (0x001F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_READ_LMP_HANDLE (0x0020 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_SETUP_ESCO_CONNECTION (0x0028 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_ACCEPT_ESCO_CONNECTION (0x0029 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REJECT_ESCO_CONNECTION (0x002A | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_IO_CAPABILITY_RESPONSE (0x002B | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_CONF_REQUEST_REPLY (0x002C | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_CONF_VALUE_NEG_REPLY (0x002D | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_PASSKEY_REQ_REPLY (0x002E | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_USER_PASSKEY_REQ_NEG_REPLY (0x002F | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REM_OOB_DATA_REQ_REPLY (0x0030 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_REM_OOB_DATA_REQ_NEG_REPLY (0x0033 | HCI_GRP_LINK_CONTROL_CMDS)
+#define HCI_IO_CAP_REQ_NEG_REPLY (0x0034 | HCI_GRP_LINK_CONTROL_CMDS)
+
+#define HCI_LINK_CTRL_CMDS_FIRST HCI_INQUIRY
+#define HCI_LINK_CTRL_CMDS_LAST HCI_IO_CAP_REQ_NEG_REPLY
+
+/* Commands of HCI_GRP_LINK_POLICY_CMDS */
+#define HCI_HOLD_MODE (0x0001 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_SNIFF_MODE (0x0003 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_EXIT_SNIFF_MODE (0x0004 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_PARK_MODE (0x0005 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_EXIT_PARK_MODE (0x0006 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_QOS_SETUP (0x0007 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_ROLE_DISCOVERY (0x0009 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_SWITCH_ROLE (0x000B | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_READ_POLICY_SETTINGS (0x000C | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_WRITE_POLICY_SETTINGS (0x000D | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_READ_DEF_POLICY_SETTINGS (0x000E | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_WRITE_DEF_POLICY_SETTINGS (0x000F | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_FLOW_SPECIFICATION (0x0010 | HCI_GRP_LINK_POLICY_CMDS)
+#define HCI_SNIFF_SUB_RATE (0x0011 | HCI_GRP_LINK_POLICY_CMDS)
+
+#define HCI_LINK_POLICY_CMDS_FIRST HCI_HOLD_MODE
+#define HCI_LINK_POLICY_CMDS_LAST HCI_SNIFF_SUB_RATE
+
+
+/* Commands of HCI_GRP_HOST_CONT_BASEBAND_CMDS */
+#define HCI_SET_EVENT_MASK (0x0001 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_RESET (0x0003 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_EVENT_FILTER (0x0005 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_FLUSH (0x0008 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PIN_TYPE (0x0009 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PIN_TYPE (0x000A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_CREATE_NEW_UNIT_KEY (0x000B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_STORED_LINK_KEY (0x000D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_STORED_LINK_KEY (0x0011 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_DELETE_STORED_LINK_KEY (0x0012 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_CHANGE_LOCAL_NAME (0x0013 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_LOCAL_NAME (0x0014 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_CONN_ACCEPT_TOUT (0x0015 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CONN_ACCEPT_TOUT (0x0016 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGE_TOUT (0x0017 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGE_TOUT (0x0018 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SCAN_ENABLE (0x0019 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SCAN_ENABLE (0x001A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_CFG (0x001B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_CFG (0x001C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_INQUIRYSCAN_CFG (0x001D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQUIRYSCAN_CFG (0x001E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_AUTHENTICATION_ENABLE (0x001F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_AUTHENTICATION_ENABLE (0x0020 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_ENCRYPTION_MODE (0x0021 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_ENCRYPTION_MODE (0x0022 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_CLASS_OF_DEVICE (0x0023 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CLASS_OF_DEVICE (0x0024 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_VOICE_SETTINGS (0x0025 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_VOICE_SETTINGS (0x0026 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_AUTO_FLUSH_TOUT (0x0027 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_AUTO_FLUSH_TOUT (0x0028 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_NUM_BCAST_REXMITS (0x0029 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_NUM_BCAST_REXMITS (0x002A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_HOLD_MODE_ACTIVITY (0x002B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_HOLD_MODE_ACTIVITY (0x002C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_TRANSMIT_POWER_LEVEL (0x002D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SCO_FLOW_CTRL_ENABLE (0x002E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SCO_FLOW_CTRL_ENABLE (0x002F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_HC_TO_HOST_FLOW_CTRL (0x0031 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_HOST_BUFFER_SIZE (0x0033 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_HOST_NUM_PACKETS_DONE (0x0035 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_LINK_SUPER_TOUT (0x0036 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_LINK_SUPER_TOUT (0x0037 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_NUM_SUPPORTED_IAC (0x0038 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_CURRENT_IAC_LAP (0x0039 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_CURRENT_IAC_LAP (0x003A | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_PERIOD_MODE (0x003B | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_PERIOD_MODE (0x003C | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_MODE (0x003D | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_MODE (0x003E | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SET_AFH_CHANNELS (0x003F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+#define HCI_READ_INQSCAN_TYPE (0x0042 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQSCAN_TYPE (0x0043 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_INQUIRY_MODE (0x0044 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQUIRY_MODE (0x0045 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_PAGESCAN_TYPE (0x0046 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_PAGESCAN_TYPE (0x0047 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_AFH_ASSESSMENT_MODE (0x0048 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_AFH_ASSESSMENT_MODE (0x0049 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_EXT_INQ_RESPONSE (0x0051 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_EXT_INQ_RESPONSE (0x0052 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_REFRESH_ENCRYPTION_KEY (0x0053 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_SIMPLE_PAIRING_MODE (0x0055 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_SIMPLE_PAIRING_MODE (0x0056 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_LOCAL_OOB_DATA (0x0057 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_READ_INQ_TX_POWER_LEVEL (0x0058 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_WRITE_INQ_TX_POWER_LEVEL (0x0059 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+#define HCI_SEND_KEYPRESS_NOTIF (0x0060 | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+#define HCI_ENHANCED_FLUSH (0x005F | HCI_GRP_HOST_CONT_BASEBAND_CMDS)
+
+#define HCI_CONT_BASEBAND_CMDS_FIRST HCI_SET_EVENT_MASK
+#define HCI_CONT_BASEBAND_CMDS_LAST HCI_SEND_KEYPRESS_NOTIF
+
+
+/* Commands of HCI_GRP_INFORMATIONAL_PARAMS group */
+#define HCI_READ_LOCAL_VERSION_INFO (0x0001 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_SUPPORTED_CMDS (0x0002 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_FEATURES (0x0003 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_LOCAL_EXT_FEATURES (0x0004 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_BUFFER_SIZE (0x0005 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_COUNTRY_CODE (0x0007 | HCI_GRP_INFORMATIONAL_PARAMS)
+#define HCI_READ_BD_ADDR (0x0009 | HCI_GRP_INFORMATIONAL_PARAMS)
+
+#define HCI_INFORMATIONAL_CMDS_FIRST HCI_READ_LOCAL_VERSION_INFO
+#define HCI_INFORMATIONAL_CMDS_LAST HCI_READ_BD_ADDR
+
+
+/* Commands of HCI_GRP_STATUS_PARAMS group */
+#define HCI_READ_FAILED_CONTACT_COUNT (0x0001 | HCI_GRP_STATUS_PARAMS)
+#define HCI_RESET_FAILED_CONTACT_COUNT (0x0002 | HCI_GRP_STATUS_PARAMS)
+#define HCI_GET_LINK_QUALITY (0x0003 | HCI_GRP_STATUS_PARAMS)
+#define HCI_READ_RSSI (0x0005 | HCI_GRP_STATUS_PARAMS)
+#define HCI_READ_AFH_CH_MAP (0x0006 | HCI_GRP_STATUS_PARAMS)
+#define HCI_READ_CLOCK (0x0007 | HCI_GRP_STATUS_PARAMS)
+
+#define HCI_STATUS_PARAMS_CMDS_FIRST HCI_READ_FAILED_CONTACT_COUNT
+#define HCI_STATUS_PARAMS_CMDS_LAST HCI_READ_CLOCK
+
+/* Commands of HCI_GRP_TESTING_CMDS group */
+#define HCI_READ_LOOPBACK_MODE (0x0001 | HCI_GRP_TESTING_CMDS)
+#define HCI_WRITE_LOOPBACK_MODE (0x0002 | HCI_GRP_TESTING_CMDS)
+#define HCI_ENABLE_DEV_UNDER_TEST_MODE (0x0003 | HCI_GRP_TESTING_CMDS)
+#define HCI_WRITE_SIMP_PAIR_DEBUG_MODE (0x0004 | HCI_GRP_TESTING_CMDS)
+
+#define HCI_TESTING_CMDS_FIRST HCI_READ_LOOPBACK_MODE
+#define HCI_TESTING_CMDS_LAST HCI_WRITE_SIMP_PAIR_DEBUG_MODE
+
+#define HCI_VENDOR_CMDS_FIRST 0x0001
+#define HCI_VENDOR_CMDS_LAST 0xFFFF
+
+
+/* Vendor specific commands for BRCM chipset */
+#define HCI_BRCM_UPDATE_BAUD_RATE_ENCODED_LENGTH 0x02
+#define HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH 0x06
+#define HCI_BRCM_WRITE_SLEEP_MODE_LENGTH 10
+#define HCI_BRCM_FM_OPCODE (0x0015 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_UPDATE_BAUDRATE_CMD (0x0018 | HCI_GRP_VENDOR_SPECIFIC) /* set baudrate of BCM2035 */
+#define HCI_BRCM_WRITE_SLEEP_MODE (0x0027 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_READ_SLEEP_MODE (0x0028 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_H4IBSS_CMD (0x0029 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_DOWNLOAD_MINI_DRV (0x002E | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_READ_USER_DEFINED_NVRAM (0x0033 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_ENABLE_RADIO (0x0034 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_READ_DIAGNOSTIC_VALUE (0x0035 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_GET_HID_DEVICE_LIST (0x0036 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_ADD_HID_DEVICE (0x0037 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_WRITE_HID_DEVICE_NVRAM (0x0038 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_DELETE_HID_DEVICE (0x0039 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_ENABLE_USB_HID_EMULATION (0x003B | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_BTW_STARTUP (0x0053 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_SET_ACL_PRIORITY (0x0057 | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_WRITE_RAM (0x004C | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_LAUNCH_RAM (0x004E | HCI_GRP_VENDOR_SPECIFIC)
+
+/* Dual Stack */
+#define HCI_BRCM_PAUSE_TRANSPORT (0x007A | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_TRANSPORT_RESUME (0x007B | HCI_GRP_VENDOR_SPECIFIC)
+#define HCI_BRCM_TRANSPORT_ERROR_EVT 0x0C
+
+/* Parameter information for HCI_BRCM_SET_ACL_PRIORITY */
+#define HCI_BRCM_ACL_PRIORITY_PARAM_SIZE 3
+#define HCI_BRCM_ACL_PRIORITY_LOW 0x00
+#define HCI_BRCM_ACL_PRIORITY_HIGH 0xFF
+
+#define HCI_BRCM_UPDATE_BAUD_RATE_ENCODED_LENGTH 0x02
+#define HCI_BRCM_UPDATE_BAUD_RATE_UNENCODED_LENGTH 0x06
+#define HCI_BRCM_WRITE_SLEEP_MODE_LENGTH 10
+#define HCI_BRCM_PAUSE_TRANSPORT_LENGTH 6
+
+/* Broadcom-specific SCO routing */
+#define HCI_BRCM_Write_SCO_PCM_Int_Params (0x001c | HCI_GRP_VENDOR_SPECIFIC)
+#define BRCM_SCO_PCM_Int_Params_ROUTING_PCM 0
+#define BRCM_SCO_PCM_Int_Params_ROUTING_TRANSPORT 1
+
+#define HCI_BRCM_SYNC_PACKET_TYPE (0x006B | HCI_GRP_VENDOR_SPECIFIC)
+
+#define HCI_BRCM_UIPC_OVER_HCI (0x008B | HCI_GRP_VENDOR_SPECIFIC)
+
+/*
+** Definitions for HCI Events
+*/
+#define HCI_INQUIRY_COMP_EVT 0x01
+#define HCI_INQUIRY_RESULT_EVT 0x02
+#define HCI_CONNECTION_COMP_EVT 0x03
+#define HCI_CONNECTION_REQUEST_EVT 0x04
+#define HCI_DISCONNECTION_COMP_EVT 0x05
+#define HCI_AUTHENTICATION_COMP_EVT 0x06
+#define HCI_RMT_NAME_REQUEST_COMP_EVT 0x07
+#define HCI_ENCRYPTION_CHANGE_EVT 0x08
+#define HCI_CHANGE_CONN_LINK_KEY_EVT 0x09
+#define HCI_MASTER_LINK_KEY_COMP_EVT 0x0A
+#define HCI_READ_RMT_FEATURES_COMP_EVT 0x0B
+#define HCI_READ_RMT_VERSION_COMP_EVT 0x0C
+#define HCI_QOS_SETUP_COMP_EVT 0x0D
+#define HCI_COMMAND_COMPLETE_EVT 0x0E
+#define HCI_COMMAND_STATUS_EVT 0x0F
+#define HCI_HARDWARE_ERROR_EVT 0x10
+#define HCI_FLUSH_OCCURED_EVT 0x11
+#define HCI_ROLE_CHANGE_EVT 0x12
+#define HCI_NUM_COMPL_DATA_PKTS_EVT 0x13
+#define HCI_MODE_CHANGE_EVT 0x14
+#define HCI_RETURN_LINK_KEYS_EVT 0x15
+#define HCI_PIN_CODE_REQUEST_EVT 0x16
+#define HCI_LINK_KEY_REQUEST_EVT 0x17
+#define HCI_LINK_KEY_NOTIFICATION_EVT 0x18
+#define HCI_LOOPBACK_COMMAND_EVT 0x19
+#define HCI_DATA_BUF_OVERFLOW_EVT 0x1A
+#define HCI_MAX_SLOTS_CHANGED_EVT 0x1B
+#define HCI_READ_CLOCK_OFF_COMP_EVT 0x1C
+#define HCI_CONN_PKT_TYPE_CHANGE_EVT 0x1D
+#define HCI_QOS_VIOLATION_EVT 0x1E
+#define HCI_PAGE_SCAN_MODE_CHANGE_EVT 0x1F
+#define HCI_PAGE_SCAN_REP_MODE_CHNG_EVT 0x20
+#define HCI_FLOW_SPECIFICATION_COMP_EVT 0x21
+#define HCI_INQUIRY_RSSI_RESULT_EVT 0x22
+#define HCI_READ_RMT_EXT_FEATURES_COMP_EVT 0x23
+#define HCI_ESCO_CONNECTION_COMP_EVT 0x2C
+#define HCI_ESCO_CONNECTION_CHANGED_EVT 0x2D
+#define HCI_SNIFF_SUB_RATE_EVT 0x2E
+#define HCI_EXTENDED_INQUIRY_RESULT_EVT 0x2F
+#define HCI_ENCRYPTION_KEY_REFRESH_COMP_EVT 0x30
+#define HCI_IO_CAPABILITY_REQUEST_EVT 0x31
+#define HCI_IO_CAPABILITY_RESPONSE_EVT 0x32
+#define HCI_USER_CONFIRMATION_REQUEST_EVT 0x33
+#define HCI_USER_PASSKEY_REQUEST_EVT 0x34
+#define HCI_REMOTE_OOB_DATA_REQUEST_EVT 0x35
+#define HCI_SIMPLE_PAIRING_COMPLETE_EVT 0x36
+#define HCI_LINK_SUPER_TOUT_CHANGED_EVT 0x38
+#define HCI_ENHANCED_FLUSH_COMPLETE_EVT 0x39
+#define HCI_USER_PASSKEY_NOTIFY_EVT 0x3B
+#define HCI_KEYPRESS_NOTIFY_EVT 0x3C
+#define HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT 0x3D
+
+#define HCI_EVENT_RSP_FIRST HCI_INQUIRY_COMP_EVT
+#define HCI_EVENT_RSP_LAST HCI_RMT_HOST_SUP_FEAT_NOTIFY_EVT
+
+#define HCI_BRCM_H4IBSS_EVT 0xEF /* Vendor specific events for H4IBSS */
+#define HCI_VENDOR_SPECIFIC_EVT 0xFF /* Vendor specific events */
+#define HCI_NAP_TRACE_EVT 0xFF /* was define 0xFE, 0xFD, change to 0xFF
+ because conflict w/ TCI_EVT and per
+ specification compliant */
+
+/*
+** Defentions for HCI Error Codes that are past in the events
+*/
+#define HCI_SUCCESS 0x00
+#define HCI_PENDING 0x00
+#define HCI_ERR_ILLEGAL_COMMAND 0x01
+#define HCI_ERR_NO_CONNECTION 0x02
+#define HCI_ERR_HW_FAILURE 0x03
+#define HCI_ERR_PAGE_TIMEOUT 0x04
+#define HCI_ERR_AUTH_FAILURE 0x05
+#define HCI_ERR_KEY_MISSING 0x06
+#define HCI_ERR_MEMORY_FULL 0x07
+#define HCI_ERR_CONNECTION_TOUT 0x08
+#define HCI_ERR_MAX_NUM_OF_CONNECTIONS 0x09
+#define HCI_ERR_MAX_NUM_OF_SCOS 0x0A
+#define HCI_ERR_CONNECTION_EXISTS 0x0B
+#define HCI_ERR_COMMAND_DISALLOWED 0x0C
+#define HCI_ERR_HOST_REJECT_RESOURCES 0x0D
+#define HCI_ERR_HOST_REJECT_SECURITY 0x0E
+#define HCI_ERR_HOST_REJECT_DEVICE 0x0F
+#define HCI_ERR_HOST_TIMEOUT 0x10
+#define HCI_ERR_UNSUPPORTED_VALUE 0x11
+#define HCI_ERR_ILLEGAL_PARAMETER_FMT 0x12
+#define HCI_ERR_PEER_USER 0x13
+#define HCI_ERR_PEER_LOW_RESOURCES 0x14
+#define HCI_ERR_PEER_POWER_OFF 0x15
+#define HCI_ERR_CONN_CAUSE_LOCAL_HOST 0x16
+#define HCI_ERR_REPEATED_ATTEMPTS 0x17
+#define HCI_ERR_PAIRING_NOT_ALLOWED 0x18
+#define HCI_ERR_UNKNOWN_LMP_PDU 0x19
+#define HCI_ERR_UNSUPPORTED_REM_FEATURE 0x1A
+#define HCI_ERR_SCO_OFFSET_REJECTED 0x1B
+#define HCI_ERR_SCO_INTERVAL_REJECTED 0x1C
+#define HCI_ERR_SCO_AIR_MODE 0x1D
+#define HCI_ERR_INVALID_LMP_PARAM 0x1E
+#define HCI_ERR_UNSPECIFIED 0x1F
+#define HCI_ERR_UNSUPPORTED_LMP_FEATURE 0x20
+#define HCI_ERR_ROLE_CHANGE_NOT_ALLOWED 0x21
+#define HCI_ERR_LMP_RESPONSE_TIMEOUT 0x22
+#define HCI_ERR_LMP_ERR_TRANS_COLLISION 0x23
+#define HCI_ERR_LMP_PDU_NOT_ALLOWED 0x24
+#define HCI_ERR_ENCRY_MODE_NOT_ACCEPTABLE 0x25
+#define HCI_ERR_UNIT_KEY_USED 0x26
+#define HCI_ERR_QOS_NOT_SUPPORTED 0x27
+#define HCI_ERR_INSTANT_PASSED 0x28
+#define HCI_ERR_PAIRING_WITH_UNIT_KEY_NOT_SUPPORTED 0x29
+#define HCI_ERR_DIFF_TRANSACTION_COLLISION 0x2A
+#define HCI_ERR_UNDEFINED_0x2B 0x2B
+#define HCI_ERR_QOS_UNACCEPTABLE_PARAM 0x2C
+#define HCI_ERR_QOS_REJECTED 0x2D
+#define HCI_ERR_CHAN_CLASSIF_NOT_SUPPORTED 0x2E
+#define HCI_ERR_INSUFFCIENT_SECURITY 0x2F
+#define HCI_ERR_PARAM_OUT_OF_RANGE 0x30
+#define HCI_ERR_UNDEFINED_0x31 0x31
+#define HCI_ERR_ROLE_SWITCH_PENDING 0x32
+#define HCI_ERR_UNDEFINED_0x33 0x33
+#define HCI_ERR_RESERVED_SLOT_VIOLATION 0x34
+#define HCI_ERR_ROLE_SWITCH_FAILED 0x35
+#define HCI_ERR_INQ_RSP_DATA_TOO_LARGE 0x36
+#define HCI_ERR_SIMPLE_PAIRING_NOT_SUPPORTED 0x37
+#define HCI_ERR_HOST_BUSY_PAIRING 0x38
+
+#define HCI_ERR_MAX_ERR 0x38
+
+/*
+** Definitions for HCI enable event
+*/
+#define HCI_INQUIRY_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000001)
+#define HCI_INQUIRY_RESULT_EV(p) (*((UINT32 *)(p)) & 0x00000002)
+#define HCI_CONNECTION_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000004)
+#define HCI_CONNECTION_REQUEST_EV(p) (*((UINT32 *)(p)) & 0x00000008)
+#define HCI_DISCONNECTION_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000010)
+#define HCI_AUTHENTICATION_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000020)
+#define HCI_RMT_NAME_REQUEST_COMPL_EV(p) (*((UINT32 *)(p)) & 0x00000040)
+#define HCI_CHANGE_CONN_ENCRPT_ENABLE_EV(p) (*((UINT32 *)(p)) & 0x00000080)
+#define HCI_CHANGE_CONN_LINK_KEY_EV(p) (*((UINT32 *)(p)) & 0x00000100)
+#define HCI_MASTER_LINK_KEY_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00000200)
+#define HCI_READ_RMT_FEATURES_COMPL_EV(p) (*((UINT32 *)(p)) & 0x00000400)
+#define HCI_READ_RMT_VERSION_COMPL_EV(p) (*((UINT32 *)(p)) & 0x00000800)
+#define HCI_QOS_SETUP_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00001000)
+#define HCI_COMMAND_COMPLETE_EV(p) (*((UINT32 *)(p)) & 0x00002000)
+#define HCI_COMMAND_STATUS_EV(p) (*((UINT32 *)(p)) & 0x00004000)
+#define HCI_HARDWARE_ERROR_EV(p) (*((UINT32 *)(p)) & 0x00008000)
+#define HCI_FLASH_OCCURED_EV(p) (*((UINT32 *)(p)) & 0x00010000)
+#define HCI_ROLE_CHANGE_EV(p) (*((UINT32 *)(p)) & 0x00020000)
+#define HCI_NUM_COMPLETED_PKTS_EV(p) (*((UINT32 *)(p)) & 0x00040000)
+#define HCI_MODE_CHANGE_EV(p) (*((UINT32 *)(p)) & 0x00080000)
+#define HCI_RETURN_LINK_KEYS_EV(p) (*((UINT32 *)(p)) & 0x00100000)
+#define HCI_PIN_CODE_REQUEST_EV(p) (*((UINT32 *)(p)) & 0x00200000)
+#define HCI_LINK_KEY_REQUEST_EV(p) (*((UINT32 *)(p)) & 0x00400000)
+#define HCI_LINK_KEY_NOTIFICATION_EV(p) (*((UINT32 *)(p)) & 0x00800000)
+#define HCI_LOOPBACK_COMMAND_EV(p) (*((UINT32 *)(p)) & 0x01000000)
+#define HCI_DATA_BUF_OVERFLOW_EV(p) (*((UINT32 *)(p)) & 0x02000000)
+#define HCI_MAX_SLOTS_CHANGE_EV(p) (*((UINT32 *)(p)) & 0x04000000)
+#define HCI_READ_CLOCK_OFFSET_COMP_EV(p) (*((UINT32 *)(p)) & 0x08000000)
+#define HCI_CONN_PKT_TYPE_CHANGED_EV(p) (*((UINT32 *)(p)) & 0x10000000)
+#define HCI_QOS_VIOLATION_EV(p) (*((UINT32 *)(p)) & 0x20000000)
+#define HCI_PAGE_SCAN_MODE_CHANGED_EV(p) (*((UINT32 *)(p)) & 0x40000000)
+#define HCI_PAGE_SCAN_REP_MODE_CHNG_EV(p) (*((UINT32 *)(p)) & 0x80000000)
+
+/* the default event mask for 2.1+EDR (Lisbon) does not include Lisbon events */
+#define HCI_DEFAULT_EVENT_MASK_0 0xFFFFFFFF
+#define HCI_DEFAULT_EVENT_MASK_1 0x00001FFF
+
+/* the event mask for 2.1+EDR include Lisbon events */
+#define HCI_LISBON_EVENT_MASK_0 0xFFFFFFFF
+#define HCI_LISBON_EVENT_MASK_1 0x1DBFFFFF
+#define HCI_LISBON_EVENT_MASK "\x0D\xBF\xFF\xFF\xFF\xFF\xFF\xFF"
+#define HCI_LISBON_EVENT_MASK_EXT "\x1D\xBF\xFF\xFF\xFF\xFF\xFF\xFF"
+/* 0x00001FFF FFFFFFFF Default - no Lisbon events
+ 0x00002000 00000000 Sniff Subrate Event
+ 0x00004000 00000000 Extended Inquiry Result Event
+ 0x00008000 00000000 Encryption Key Refresh Complete Event
+ 0x00010000 00000000 IO Capability Request Event
+ 0x00020000 00000000 IO Capability Response Event
+ 0x00040000 00000000 User Confirmation Request Event
+ 0x00080000 00000000 User Passkey Request Event
+ 0x00100000 00000000 Remote OOB Data Request Event
+ 0x00200000 00000000 Simple Pairing Complete Event
+ 0x00800000 00000000 Link Supervision Timeout Changed Event
+ 0x01000000 00000000 Enhanced Flush Complete Event
+ 0x04000000 00000000 User Passkey Notification Event
+ 0x08000000 00000000 Keypress Notification Event
+ 0x10000000 00000000 Remote Host Supported Features Notification Event
+ */
+
+/*
+** Definitions for packet type masks (BT1.2 and BT2.0 definitions)
+*/
+#define HCI_PKT_TYPES_MASK_NO_2_DH1 0x0002
+#define HCI_PKT_TYPES_MASK_NO_3_DH1 0x0004
+#define HCI_PKT_TYPES_MASK_DM1 0x0008
+#define HCI_PKT_TYPES_MASK_DH1 0x0010
+#define HCI_PKT_TYPES_MASK_HV1 0x0020
+#define HCI_PKT_TYPES_MASK_HV2 0x0040
+#define HCI_PKT_TYPES_MASK_HV3 0x0080
+#define HCI_PKT_TYPES_MASK_NO_2_DH3 0x0100
+#define HCI_PKT_TYPES_MASK_NO_3_DH3 0x0200
+#define HCI_PKT_TYPES_MASK_DM3 0x0400
+#define HCI_PKT_TYPES_MASK_DH3 0x0800
+#define HCI_PKT_TYPES_MASK_NO_2_DH5 0x1000
+#define HCI_PKT_TYPES_MASK_NO_3_DH5 0x2000
+#define HCI_PKT_TYPES_MASK_DM5 0x4000
+#define HCI_PKT_TYPES_MASK_DH5 0x8000
+
+/* Packet type should be one of valid but at least one should be specified */
+#define HCI_VALID_SCO_PKT_TYPE(t) (((((t) & ~(HCI_PKT_TYPES_MASK_HV1 \
+ | HCI_PKT_TYPES_MASK_HV2 \
+ | HCI_PKT_TYPES_MASK_HV3)) == 0)) \
+ && ((t) != 0))
+
+
+
+
+
+/* Packet type should not be invalid and at least one should be specified */
+#define HCI_VALID_ACL_PKT_TYPE(t) (((((t) & ~(HCI_PKT_TYPES_MASK_DM1 \
+ | HCI_PKT_TYPES_MASK_DH1 \
+ | HCI_PKT_TYPES_MASK_DM3 \
+ | HCI_PKT_TYPES_MASK_DH3 \
+ | HCI_PKT_TYPES_MASK_DM5 \
+ | HCI_PKT_TYPES_MASK_DH5 \
+ | HCI_PKT_TYPES_MASK_NO_2_DH1 \
+ | HCI_PKT_TYPES_MASK_NO_3_DH1 \
+ | HCI_PKT_TYPES_MASK_NO_2_DH3 \
+ | HCI_PKT_TYPES_MASK_NO_3_DH3 \
+ | HCI_PKT_TYPES_MASK_NO_2_DH5 \
+ | HCI_PKT_TYPES_MASK_NO_3_DH5 )) == 0)) \
+ && (((t) & (HCI_PKT_TYPES_MASK_DM1 \
+ | HCI_PKT_TYPES_MASK_DH1 \
+ | HCI_PKT_TYPES_MASK_DM3 \
+ | HCI_PKT_TYPES_MASK_DH3 \
+ | HCI_PKT_TYPES_MASK_DM5 \
+ | HCI_PKT_TYPES_MASK_DH5)) != 0))
+
+
+
+/*
+** Definitions for eSCO packet type masks (BT1.2 and BT2.0 definitions)
+*/
+#define HCI_ESCO_PKT_TYPES_MASK_HV1 0x0001
+#define HCI_ESCO_PKT_TYPES_MASK_HV2 0x0002
+#define HCI_ESCO_PKT_TYPES_MASK_HV3 0x0004
+#define HCI_ESCO_PKT_TYPES_MASK_EV3 0x0008
+#define HCI_ESCO_PKT_TYPES_MASK_EV4 0x0010
+#define HCI_ESCO_PKT_TYPES_MASK_EV5 0x0020
+#define HCI_ESCO_PKT_TYPES_MASK_NO_2_EV3 0x0040
+#define HCI_ESCO_PKT_TYPES_MASK_NO_3_EV3 0x0080
+#define HCI_ESCO_PKT_TYPES_MASK_NO_2_EV5 0x0100
+#define HCI_ESCO_PKT_TYPES_MASK_NO_3_EV5 0x0200
+
+/* Packet type should be one of valid but at least one should be specified for 1.2 */
+#define HCI_VALID_ESCO_PKT_TYPE(t) (((((t) & ~(HCI_ESCO_PKT_TYPES_MASK_EV3 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV4 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV5)) == 0)) \
+ && ((t) != 0))/* Packet type should be one of valid but at least one should be specified */
+
+#define HCI_VALID_ESCO_SCOPKT_TYPE(t) (((((t) & ~(HCI_ESCO_PKT_TYPES_MASK_HV1 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV2 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV3)) == 0)) \
+ && ((t) != 0))
+
+#define HCI_VALID_SCO_ALL_PKT_TYPE(t) (((((t) & ~(HCI_ESCO_PKT_TYPES_MASK_HV1 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV2 \
+ | HCI_ESCO_PKT_TYPES_MASK_HV3 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV3 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV4 \
+ | HCI_ESCO_PKT_TYPES_MASK_EV5)) == 0)) \
+ && ((t) != 0))
+
+/*
+** Define parameters to allow role switch during create connection
+*/
+#define HCI_CR_CONN_NOT_ALLOW_SWITCH 0x00
+#define HCI_CR_CONN_ALLOW_SWITCH 0x01
+
+/*
+** Hold Mode command destination
+*/
+#define HOLD_MODE_DEST_LOCAL_DEVICE 0x00
+#define HOLD_MODE_DEST_RMT_DEVICE 0x01
+
+/*
+** Defentions for different HCI parameters
+*/
+#define HCI_PER_INQ_MIN_MAX_PERIOD 0x0003
+#define HCI_PER_INQ_MAX_MAX_PERIOD 0xFFFF
+#define HCI_PER_INQ_MIN_MIN_PERIOD 0x0002
+#define HCI_PER_INQ_MAX_MIN_PERIOD 0xFFFE
+
+#define HCI_MAX_INQUIRY_LENGTH 0x30
+
+#define HCI_MIN_INQ_LAP 0x9E8B00
+#define HCI_MAX_INQ_LAP 0x9E8B3F
+
+/* HCI role defenitions */
+#define HCI_ROLE_MASTER 0x00
+#define HCI_ROLE_SLAVE 0x01
+#define HCI_ROLE_UNKNOWN 0xff
+
+/* HCI mode defenitions */
+#define HCI_MODE_ACTIVE 0x00
+#define HCI_MODE_HOLD 0x01
+#define HCI_MODE_SNIFF 0x02
+#define HCI_MODE_PARK 0x03
+
+/* Define Packet types as requested by the Host */
+#define HCI_ACL_PKT_TYPE_NONE 0x0000
+#define HCI_ACL_PKT_TYPE_DM1 0x0008
+#define HCI_ACL_PKT_TYPE_DH1 0x0010
+#define HCI_ACL_PKT_TYPE_AUX1 0x0200
+#define HCI_ACL_PKT_TYPE_DM3 0x0400
+#define HCI_ACL_PKT_TYPE_DH3 0x0800
+#define HCI_ACL_PKT_TYPE_DM5 0x4000
+#define HCI_ACL_PKT_TYPE_DH5 0x8000
+
+/* Define key type in the Master Link Key command */
+#define HCI_USE_SEMI_PERMANENT_KEY 0x00
+#define HCI_USE_TEMPORARY_KEY 0x01
+
+/* Page scan period modes */
+#define HCI_PAGE_SCAN_REP_MODE_R0 0x00
+#define HCI_PAGE_SCAN_REP_MODE_R1 0x01
+#define HCI_PAGE_SCAN_REP_MODE_R2 0x02
+
+/* Define limits for page scan repetition modes */
+#define HCI_PAGE_SCAN_R1_LIMIT 0x0800
+#define HCI_PAGE_SCAN_R2_LIMIT 0x1000
+
+/* Page scan period modes */
+#define HCI_PAGE_SCAN_PER_MODE_P0 0x00
+#define HCI_PAGE_SCAN_PER_MODE_P1 0x01
+#define HCI_PAGE_SCAN_PER_MODE_P2 0x02
+
+/* Page scan modes */
+#define HCI_MANDATARY_PAGE_SCAN_MODE 0x00
+#define HCI_OPTIONAL_PAGE_SCAN_MODE1 0x01
+#define HCI_OPTIONAL_PAGE_SCAN_MODE2 0x02
+#define HCI_OPTIONAL_PAGE_SCAN_MODE3 0x03
+
+/* Page and inquiry scan types */
+#define HCI_SCAN_TYPE_STANDARD 0x00
+#define HCI_SCAN_TYPE_INTERLACED 0x01 /* 1.2 devices or later */
+#define HCI_DEF_SCAN_TYPE HCI_SCAN_TYPE_STANDARD
+
+/* Definitions for quality of service service types */
+#define HCI_SERVICE_NO_TRAFFIC 0x00
+#define HCI_SERVICE_BEST_EFFORT 0x01
+#define HCI_SERVICE_GUARANTEED 0x02
+
+#define HCI_QOS_LATENCY_DO_NOT_CARE 0xFFFFFFFF
+#define HCI_QOS_DELAY_DO_NOT_CARE 0xFFFFFFFF
+
+/* Definitions for Flow Specification */
+#define HCI_FLOW_SPEC_LATENCY_DO_NOT_CARE 0xFFFFFFFF
+
+/* Definitions for AFH Channel Map */
+#define HCI_AFH_CHANNEL_MAP_LEN 10
+
+/* Definitions for Extended Inquiry Response */
+#define HCI_EXT_INQ_RESPONSE_LEN 240
+#define HCI_EIR_FLAGS_TYPE 0x01
+#define HCI_EIR_MORE_16BITS_UUID_TYPE 0x02
+#define HCI_EIR_COMPLETE_16BITS_UUID_TYPE 0x03
+#define HCI_EIR_MORE_32BITS_UUID_TYPE 0x04
+#define HCI_EIR_COMPLETE_32BITS_UUID_TYPE 0x05
+#define HCI_EIR_MORE_128BITS_UUID_TYPE 0x06
+#define HCI_EIR_COMPLETE_128BITS_UUID_TYPE 0x07
+#define HCI_EIR_SHORTENED_LOCAL_NAME_TYPE 0x08
+#define HCI_EIR_COMPLETE_LOCAL_NAME_TYPE 0x09
+#define HCI_EIR_TX_POWER_LEVEL_TYPE 0x0A
+#define HCI_EIR_MANUFACTURER_SPECIFIC_TYPE 0xFF
+
+/* Definitions for Write Simple Pairing Mode */
+#define HCI_SP_MODE_UNDEFINED 0x00
+#define HCI_SP_MODE_ENABLED 0x01
+
+/* Definitions for Write Simple Pairing Debug Mode */
+#define HCI_SPD_MODE_DISABLED 0x00
+#define HCI_SPD_MODE_ENABLED 0x01
+
+/* Definitions for IO Capability Response/Command */
+#define HCI_IO_CAP_DISPLAY_ONLY 0x00
+#define HCI_IO_CAP_DISPLAY_YESNO 0x01
+#define HCI_IO_CAP_KEYBOARD_ONLY 0x02
+#define HCI_IO_CAP_NO_IO 0x03
+
+#define HCI_OOB_AUTH_DATA_NOT_PRESENT 0x00
+#define HCI_OOB_REM_AUTH_DATA_PRESENT 0x01
+
+#define HCI_MITM_PROTECT_NOT_REQUIRED 0x00
+#define HCI_MITM_PROTECT_REQUIRED 0x01
+
+
+/* Policy settings status */
+#define HCI_DISABLE_ALL_LM_MODES 0x0000
+#define HCI_ENABLE_MASTER_SLAVE_SWITCH 0x0001
+#define HCI_ENABLE_HOLD_MODE 0x0002
+#define HCI_ENABLE_SNIFF_MODE 0x0004
+#define HCI_ENABLE_PARK_MODE 0x0008
+
+/* By default allow switch, because host can not allow that */
+/* that until he created the connection */
+#define HCI_DEFAULT_POLICY_SETTINGS HCI_DISABLE_ALL_LM_MODES
+
+/* Filters that are sent in set filter command */
+#define HCI_FILTER_TYPE_CLEAR_ALL 0x00
+#define HCI_FILTER_INQUIRY_RESULT 0x01
+#define HCI_FILTER_CONNECTION_SETUP 0x02
+
+#define HCI_FILTER_COND_NEW_DEVICE 0x00
+#define HCI_FILTER_COND_DEVICE_CLASS 0x01
+#define HCI_FILTER_COND_BD_ADDR 0x02
+
+#define HCI_DO_NOT_AUTO_ACCEPT_CONNECT 1
+#define HCI_DO_AUTO_ACCEPT_CONNECT 2 /* role switch disabled */
+#define HCI_DO_AUTO_ACCEPT_CONNECT_RS 3 /* role switch enabled (1.1 errata 1115) */
+
+/* Auto accept flags */
+#define HCI_AUTO_ACCEPT_OFF 0x00
+#define HCI_AUTO_ACCEPT_ACL_CONNECTIONS 0x01
+#define HCI_AUTO_ACCEPT_SCO_CONNECTIONS 0x02
+
+/* PIN type */
+#define HCI_PIN_TYPE_VARIABLE 0
+#define HCI_PIN_TYPE_FIXED 1
+
+/* Loopback Modes */
+#define HCI_LOOPBACK_MODE_DISABLED 0
+#define HCI_LOOPBACK_MODE_LOCAL 1
+#define HCI_LOOPBACK_MODE_REMOTE 2
+
+#define SLOTS_PER_10MS 16 /* 0.625 ms slots in a 10 ms tick */
+
+/* Maximum connection accept timeout in 0.625msec */
+#define HCI_MAX_CONN_ACCEPT_TOUT 0xB540 /* 29 sec */
+#define HCI_DEF_CONN_ACCEPT_TOUT 0x1FA0 /* 5 sec */
+
+/* Page timeout is used in LC only and LC is counting down slots not using OS */
+#define HCI_DEFAULT_PAGE_TOUT 0x2000 /* 5.12 sec (in slots) */
+
+/* Scan enable flags */
+#define HCI_NO_SCAN_ENABLED 0x00
+#define HCI_INQUIRY_SCAN_ENABLED 0x01
+#define HCI_PAGE_SCAN_ENABLED 0x02
+
+/* Pagescan timer definitions in 0.625 ms */
+#define HCI_MIN_PAGESCAN_INTERVAL 0x12 /* 11.25 ms */
+#define HCI_MAX_PAGESCAN_INTERVAL 0x1000 /* 2.56 sec */
+#define HCI_DEF_PAGESCAN_INTERVAL 0x0800 /* 1.28 sec */
+
+/* Parameter for pagescan window is passed to LC and is kept in slots */
+#define HCI_MIN_PAGESCAN_WINDOW 0x12 /* 11.25 ms */
+#define HCI_MAX_PAGESCAN_WINDOW 0x1000 /* 2.56 sec */
+#define HCI_DEF_PAGESCAN_WINDOW 0x12 /* 11.25 ms */
+
+/* Inquiryscan timer definitions in 0.625 ms */
+#define HCI_MIN_INQUIRYSCAN_INTERVAL 0x12 /* 11.25 ms */
+#define HCI_MAX_INQUIRYSCAN_INTERVAL 0x1000 /* 2.56 sec */
+#define HCI_DEF_INQUIRYSCAN_INTERVAL 0x0800 /* 1.28 sec */
+
+/* Parameter for inquiryscan window is passed to LC and is kept in slots */
+#define HCI_MIN_INQUIRYSCAN_WINDOW 0x12 /* 11.25 ms */
+#define HCI_MAX_INQUIRYSCAN_WINDOW 0x1000 /* 2.56 sec */
+#define HCI_DEF_INQUIRYSCAN_WINDOW 0x12 /* 11.25 ms */
+
+/* Encryption modes */
+#define HCI_ENCRYPT_MODE_DISABLED 0x00
+#define HCI_ENCRYPT_MODE_POINT_TO_POINT 0x01
+#define HCI_ENCRYPT_MODE_ALL 0x02
+
+/* Voice settings */
+#define HCI_INP_CODING_LINEAR 0x0000 /* 0000000000 */
+#define HCI_INP_CODING_U_LAW 0x0100 /* 0100000000 */
+#define HCI_INP_CODING_A_LAW 0x0200 /* 1000000000 */
+#define HCI_INP_CODING_MASK 0x0300 /* 1100000000 */
+
+#define HCI_INP_DATA_FMT_1S_COMPLEMENT 0x0000 /* 0000000000 */
+#define HCI_INP_DATA_FMT_2S_COMPLEMENT 0x0040 /* 0001000000 */
+#define HCI_INP_DATA_FMT_SIGN_MAGNITUDE 0x0080 /* 0010000000 */
+#define HCI_INP_DATA_FMT_UNSIGNED 0x00c0 /* 0011000000 */
+#define HCI_INP_DATA_FMT_MASK 0x00c0 /* 0011000000 */
+
+#define HCI_INP_SAMPLE_SIZE_8BIT 0x0000 /* 0000000000 */
+#define HCI_INP_SAMPLE_SIZE_16BIT 0x0020 /* 0000100000 */
+#define HCI_INP_SAMPLE_SIZE_MASK 0x0020 /* 0000100000 */
+
+#define HCI_INP_LINEAR_PCM_BIT_POS_MASK 0x001c /* 0000011100 */
+#define HCI_INP_LINEAR_PCM_BIT_POS_OFFS 2
+
+#define HCI_AIR_CODING_FORMAT_CVSD 0x0000 /* 0000000000 */
+#define HCI_AIR_CODING_FORMAT_U_LAW 0x0001 /* 0000000001 */
+#define HCI_AIR_CODING_FORMAT_A_LAW 0x0002 /* 0000000010 */
+#define HCI_AIR_CODING_FORMAT_TRANSPNT 0x0003 /* 0000000011 */
+#define HCI_AIR_CODING_FORMAT_MASK 0x0003 /* 0000000011 */
+
+/* default 0001100000 */
+#define HCI_DEFAULT_VOICE_SETTINGS (HCI_INP_CODING_LINEAR \
+ | HCI_INP_DATA_FMT_2S_COMPLEMENT \
+ | HCI_INP_SAMPLE_SIZE_16BIT \
+ | HCI_AIR_CODING_FORMAT_CVSD)
+
+#define HCI_CVSD_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_CVSD)
+#define HCI_U_LAW_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_U_LAW)
+#define HCI_A_LAW_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_A_LAW)
+#define HCI_TRANSPNT_SUPPORTED(x) (((x) & HCI_AIR_CODING_FORMAT_MASK) == HCI_AIR_CODING_FORMAT_TRANSPNT)
+
+/* Retransmit timer definitions in 0.625 */
+#define HCI_MAX_AUTO_FLUSH_TOUT 0x07FF
+#define HCI_DEFAULT_AUTO_FLUSH_TOUT 0 /* No auto flush */
+
+/* Broadcast retransmitions */
+#define HCI_DEFAULT_NUM_BCAST_RETRAN 1
+
+/* Define broadcast data types as passed in the hci data packet */
+#define HCI_DATA_POINT_TO_POINT 0x00
+#define HCI_DATA_ACTIVE_BCAST 0x01
+#define HCI_DATA_PICONET_BCAST 0x02
+
+/* Hold mode activity */
+#define HCI_MAINTAIN_CUR_POWER_STATE 0x00
+#define HCI_SUSPEND_PAGE_SCAN 0x01
+#define HCI_SUSPEND_INQUIRY_SCAN 0x02
+#define HCI_SUSPEND_PERIODIC_INQUIRIES 0x04
+
+/* Default Link Supervision timeoout */
+#define HCI_DEFAULT_INACT_TOUT 0x7D00 /* 20 seconds */
+
+/* Read transmit power level parameter */
+#define HCI_READ_CURRENT 0x00
+#define HCI_READ_MAXIMUM 0x01
+
+/* Link types for connection complete event */
+#define HCI_LINK_TYPE_SCO 0x00
+#define HCI_LINK_TYPE_ACL 0x01
+#define HCI_LINK_TYPE_ESCO 0x02
+
+/* Link Key Notification Event (Key Type) definitions */
+#define HCI_LKEY_TYPE_COMBINATION 0x00
+#define HCI_LKEY_TYPE_LOCAL_UNIT 0x01
+#define HCI_LKEY_TYPE_REMOTE_UNIT 0x02
+#define HCI_LKEY_TYPE_DEBUG_COMB 0x03
+#define HCI_LKEY_TYPE_UNAUTH_COMB 0x04
+#define HCI_LKEY_TYPE_AUTH_COMB 0x05
+#define HCI_LKEY_TYPE_CHANGED_COMB 0x06
+
+/* Read Local Version HCI Version return values (Command Complete Event) */
+#define HCI_VERSION_1_0B 0x00
+#define HCI_VERSION_1_1 0x01
+
+/* Define an invalid value for a handle */
+#define HCI_INVALID_HANDLE 0xFFFF
+
+/* Define max amount of data in the HCI command */
+#define HCI_COMMAND_SIZE 255
+
+/* Define the preamble length for all HCI Commands.
+** This is 2-bytes for opcode and 1 byte for length
+*/
+#define HCIC_PREAMBLE_SIZE 3
+
+/* Define the preamble length for all HCI Events
+** This is 1-byte for opcode and 1 byte for length
+*/
+#define HCIE_PREAMBLE_SIZE 2
+#define HCI_SCO_PREAMBLE_SIZE 3
+#define HCI_DATA_PREAMBLE_SIZE 4
+
+
+/* HCI message type definitions (for H4 messages) */
+#define HCIT_TYPE_COMMAND 1
+#define HCIT_TYPE_ACL_DATA 2
+#define HCIT_TYPE_SCO_DATA 3
+#define HCIT_TYPE_EVENT 4
+#define HCIT_TYPE_LM_DIAG 7
+
+#define HCIT_LM_DIAG_LENGTH 63
+
+/* Define values for LMP Test Control parameters
+** Test Scenario, Hopping Mode, Power Control Mode
+*/
+#define LMP_TESTCTL_TESTSC_PAUSE 0
+#define LMP_TESTCTL_TESTSC_TXTEST_0 1
+#define LMP_TESTCTL_TESTSC_TXTEST_1 2
+#define LMP_TESTCTL_TESTSC_TXTEST_1010 3
+#define LMP_TESTCTL_TESTSC_PSRND_BITSEQ 4
+#define LMP_TESTCTL_TESTSC_CLOSEDLB_ACL 5
+#define LMP_TESTCTL_TESTSC_CLOSEDLB_SCO 6
+#define LMP_TESTCTL_TESTSC_ACL_NOWHIT 7
+#define LMP_TESTCTL_TESTSC_SCO_NOWHIT 8
+#define LMP_TESTCTL_TESTSC_TXTEST_11110000 9
+#define LMP_TESTCTL_TESTSC_EXITTESTMODE 255
+
+#define LMP_TESTCTL_HOPMOD_RXTX1FREQ 0
+#define LMP_TESTCTL_HOPMOD_HOP_EURUSA 1
+#define LMP_TESTCTL_HOPMOD_HOP_JAPAN 2
+#define LMP_TESTCTL_HOPMOD_HOP_FRANCE 3
+#define LMP_TESTCTL_HOPMOD_HOP_SPAIN 4
+#define LMP_TESTCTL_HOPMOD_REDUCED_HOP 5
+
+#define LMP_TESTCTL_POWCTL_FIXEDTX_OP 0
+#define LMP_TESTCTL_POWCTL_ADAPTIVE 1
+
+
+/*
+** Define company IDs (from Bluetooth Assigned Numbers v1.1, section 2.2)
+*/
+#define LMP_COMPID_ERICSSON 0
+#define LMP_COMPID_NOKIA 1
+#define LMP_COMPID_INTEL 2
+#define LMP_COMPID_IBM 3
+#define LMP_COMPID_TOSHIBA 4
+#define LMP_COMPID_3COM 5
+#define LMP_COMPID_MICROSOFT 6
+#define LMP_COMPID_LUCENT 7
+#define LMP_COMPID_MOTOROLA 8
+#define LMP_COMPID_INFINEON 9
+#define LMP_COMPID_CSR 10
+#define LMP_COMPID_SILICON_WAVE 11
+#define LMP_COMPID_DIGIANSWER 12
+#define LMP_COMPID_TEXAS_INSTRUMENTS 13
+#define LMP_COMPID_PARTHUS 14
+#define LMP_COMPID_BROADCOM 15
+#define LMP_COMPID_MITEL_SEMI 16
+#define LMP_COMPID_WIDCOMM 17
+#define LMP_COMPID_ZEEVO 18
+#define LMP_COMPID_ATMEL 19
+#define LMP_COMPID_MITSUBISHI 20
+#define LMP_COMPID_RTX_TELECOM 21
+#define LMP_COMPID_KC_TECH 22
+#define LMP_COMPID_NEWLOGIC 23
+#define LMP_COMPID_TRANSILICA 24
+#define LMP_COMPID_ROHDE_SCHWARZ 25
+#define LMP_COMPID_TTPCOM 26
+#define LMP_COMPID_SIGNIA 27
+#define LMP_COMPID_CONEXANT 28
+#define LMP_COMPID_QUALCOMM 29
+#define LMP_COMPID_INVENTEL 30
+#define LMP_COMPID_AVM 31
+#define LMP_COMPID_BANDSPEED 32
+#define LMP_COMPID_MANSELLA 33
+#define LMP_COMPID_NEC_CORP 34
+#define LMP_COMPID_WAVEPLUS 35
+#define LMP_COMPID_ALCATEL 36
+#define LMP_COMPID_PHILIPS 37
+#define LMP_COMPID_C_TECHNOLOGIES 38
+#define LMP_COMPID_OPEN_INTERFACE 39
+#define LMP_COMPID_RF_MICRO 40
+#define LMP_COMPID_HITACHI 41
+#define LMP_COMPID_SYMBOL_TECH 42
+#define LMP_COMPID_TENOVIS 43
+#define LMP_COMPID_MACRONIX 44
+#define LMP_COMPID_GCT_SEMI 45
+#define LMP_COMPID_NORWOOD_SYSTEMS 46
+#define LMP_COMPID_MEWTEL_TECH 47
+#define LMP_COMPID_STM 48
+#define LMP_COMPID_SYNOPSYS 49
+#define LMP_COMPID_RED_M_LTD 50
+#define LMP_COMPID_COMMIL_LTD 51
+#define LMP_COMPID_CATC 52
+#define LMP_COMPID_ECLIPSE 53
+#define LMP_COMPID_RENESAS_TECH 54
+#define LMP_COMPID_MOBILIAN_CORP 55
+#define LMP_COMPID_TERAX 56
+#define LMP_COMPID_ISSC 57
+#define LMP_COMPID_MATSUSHITA 58
+#define LMP_COMPID_GENNUM_CORP 59
+#define LMP_COMPID_RESEARCH_IN_MOTION 60
+#define LMP_COMPID_IPEXTREME 61
+#define LMP_COMPID_SYSTEMS_AND_CHIPS 62
+#define LMP_COMPID_BLUETOOTH_SIG 63
+#define LMP_COMPID_SEIKO_EPSON_CORP 64
+#define LMP_COMPID_ISS_TAIWAN 65
+#define LMP_COMPID_CONWISE_TECHNOLOGIES 66
+#define LMP_COMPID_PARROT_SA 67
+#define LMP_COMPID_SOCKET_COMM 68
+#define LMP_COMPID_MAX_ID 69 /* this is a place holder */
+#define LMP_COMPID_INTERNAL 65535
+
+#define MAX_LMP_COMPID (LMP_COMPID_MAX_ID)
+/*
+** Define the packet types in the packet header, and a couple extra
+*/
+#define PKT_TYPE_NULL 0x00
+#define PKT_TYPE_POLL 0x01
+#define PKT_TYPE_FHS 0x02
+#define PKT_TYPE_DM1 0x03
+
+#define PKT_TYPE_DH1 0x04
+#define PKT_TYPE_HV1 0x05
+#define PKT_TYPE_HV2 0x06
+#define PKT_TYPE_HV3 0x07
+#define PKT_TYPE_DV 0x08
+#define PKT_TYPE_AUX1 0x09
+
+#define PKT_TYPE_DM3 0x0a
+#define PKT_TYPE_DH3 0x0b
+
+#define PKT_TYPE_DM5 0x0e
+#define PKT_TYPE_DH5 0x0f
+
+
+#define PKT_TYPE_ID 0x10 /* Internally used packet types */
+#define PKT_TYPE_BAD 0x11
+#define PKT_TYPE_NONE 0x12
+
+/*
+** Define packet size
+*/
+#define HCI_DM1_PACKET_SIZE 17
+#define HCI_DH1_PACKET_SIZE 27
+#define HCI_DM3_PACKET_SIZE 121
+#define HCI_DH3_PACKET_SIZE 183
+#define HCI_DM5_PACKET_SIZE 224
+#define HCI_DH5_PACKET_SIZE 339
+#define HCI_AUX1_PACKET_SIZE 29
+#define HCI_HV1_PACKET_SIZE 10
+#define HCI_HV2_PACKET_SIZE 20
+#define HCI_HV3_PACKET_SIZE 30
+#define HCI_DV_PACKET_SIZE 9
+#define HCI_EDR2_DH1_PACKET_SIZE 54
+#define HCI_EDR2_DH3_PACKET_SIZE 367
+#define HCI_EDR2_DH5_PACKET_SIZE 679
+#define HCI_EDR3_DH1_PACKET_SIZE 83
+#define HCI_EDR3_DH3_PACKET_SIZE 552
+#define HCI_EDR3_DH5_PACKET_SIZE 1021
+
+/*
+** Features encoding - page 0
+*/
+#define HCI_NUM_FEATURE_BYTES 8
+#define HCI_FEATURES_KNOWN(x) ((x[0] | x[1] | x[2] | x[3] | x[4] | x[5] | x[6] | x[7]) != 0)
+
+#define HCI_FEATURE_3_SLOT_PACKETS_MASK 0x01
+#define HCI_FEATURE_3_SLOT_PACKETS_OFF 0
+#define HCI_3_SLOT_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_3_SLOT_PACKETS_OFF] & HCI_FEATURE_3_SLOT_PACKETS_MASK)
+
+#define HCI_FEATURE_5_SLOT_PACKETS_MASK 0x02
+#define HCI_FEATURE_5_SLOT_PACKETS_OFF 0
+#define HCI_5_SLOT_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_5_SLOT_PACKETS_OFF] & HCI_FEATURE_5_SLOT_PACKETS_MASK)
+
+#define HCI_FEATURE_ENCRYPTION_MASK 0x04
+#define HCI_FEATURE_ENCRYPTION_OFF 0
+#define HCI_ENCRYPTION_SUPPORTED(x) ((x)[HCI_FEATURE_ENCRYPTION_OFF] & HCI_FEATURE_ENCRYPTION_MASK)
+
+#define HCI_FEATURE_SLOT_OFFSET_MASK 0x08
+#define HCI_FEATURE_SLOT_OFFSET_OFF 0
+#define HCI_SLOT_OFFSET_SUPPORTED(x) ((x)[HCI_FEATURE_SLOT_OFFSET_OFF] & HCI_FEATURE_SLOT_OFFSET_MASK)
+
+#define HCI_FEATURE_TIMING_ACC_MASK 0x10
+#define HCI_FEATURE_TIMING_ACC_OFF 0
+#define HCI_TIMING_ACC_SUPPORTED(x) ((x)[HCI_FEATURE_TIMING_ACC_OFF] & HCI_FEATURE_TIMING_ACC_MASK)
+
+#define HCI_FEATURE_SWITCH_MASK 0x20
+#define HCI_FEATURE_SWITCH_OFF 0
+#define HCI_SWITCH_SUPPORTED(x) ((x)[HCI_FEATURE_SWITCH_OFF] & HCI_FEATURE_SWITCH_MASK)
+
+#define HCI_FEATURE_HOLD_MODE_MASK 0x40
+#define HCI_FEATURE_HOLD_MODE_OFF 0
+#define HCI_HOLD_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_HOLD_MODE_OFF] & HCI_FEATURE_HOLD_MODE_MASK)
+
+#define HCI_FEATURE_SNIFF_MODE_MASK 0x80
+#define HCI_FEATURE_SNIFF_MODE_OFF 0
+#define HCI_SNIFF_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_SNIFF_MODE_OFF] & HCI_FEATURE_SNIFF_MODE_MASK)
+
+#define HCI_FEATURE_PARK_MODE_MASK 0x01
+#define HCI_FEATURE_PARK_MODE_OFF 1
+#define HCI_PARK_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_PARK_MODE_OFF] & HCI_FEATURE_PARK_MODE_MASK)
+
+#define HCI_FEATURE_RSSI_MASK 0x02
+#define HCI_FEATURE_RSSI_OFF 1
+#define HCI_RSSI_SUPPORTED(x) ((x)[HCI_FEATURE_RSSI_OFF] & HCI_FEATURE_RSSI_MASK)
+
+#define HCI_FEATURE_CQM_DATA_RATE_MASK 0x04
+#define HCI_FEATURE_CQM_DATA_RATE_OFF 1
+#define HCI_CQM_DATA_RATE_SUPPORTED(x) ((x)[HCI_FEATURE_CQM_DATA_RATE_OFF] & HCI_FEATURE_CQM_DATA_RATE_MASK)
+
+#define HCI_FEATURE_SCO_LINK_MASK 0x08
+#define HCI_FEATURE_SCO_LINK_OFF 1
+#define HCI_SCO_LINK_SUPPORTED(x) ((x)[HCI_FEATURE_SCO_LINK_OFF] & HCI_FEATURE_SCO_LINK_MASK)
+
+#define HCI_FEATURE_HV2_PACKETS_MASK 0x10
+#define HCI_FEATURE_HV2_PACKETS_OFF 1
+#define HCI_HV2_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_HV2_PACKETS_OFF] & HCI_FEATURE_HV2_PACKETS_MASK)
+
+#define HCI_FEATURE_HV3_PACKETS_MASK 0x20
+#define HCI_FEATURE_HV3_PACKETS_OFF 1
+#define HCI_HV3_PACKETS_SUPPORTED(x) ((x)[HCI_FEATURE_HV3_PACKETS_OFF] & HCI_FEATURE_HV3_PACKETS_MASK)
+
+#define HCI_FEATURE_U_LAW_MASK 0x40
+#define HCI_FEATURE_U_LAW_OFF 1
+#define HCI_LMP_U_LAW_SUPPORTED(x) ((x)[HCI_FEATURE_U_LAW_OFF] & HCI_FEATURE_U_LAW_MASK)
+
+#define HCI_FEATURE_A_LAW_MASK 0x80
+#define HCI_FEATURE_A_LAW_OFF 1
+#define HCI_LMP_A_LAW_SUPPORTED(x) ((x)[HCI_FEATURE_A_LAW_OFF] & HCI_FEATURE_A_LAW_MASK)
+
+#define HCI_FEATURE_CVSD_MASK 0x01
+#define HCI_FEATURE_CVSD_OFF 2
+#define HCI_LMP_CVSD_SUPPORTED(x) ((x)[HCI_FEATURE_CVSD_OFF] & HCI_FEATURE_CVSD_MASK)
+
+#define HCI_FEATURE_PAGING_SCHEME_MASK 0x02
+#define HCI_FEATURE_PAGING_SCHEME_OFF 2
+#define HCI_PAGING_SCHEME_SUPPORTED(x) ((x)[HCI_FEATURE_PAGING_SCHEME_OFF] & HCI_FEATURE_PAGING_SCHEME_MASK)
+
+#define HCI_FEATURE_POWER_CTRL_MASK 0x04
+#define HCI_FEATURE_POWER_CTRL_OFF 2
+#define HCI_POWER_CTRL_SUPPORTED(x) ((x)[HCI_FEATURE_POWER_CTRL_OFF] & HCI_FEATURE_POWER_CTRL_MASK)
+
+#define HCI_FEATURE_TRANSPNT_MASK 0x08
+#define HCI_FEATURE_TRANSPNT_OFF 2
+#define HCI_LMP_TRANSPNT_SUPPORTED(x) ((x)[HCI_FEATURE_TRANSPNT_OFF] & HCI_FEATURE_TRANSPNT_MASK)
+
+#define HCI_FEATURE_FLOW_CTRL_LAG_MASK 0x70
+#define HCI_FEATURE_FLOW_CTRL_LAG_OFF 2
+#define HCI_FLOW_CTRL_LAG_VALUE(x) (((x)[HCI_FEATURE_FLOW_CTRL_LAG_OFF] & HCI_FEATURE_FLOW_CTRL_LAG_MASK) >> 4)
+
+#define HCI_FEATURE_BROADCAST_ENC_MASK 0x80
+#define HCI_FEATURE_BROADCAST_ENC_OFF 2
+#define HCI_LMP_BCAST_ENC_SUPPORTED(x) ((x)[HCI_FEATURE_BROADCAST_ENC_OFF] & HCI_FEATURE_BROADCAST_ENC_MASK)
+
+#define HCI_FEATURE_SCATTER_MODE_MASK 0x01
+#define HCI_FEATURE_SCATTER_MODE_OFF 3
+#define HCI_LMP_SCATTER_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_SCATTER_MODE_OFF] & HCI_FEATURE_SCATTER_MODE_MASK)
+
+#define HCI_FEATURE_EDR_ACL_2MPS_MASK 0x02
+#define HCI_FEATURE_EDR_ACL_2MPS_OFF 3
+#define HCI_EDR_ACL_2MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ACL_2MPS_OFF] & HCI_FEATURE_EDR_ACL_2MPS_MASK)
+
+#define HCI_FEATURE_EDR_ACL_3MPS_MASK 0x04
+#define HCI_FEATURE_EDR_ACL_3MPS_OFF 3
+#define HCI_EDR_ACL_3MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ACL_3MPS_OFF] & HCI_FEATURE_EDR_ACL_3MPS_MASK)
+
+#define HCI_FEATURE_ENHANCED_INQ_MASK 0x08
+#define HCI_FEATURE_ENHANCED_INQ_OFF 3
+#define HCI_ENHANCED_INQ_SUPPORTED(x) ((x)[HCI_FEATURE_ENHANCED_INQ_OFF] & HCI_FEATURE_ENHANCED_INQ_MASK)
+
+#define HCI_FEATURE_INTERLACED_INQ_SCAN_MASK 0x10
+#define HCI_FEATURE_INTERLACED_INQ_SCAN_OFF 3
+#define HCI_LMP_INTERLACED_INQ_SCAN_SUPPORTED(x) ((x)[HCI_FEATURE_INTERLACED_INQ_SCAN_OFF] & HCI_FEATURE_INTERLACED_INQ_SCAN_MASK)
+
+#define HCI_FEATURE_INTERLACED_PAGE_SCAN_MASK 0x20
+#define HCI_FEATURE_INTERLACED_PAGE_SCAN_OFF 3
+#define HCI_LMP_INTERLACED_PAGE_SCAN_SUPPORTED(x) ((x)[HCI_FEATURE_INTERLACED_PAGE_SCAN_OFF] & HCI_FEATURE_INTERLACED_PAGE_SCAN_MASK)
+
+#define HCI_FEATURE_INQ_RSSI_MASK 0x40
+#define HCI_FEATURE_INQ_RSSI_OFF 3
+#define HCI_LMP_INQ_RSSI_SUPPORTED(x) ((x)[HCI_FEATURE_INQ_RSSI_OFF] & HCI_FEATURE_INQ_RSSI_MASK)
+
+#define HCI_FEATURE_ESCO_EV3_MASK 0x80
+#define HCI_FEATURE_ESCO_EV3_OFF 3
+#define HCI_ESCO_EV3_SUPPORTED(x) ((x)[HCI_FEATURE_ESCO_EV3_OFF] & HCI_FEATURE_ESCO_EV3_MASK)
+
+#define HCI_FEATURE_ESCO_EV4_MASK 0x01
+#define HCI_FEATURE_ESCO_EV4_OFF 4
+#define HCI_ESCO_EV4_SUPPORTED(x) ((x)[HCI_FEATURE_ESCO_EV4_OFF] & HCI_FEATURE_ESCO_EV4_MASK)
+
+#define HCI_FEATURE_ESCO_EV5_MASK 0x02
+#define HCI_FEATURE_ESCO_EV5_OFF 4
+#define HCI_ESCO_EV5_SUPPORTED(x) ((x)[HCI_FEATURE_ESCO_EV5_OFF] & HCI_FEATURE_ESCO_EV5_MASK)
+
+#define HCI_FEATURE_ABSENCE_MASKS_MASK 0x04
+#define HCI_FEATURE_ABSENCE_MASKS_OFF 4
+#define HCI_LMP_ABSENCE_MASKS_SUPPORTED(x) ((x)[HCI_FEATURE_ABSENCE_MASKS_OFF] & HCI_FEATURE_ABSENCE_MASKS_MASK)
+
+#define HCI_FEATURE_AFH_CAP_SLAVE_MASK 0x08
+#define HCI_FEATURE_AFH_CAP_SLAVE_OFF 4
+#define HCI_LMP_AFH_CAP_SLAVE_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CAP_SLAVE_OFF] & HCI_FEATURE_AFH_CAP_SLAVE_MASK)
+
+#define HCI_FEATURE_AFH_CLASS_SLAVE_MASK 0x10
+#define HCI_FEATURE_AFH_CLASS_SLAVE_OFF 4
+#define HCI_LMP_AFH_CLASS_SLAVE_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CLASS_SLAVE_OFF] & HCI_FEATURE_AFH_CLASS_SLAVE_MASK)
+
+#define HCI_FEATURE_ALIAS_AUTH_MASK 0x20
+#define HCI_FEATURE_ALIAS_AUTH_OFF 4
+#define HCI_LMP_ALIAS_AUTH_SUPPORTED(x) ((x)[HCI_FEATURE_ALIAS_AUTH_OFF] & HCI_FEATURE_ALIAS_AUTH_MASK)
+
+#define HCI_FEATURE_ANON_MODE_MASK 0x40
+#define HCI_FEATURE_ANON_MODE_OFF 4
+#define HCI_LMP_ANON_MODE_SUPPORTED(x) ((x)[HCI_FEATURE_ANON_MODE_OFF] & HCI_FEATURE_ANON_MODE_MASK)
+
+#define HCI_FEATURE_3_SLOT_EDR_ACL_MASK 0x80
+#define HCI_FEATURE_3_SLOT_EDR_ACL_OFF 4
+#define HCI_3_SLOT_EDR_ACL_SUPPORTED(x) ((x)[HCI_FEATURE_3_SLOT_EDR_ACL_OFF] & HCI_FEATURE_3_SLOT_EDR_ACL_MASK)
+
+#define HCI_FEATURE_5_SLOT_EDR_ACL_MASK 0x01
+#define HCI_FEATURE_5_SLOT_EDR_ACL_OFF 5
+#define HCI_5_SLOT_EDR_ACL_SUPPORTED(x) ((x)[HCI_FEATURE_5_SLOT_EDR_ACL_OFF] & HCI_FEATURE_5_SLOT_EDR_ACL_MASK)
+
+#define HCI_FEATURE_SNIFF_SUB_RATE_MASK 0x02
+#define HCI_FEATURE_SNIFF_SUB_RATE_OFF 5
+#define HCI_SNIFF_SUB_RATE_SUPPORTED(x) ((x)[HCI_FEATURE_SNIFF_SUB_RATE_OFF] & HCI_FEATURE_SNIFF_SUB_RATE_MASK)
+
+#define HCI_FEATURE_ATOMIC_ENCRYPT_MASK 0x04
+#define HCI_FEATURE_ATOMIC_ENCRYPT_OFF 5
+#define HCI_ATOMIC_ENCRYPT_SUPPORTED(x) ((x)[HCI_FEATURE_ATOMIC_ENCRYPT_OFF] & HCI_FEATURE_ATOMIC_ENCRYPT_MASK)
+
+#define HCI_FEATURE_AFH_CAP_MASTR_MASK 0x08
+#define HCI_FEATURE_AFH_CAP_MASTR_OFF 5
+#define HCI_LMP_AFH_CAP_MASTR_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CAP_MASTR_OFF] & HCI_FEATURE_AFH_CAP_MASTR_MASK)
+
+#define HCI_FEATURE_AFH_CLASS_MASTR_MASK 0x10
+#define HCI_FEATURE_AFH_CLASS_MASTR_OFF 5
+#define HCI_LMP_AFH_CLASS_MASTR_SUPPORTED(x) ((x)[HCI_FEATURE_AFH_CLASS_MASTR_OFF] & HCI_FEATURE_AFH_CLASS_MASTR_MASK)
+
+#define HCI_FEATURE_EDR_ESCO_2MPS_MASK 0x20
+#define HCI_FEATURE_EDR_ESCO_2MPS_OFF 5
+#define HCI_EDR_ESCO_2MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ESCO_2MPS_OFF] & HCI_FEATURE_EDR_ESCO_2MPS_MASK)
+
+#define HCI_FEATURE_EDR_ESCO_3MPS_MASK 0x40
+#define HCI_FEATURE_EDR_ESCO_3MPS_OFF 5
+#define HCI_EDR_ESCO_3MPS_SUPPORTED(x) ((x)[HCI_FEATURE_EDR_ESCO_3MPS_OFF] & HCI_FEATURE_EDR_ESCO_3MPS_MASK)
+
+#define HCI_FEATURE_3_SLOT_EDR_ESCO_MASK 0x80
+#define HCI_FEATURE_3_SLOT_EDR_ESCO_OFF 5
+#define HCI_3_SLOT_EDR_ESCO_SUPPORTED(x) ((x)[HCI_FEATURE_3_SLOT_EDR_ESCO_OFF] & HCI_FEATURE_3_SLOT_EDR_ESCO_MASK)
+
+#define HCI_FEATURE_EXT_INQ_RSP_MASK 0x01
+#define HCI_FEATURE_EXT_INQ_RSP_OFF 6
+#define HCI_EXT_INQ_RSP_SUPPORTED(x) ((x)[HCI_FEATURE_EXT_INQ_RSP_OFF] & HCI_FEATURE_EXT_INQ_RSP_MASK)
+
+#define HCI_FEATURE_ANUM_PIN_AWARE_MASK 0x02
+#define HCI_FEATURE_ANUM_PIN_AWARE_OFF 6
+#define HCI_ANUM_PIN_AWARE_SUPPORTED(x) ((x)[HCI_FEATURE_ANUM_PIN_AWARE_OFF] & HCI_FEATURE_ANUM_PIN_AWARE_MASK)
+
+#define HCI_FEATURE_ANUM_PIN_CAP_MASK 0x04
+#define HCI_FEATURE_ANUM_PIN_CAP_OFF 6
+#define HCI_ANUM_PIN_CAP_SUPPORTED(x) ((x)[HCI_FEATURE_ANUM_PIN_CAP_OFF] & HCI_FEATURE_ANUM_PIN_CAP_MASK)
+
+#define HCI_FEATURE_SIMPLE_PAIRING_MASK 0x08
+#define HCI_FEATURE_SIMPLE_PAIRING_OFF 6
+#define HCI_SIMPLE_PAIRING_SUPPORTED(x) ((x)[HCI_FEATURE_SIMPLE_PAIRING_OFF] & HCI_FEATURE_SIMPLE_PAIRING_MASK)
+
+#define HCI_FEATURE_ENCAP_PDU_MASK 0x10
+#define HCI_FEATURE_ENCAP_PDU_OFF 6
+#define HCI_ENCAP_PDU_SUPPORTED(x) ((x)[HCI_FEATURE_ENCAP_PDU_OFF] & HCI_FEATURE_ENCAP_PDU_MASK)
+
+#define HCI_FEATURE_ERROR_DATA_MASK 0x20
+#define HCI_FEATURE_ERROR_DATA_OFF 6
+#define HCI_ERROR_DATA_SUPPORTED(x) ((x)[HCI_FEATURE_ERROR_DATA_OFF] & HCI_FEATURE_ERROR_DATA_MASK)
+
+#define HCI_FEATURE_NON_FLUSHABLE_PB_MASK 0x40
+#define HCI_FEATURE_NON_FLUSHABLE_PB_OFF 6
+#define HCI_NON_FLUSHABLE_PB_SUPPORTED(x) ((x)[HCI_FEATURE_NON_FLUSHABLE_PB_OFF] & HCI_FEATURE_NON_FLUSHABLE_PB_MASK)
+
+#define HCI_FEATURE_LINK_SUP_TO_EVT_MASK 0x01
+#define HCI_FEATURE_LINK_SUP_TO_EVT_OFF 7
+#define HCI_LINK_SUP_TO_EVT_SUPPORTED(x) ((x)[HCI_FEATURE_LINK_SUP_TO_EVT_OFF] & HCI_FEATURE_LINK_SUP_TO_EVT_MASK)
+
+#define HCI_FEATURE_INQ_RESP_TX_MASK 0x02
+#define HCI_FEATURE_INQ_RESP_TX_OFF 7
+#define HCI_INQ_RESP_TX_SUPPORTED(x) ((x)[HCI_FEATURE_INQ_RESP_TX_OFF] & HCI_FEATURE_INQ_RESP_TX_MASK)
+
+#define HCI_FEATURE_EXTENDED_MASK 0x80
+#define HCI_FEATURE_EXTENDED_OFF 7
+#define HCI_LMP_EXTENDED_SUPPORTED(x) ((x)[HCI_FEATURE_EXTENDED_OFF] & HCI_FEATURE_EXTENDED_MASK)
+
+/*
+** Features encoding - page 1
+*/
+#define HCI_EXT_FEATURE_SSP_HOST_MASK 0x01
+#define HCI_EXT_FEATURE_SSP_HOST_OFF 0
+#define HCI_SSP_HOST_SUPPORTED(x) ((x)[HCI_EXT_FEATURE_SSP_HOST_OFF] & HCI_EXT_FEATURE_SSP_HOST_MASK)
+
+/*
+** Local Supported Commands encoding
+*/
+#define HCI_NUM_SUPP_COMMANDS_BYTES 64
+
+#define HCI_SUPP_COMMANDS_INQUIRY_MASK 0x01
+#define HCI_SUPP_COMMANDS_INQUIRY_OFF 0
+#define HCI_INQUIRY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_INQUIRY_OFF] & HCI_SUPP_COMMANDS_INQUIRY_MASK)
+
+#define HCI_SUPP_COMMANDS_INQUIRY_CANCEL_MASK 0x02
+#define HCI_SUPP_COMMANDS_INQUIRY_CANCEL_OFF 0
+#define HCI_INQUIRY_CANCEL_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_INQUIRY_CANCEL_OFF] & HCI_SUPP_COMMANDS_INQUIRY_CANCEL_MASK)
+
+#define HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_MASK 0x04
+#define HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_OFF 0
+#define HCI_PERIODIC_INQUIRY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_OFF] & HCI_SUPP_COMMANDS_PERIODIC_INQUIRY_MASK)
+
+#define HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_MASK 0x08
+#define HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_OFF 0
+#define HCI_EXIT_PERIODIC_INQUIRY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_OFF] & HCI_SUPP_COMMANDS_EXIT_PERIODIC_INQUIRY_MASK)
+
+#define HCI_SUPP_COMMANDS_CREATE_CONN_MASK 0x10
+#define HCI_SUPP_COMMANDS_CREATE_CONN_OFF 0
+#define HCI_CREATE_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CREATE_CONN_OFF] & HCI_SUPP_COMMANDS_CREATE_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_DISCONNECT_MASK 0x20
+#define HCI_SUPP_COMMANDS_DISCONNECT_OFF 0
+#define HCI_DISCONNECT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_DISCONNECT_OFF] & HCI_SUPP_COMMANDS_DISCONNECT_MASK)
+
+#define HCI_SUPP_COMMANDS_ADD_SCO_CONN_MASK 0x40
+#define HCI_SUPP_COMMANDS_ADD_SCO_CONN_OFF 0
+#define HCI_ADD_SCO_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ADD_SCO_CONN_OFF] & HCI_SUPP_COMMANDS_ADD_SCO_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_MASK 0x80
+#define HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_OFF 0
+#define HCI_CANCEL_CREATE_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_OFF] & HCI_SUPP_COMMANDS_CANCEL_CREATE_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_MASK 0x01
+#define HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_OFF 1
+#define HCI_ACCEPT_CONN_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_OFF] & HCI_SUPP_COMMANDS_ACCEPT_CONN_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_MASK 0x02
+#define HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_OFF 1
+#define HCI_REJECT_CONN_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_OFF] & HCI_SUPP_COMMANDS_REJECT_CONN_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_MASK 0x04
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_OFF 1
+#define HCI_LINK_KEY_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_MASK 0x08
+#define HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_OFF 1
+#define HCI_LINK_KEY_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_LINK_KEY_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_MASK 0x10
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_OFF 1
+#define HCI_PIN_CODE_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_MASK 0x20
+#define HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_OFF 1
+#define HCI_PIN_CODE_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_PIN_CODE_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_MASK 0x40
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_OFF 1
+#define HCI_CHANGE_CONN_PKT_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_OFF] & HCI_SUPP_COMMANDS_CHANGE_CONN_PKT_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_AUTH_REQUEST_MASK 0x80
+#define HCI_SUPP_COMMANDS_AUTH_REQUEST_OFF 1
+#define HCI_AUTH_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_AUTH_REQUEST_OFF] & HCI_SUPP_COMMANDS_AUTH_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_MASK 0x01
+#define HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_OFF 2
+#define HCI_SET_CONN_ENCRYPTION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_OFF] & HCI_SUPP_COMMANDS_SET_CONN_ENCRYPTION_MASK)
+
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_MASK 0x02
+#define HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_OFF 2
+#define HCI_CHANGE_CONN_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_CHANGE_CONN_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_MASTER_LINK_KEY_MASK 0x04
+#define HCI_SUPP_COMMANDS_MASTER_LINK_KEY_OFF 2
+#define HCI_MASTER_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_MASTER_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_MASTER_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_MASK 0x08
+#define HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_OFF 2
+#define HCI_REMOTE_NAME_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_OFF] & HCI_SUPP_COMMANDS_REMOTE_NAME_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_MASK 0x10
+#define HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_OFF 2
+#define HCI_CANCEL_REMOTE_NAME_REQUEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_OFF] & HCI_SUPP_COMMANDS_CANCEL_REMOTE_NAME_REQUEST_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_OFF 2
+#define HCI_READ_REMOTE_SUPP_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_REMOTE_SUPP_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_OFF 2
+#define HCI_READ_REMOTE_EXT_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_REMOTE_EXT_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_OFF 2
+#define HCI_READ_REMOTE_VER_INFO_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_OFF] & HCI_SUPP_COMMANDS_READ_REMOTE_VER_INFO_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_OFF 3
+#define HCI_READ_CLOCK_OFFSET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_OFF] & HCI_SUPP_COMMANDS_READ_CLOCK_OFFSET_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LMP_HANDLE_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_LMP_HANDLE_OFF 3
+#define HCI_READ_LMP_HANDLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LMP_HANDLE_OFF] & HCI_SUPP_COMMANDS_READ_LMP_HANDLE_MASK)
+
+#define HCI_SUPP_COMMANDS_HOLD_MODE_CMD_MASK 0x02
+#define HCI_SUPP_COMMANDS_HOLD_MODE_CMD_OFF 4
+#define HCI_HOLD_MODE_CMD_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_HOLD_MODE_CMD_OFF] & HCI_SUPP_COMMANDS_HOLD_MODE_CMD_MASK)
+
+#define HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_MASK 0x04
+#define HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_OFF 4
+#define HCI_SNIFF_MODE_CMD_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_OFF] & HCI_SUPP_COMMANDS_SNIFF_MODE_CMD_MASK)
+
+#define HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_MASK 0x08
+#define HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_OFF 4
+#define HCI_EXIT_SNIFF_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_OFF] & HCI_SUPP_COMMANDS_EXIT_SNIFF_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_PARK_STATE_MASK 0x10
+#define HCI_SUPP_COMMANDS_PARK_STATE_OFF 4
+#define HCI_PARK_STATE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_PARK_STATE_OFF] & HCI_SUPP_COMMANDS_PARK_STATE_MASK)
+
+#define HCI_SUPP_COMMANDS_EXIT_PARK_STATE_MASK 0x20
+#define HCI_SUPP_COMMANDS_EXIT_PARK_STATE_OFF 4
+#define HCI_EXIT_PARK_STATE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_EXIT_PARK_STATE_OFF] & HCI_SUPP_COMMANDS_EXIT_PARK_STATE_MASK)
+
+#define HCI_SUPP_COMMANDS_QOS_SETUP_MASK 0x40
+#define HCI_SUPP_COMMANDS_QOS_SETUP_OFF 4
+#define HCI_QOS_SETUP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_QOS_SETUP_OFF] & HCI_SUPP_COMMANDS_QOS_SETUP_MASK)
+
+#define HCI_SUPP_COMMANDS_ROLE_DISCOVERY_MASK 0x80
+#define HCI_SUPP_COMMANDS_ROLE_DISCOVERY_OFF 4
+#define HCI_ROLE_DISCOVERY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ROLE_DISCOVERY_OFF] & HCI_SUPP_COMMANDS_ROLE_DISCOVERY_MASK)
+
+#define HCI_SUPP_COMMANDS_SWITCH_ROLE_MASK 0x01
+#define HCI_SUPP_COMMANDS_SWITCH_ROLE_OFF 5
+#define HCI_SWITCH_ROLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SWITCH_ROLE_OFF] & HCI_SUPP_COMMANDS_SWITCH_ROLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_OFF 5
+#define HCI_READ_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_READ_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_MASK 0x04
+#define HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_OFF 5
+#define HCI_WRITE_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_WRITE_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_OFF 5
+#define HCI_READ_DEF_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_READ_DEF_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_MASK 0x10
+#define HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_OFF 5
+#define HCI_WRITE_DEF_LINK_POLICY_SET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_OFF] & HCI_SUPP_COMMANDS_WRITE_DEF_LINK_POLICY_SET_MASK)
+
+#define HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_MASK 0x20
+#define HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_OFF 5
+#define HCI_FLOW_SPECIFICATION_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_OFF] & HCI_SUPP_COMMANDS_FLOW_SPECIFICATION_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_EVENT_MASK_MASK 0x40
+#define HCI_SUPP_COMMANDS_SET_EVENT_MASK_OFF 5
+#define HCI_SET_EVENT_MASK_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_EVENT_MASK_OFF] & HCI_SUPP_COMMANDS_SET_EVENT_MASK_MASK)
+
+#define HCI_SUPP_COMMANDS_RESET_MASK 0x80
+#define HCI_SUPP_COMMANDS_RESET_OFF 5
+#define HCI_RESET_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_RESET_OFF] & HCI_SUPP_COMMANDS_RESET_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_EVENT_FILTER_MASK 0x01
+#define HCI_SUPP_COMMANDS_SET_EVENT_FILTER_OFF 6
+#define HCI_SET_EVENT_FILTER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_EVENT_FILTER_OFF] & HCI_SUPP_COMMANDS_SET_EVENT_FILTER_MASK)
+
+#define HCI_SUPP_COMMANDS_FLUSH_MASK 0x02
+#define HCI_SUPP_COMMANDS_FLUSH_OFF 6
+#define HCI_FLUSH_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_FLUSH_OFF] & HCI_SUPP_COMMANDS_FLUSH_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PIN_TYPE_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_PIN_TYPE_OFF 6
+#define HCI_READ_PIN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PIN_TYPE_OFF] & HCI_SUPP_COMMANDS_READ_PIN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_OFF 6
+#define HCI_WRITE_PIN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_OFF] & HCI_SUPP_COMMANDS_WRITE_PIN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_MASK 0x10
+#define HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_OFF 6
+#define HCI_CREATE_NEW_UNIT_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_OFF] & HCI_SUPP_COMMANDS_CREATE_NEW_UNIT_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_OFF 6
+#define HCI_READ_STORED_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_READ_STORED_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_MASK 0x40
+#define HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_OFF 6
+#define HCI_WRITE_STORED_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_WRITE_STORED_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_MASK 0x80
+#define HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_OFF 6
+#define HCI_DELETE_STORED_LINK_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_OFF] & HCI_SUPP_COMMANDS_DELETE_STORED_LINK_KEY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_MASK 0x01
+#define HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_OFF 7
+#define HCI_WRITE_LOCAL_NAME_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_OFF] & HCI_SUPP_COMMANDS_WRITE_LOCAL_NAME_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_NAME_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_LOCAL_NAME_OFF 7
+#define HCI_READ_LOCAL_NAME_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_NAME_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_NAME_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_OFF 7
+#define HCI_READ_CONN_ACCEPT_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_CONN_ACCEPT_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_OFF 7
+#define HCI_WRITE_CONN_ACCEPT_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_CONN_ACCEPT_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_TOUT_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_PAGE_TOUT_OFF 7
+#define HCI_READ_PAGE_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_OFF 7
+#define HCI_WRITE_PAGE_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_OFF 7
+#define HCI_READ_SCAN_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_SCAN_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_OFF 7
+#define HCI_WRITE_SCAN_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_SCAN_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_OFF 8
+#define HCI_READ_PAGE_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_OFF 8
+#define HCI_WRITE_PAGE_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_OFF 8
+#define HCI_READ_INQURIY_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_READ_INQURIY_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_OFF 8
+#define HCI_WRITE_INQURIY_SCAN_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_WRITE_INQURIY_SCAN_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_OFF 8
+#define HCI_READ_AUTH_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_AUTH_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_OFF 8
+#define HCI_WRITE_AUTH_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_AUTH_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_OFF 8
+#define HCI_READ_ENCRYPT_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_ENCRYPT_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_OFF 8
+#define HCI_WRITE_ENCRYPT_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_ENCRYPT_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_OFF 9
+#define HCI_READ_CLASS_DEVICE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_OFF] & HCI_SUPP_COMMANDS_READ_CLASS_DEVICE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_OFF 9
+#define HCI_WRITE_CLASS_DEVICE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_OFF] & HCI_SUPP_COMMANDS_WRITE_CLASS_DEVICE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_VOICE_SETTING_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_VOICE_SETTING_OFF 9
+#define HCI_READ_VOICE_SETTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_VOICE_SETTING_OFF] & HCI_SUPP_COMMANDS_READ_VOICE_SETTING_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_OFF 9
+#define HCI_WRITE_VOICE_SETTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_OFF] & HCI_SUPP_COMMANDS_WRITE_VOICE_SETTING_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_OFF 9
+#define HCI_READ_AUTO_FLUSH_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_AUTO_FLUSH_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_OFF 9
+#define HCI_WRITE_AUTO_FLUSH_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_AUTO_FLUSH_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_OFF 9
+#define HCI_READ_NUM_BROAD_RETRANS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_OFF] & HCI_SUPP_COMMANDS_READ_NUM_BROAD_RETRANS_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_OFF 9
+#define HCI_WRITE_NUM_BROAD_RETRANS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_OFF] & HCI_SUPP_COMMANDS_WRITE_NUM_BROAD_RETRANS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_OFF 10
+#define HCI_READ_HOLD_MODE_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_READ_HOLD_MODE_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_OFF 10
+#define HCI_WRITE_HOLD_MODE_ACTIVITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_OFF] & HCI_SUPP_COMMANDS_WRITE_HOLD_MODE_ACTIVITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_OFF 10
+#define HCI_READ_TRANS_PWR_LEVEL_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_OFF] & HCI_SUPP_COMMANDS_READ_TRANS_PWR_LEVEL_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_OFF 10
+#define HCI_READ_SYNCH_FLOW_CTRL_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_OFF] & HCI_SUPP_COMMANDS_READ_SYNCH_FLOW_CTRL_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_MASK 0x10
+#define HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_OFF 10
+#define HCI_WRITE_SYNCH_FLOW_CTRL_ENABLE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_OFF] & HCI_SUPP_COMMANDS_WRITE_SYNCH_FLOW_CTRL_ENABLE_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_MASK 0x20
+#define HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_OFF 10
+#define HCI_SET_HOST_CTRLR_TO_HOST_FC_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_OFF] & HCI_SUPP_COMMANDS_SET_HOST_CTRLR_TO_HOST_FC_MASK)
+
+#define HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_MASK 0x40
+#define HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_OFF 10
+#define HCI_HOST_BUFFER_SIZE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_OFF] & HCI_SUPP_COMMANDS_HOST_BUFFER_SIZE_MASK)
+
+#define HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_MASK 0x80
+#define HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_OFF 10
+#define HCI_HOST_NUM_COMPLETED_PKTS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_OFF] & HCI_SUPP_COMMANDS_HOST_NUM_COMPLETED_PKTS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_OFF 11
+#define HCI_READ_LINK_SUP_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_OFF] & HCI_SUPP_COMMANDS_READ_LINK_SUP_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_OFF 11
+#define HCI_WRITE_LINK_SUP_TOUT_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_OFF] & HCI_SUPP_COMMANDS_WRITE_LINK_SUP_TOUT_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_OFF 11
+#define HCI_READ_NUM_SUPP_IAC_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_OFF] & HCI_SUPP_COMMANDS_READ_NUM_SUPP_IAC_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_OFF 11
+#define HCI_READ_CURRENT_IAC_LAP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_OFF] & HCI_SUPP_COMMANDS_READ_CURRENT_IAC_LAP_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_MASK 0x10
+#define HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_OFF 11
+#define HCI_WRITE_CURRENT_IAC_LAP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_OFF] & HCI_SUPP_COMMANDS_WRITE_CURRENT_IAC_LAP_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_OFF 11
+#define HCI_READ_PAGE_SCAN_PER_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_PER_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_MASK 0x40
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_OFF 11
+#define HCI_WRITE_PAGE_SCAN_PER_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_PER_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_OFF 11
+#define HCI_READ_PAGE_SCAN_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_MASK 0x01
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_OFF 12
+#define HCI_WRITE_PAGE_SCAN_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_MASK 0x02
+#define HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_OFF 12
+#define HCI_SET_AFH_CHNL_CLASS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_OFF] & HCI_SUPP_COMMANDS_SET_AFH_CHNL_CLASS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_OFF 12
+#define HCI_READ_INQUIRY_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_READ_INQUIRY_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_OFF 12
+#define HCI_WRITE_INQUIRY_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_WRITE_INQUIRY_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_OFF 12
+#define HCI_READ_INQUIRY_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_OFF] & HCI_SUPP_COMMANDS_READ_INQUIRY_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_MASK 0x80
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_OFF 12
+#define HCI_WRITE_INQUIRY_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_INQUIRY_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_OFF 13
+#define HCI_READ_PAGE_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_READ_PAGE_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_OFF 13
+#define HCI_WRITE_PAGE_SCAN_TYPE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_OFF] & HCI_SUPP_COMMANDS_WRITE_PAGE_SCAN_TYPE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_OFF 13
+#define HCI_READ_AFH_CHNL_ASSESS_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_OFF] & HCI_SUPP_COMMANDS_READ_AFH_CHNL_ASSESS_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_OFF 13
+#define HCI_WRITE_AFH_CHNL_ASSESS_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_AFH_CHNL_ASSESS_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_MASK 0x08
+#define HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_OFF 14
+#define HCI_READ_LOCAL_VER_INFO_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_VER_INFO_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_MASK 0x10
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_OFF 14
+#define HCI_READ_LOCAL_SUP_CMDS_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_SUP_CMDS_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_OFF 14
+#define HCI_READ_LOCAL_SUPP_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_SUPP_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_OFF 14
+#define HCI_READ_LOCAL_EXT_FEATURES_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_EXT_FEATURES_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_OFF 14
+#define HCI_READ_BUFFER_SIZE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_OFF] & HCI_SUPP_COMMANDS_READ_BUFFER_SIZE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_OFF 15
+#define HCI_READ_COUNTRY_CODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_OFF] & HCI_SUPP_COMMANDS_READ_COUNTRY_CODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_BD_ADDR_MASK 0x02
+#define HCI_SUPP_COMMANDS_READ_BD_ADDR_OFF 15
+#define HCI_READ_BD_ADDR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_BD_ADDR_OFF] & HCI_SUPP_COMMANDS_READ_BD_ADDR_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_OFF 15
+#define HCI_READ_FAIL_CONTACT_CNTR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_OFF] & HCI_SUPP_COMMANDS_READ_FAIL_CONTACT_CNTR_MASK)
+
+#define HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_MASK 0x08
+#define HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_OFF 15
+#define HCI_RESET_FAIL_CONTACT_CNTR_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_OFF] & HCI_SUPP_COMMANDS_RESET_FAIL_CONTACT_CNTR_MASK)
+
+#define HCI_SUPP_COMMANDS_GET_LINK_QUALITY_MASK 0x10
+#define HCI_SUPP_COMMANDS_GET_LINK_QUALITY_OFF 15
+#define HCI_GET_LINK_QUALITY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_GET_LINK_QUALITY_OFF] & HCI_SUPP_COMMANDS_GET_LINK_QUALITY_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_RSSI_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_RSSI_OFF 15
+#define HCI_READ_RSSI_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_RSSI_OFF] & HCI_SUPP_COMMANDS_READ_RSSI_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_MASK 0x40
+#define HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_OFF 15
+#define HCI_READ_AFH_CH_MAP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_OFF] & HCI_SUPP_COMMANDS_READ_AFH_CH_MAP_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_BD_CLOCK_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_BD_CLOCK_OFF 15
+#define HCI_READ_BD_CLOCK_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_BD_CLOCK_OFF] & HCI_SUPP_COMMANDS_READ_BD_CLOCK_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_OFF 16
+#define HCI_READ_LOOPBACK_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_OFF] & HCI_SUPP_COMMANDS_READ_LOOPBACK_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_OFF 16
+#define HCI_WRITE_LOOPBACK_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_LOOPBACK_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_MASK 0x04
+#define HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_OFF 16
+#define HCI_ENABLE_DEV_UNDER_TEST_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_OFF] & HCI_SUPP_COMMANDS_ENABLE_DEV_UNDER_TEST_MASK)
+
+#define HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_MASK 0x08
+#define HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_OFF 16
+#define HCI_SETUP_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_SETUP_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_MASK 0x10
+#define HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_OFF 16
+#define HCI_ACCEPT_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_ACCEPT_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_MASK 0x20
+#define HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_OFF 16
+#define HCI_REJECT_SYNCH_CONN_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_OFF] & HCI_SUPP_COMMANDS_REJECT_SYNCH_CONN_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_OFF 17
+#define HCI_READ_EXT_INQUIRY_RESP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_OFF] & HCI_SUPP_COMMANDS_READ_EXT_INQUIRY_RESP_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_OFF 17
+#define HCI_WRITE_EXT_INQUIRY_RESP_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_OFF] & HCI_SUPP_COMMANDS_WRITE_EXT_INQUIRY_RESP_MASK)
+
+#define HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_MASK 0x04
+#define HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_OFF 17
+#define HCI_REFRESH_ENCRYPTION_KEY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_OFF] & HCI_SUPP_COMMANDS_REFRESH_ENCRYPTION_KEY_MASK)
+
+/* Octet 17, bit 3 is reserved */
+
+#define HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_MASK 0x10
+#define HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_OFF 17
+#define HCI_SNIFF_SUB_RATE_CMD_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_OFF] & HCI_SUPP_COMMANDS_SNIFF_SUB_RATE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_MASK 0x20
+#define HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_OFF 17
+#define HCI_READ_SIMPLE_PAIRING_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_OFF] & HCI_SUPP_COMMANDS_READ_SIMPLE_PAIRING_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_MASK 0x40
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_OFF 17
+#define HCI_WRITE_SIMPLE_PAIRING_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_MASK 0x80
+#define HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_OFF 17
+#define HCI_READ_LOCAL_OOB_DATA_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_OFF] & HCI_SUPP_COMMANDS_READ_LOCAL_OOB_DATA_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_MASK 0x01
+#define HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_OFF 18
+#define HCI_READ_INQUIRY_RESPONSE_TX_POWER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_OFF] & HCI_SUPP_COMMANDS_READ_INQUIRY_RESPONSE_TX_POWER_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_MASK 0x02
+#define HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_OFF 18
+#define HCI_WRITE_INQUIRY_RESPONSE_TX_POWER_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_OFF] & HCI_SUPP_COMMANDS_WRITE_INQUIRY_RESPONSE_TX_POWER_MASK)
+
+#define HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK 0x04
+#define HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF 18
+#define HCI_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF] & HCI_SUPP_COMMANDS_READ_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK 0x08
+#define HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF 18
+#define HCI_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_OFF] & HCI_SUPP_COMMANDS_WRITE_DEFAULT_ERRONEOUS_DATA_REPORTING_MASK)
+
+#define HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_MASK 0x80
+#define HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_OFF 18
+#define HCI_IO_CAPABILITY_RESPONSE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_OFF] & HCI_SUPP_COMMANDS_IO_CAPABILITY_RESPONSE_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_MASK 0x01
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_OFF 19
+#define HCI_USER_CONFIRMATION_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_MASK 0x02
+#define HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_OFF 19
+#define HCI_USER_CONFIRMATION_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_CONFIRMATION_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_MASK 0x04
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_OFF 19
+#define HCI_USER_PASSKEY_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_MASK 0x08
+#define HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_OFF 19
+#define HCI_USER_PASSKEY_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_USER_PASSKEY_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_MASK 0x10
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_OFF 19
+#define HCI_REMOTE_OOB_DATA_REQUEST_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_OFF] & HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_MASK 0x20
+#define HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_OFF 19
+#define HCI_WRITE_SIMPLE_PAIRING_DBG_MODE_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_OFF] & HCI_SUPP_COMMANDS_WRITE_SIMPLE_PAIRING_DBG_MODE_MASK)
+
+#define HCI_SUPP_COMMANDS_ENHANCED_FLUSH_MASK 0x40
+#define HCI_SUPP_COMMANDS_ENHANCED_FLUSH_OFF 19
+#define HCI_ENHANCED_FLUSH_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_ENHANCED_FLUSH_OFF] & HCI_SUPP_COMMANDS_ENHANCED_FLUSH_MASK)
+
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_MASK 0x80
+#define HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_OFF 19
+#define HCI_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_REMOTE_OOB_DATA_REQUEST_NEG_REPLY_MASK)
+
+#define HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_MASK 0x04
+#define HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_OFF 20
+#define HCI_SEND_NOTIF_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_OFF] & HCI_SUPP_COMMANDS_SEND_KEYPRESS_NOTIF_MASK)
+
+#define HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_MASK 0x08
+#define HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_OFF 20
+#define HCI_IO_CAP_REQ_NEG_REPLY_SUPPORTED(x) ((x)[HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_OFF] & HCI_SUPP_COMMANDS_IO_CAP_REQ_NEG_REPLY_MASK)
+
+#endif
+
diff --git a/btusb_1_6_29_1/inc/target.h b/btusb_1_6_29_1/inc/target.h
new file mode 100755
index 0000000..32b5bf9
--- a/dev/null
+++ b/btusb_1_6_29_1/inc/target.h
@@ -0,0 +1,121 @@
+/*
+ *
+ * target.h
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#ifndef _TARGET_H
+#define _TARGET_H
+
+#include <linux/usb.h>
+
+#define BT_API
+#define RFC_API
+#define L2C_API
+
+#define INT int
+#define UINT unsigned int
+#define DWORD unsigned long
+
+#ifndef BOOL
+#define BOOL int
+#endif
+
+#ifndef USHORT
+#define USHORT unsigned short
+#endif
+
+#ifndef ULONG
+#define ULONG unsigned long
+#endif
+
+#ifndef VOID
+#define VOID void
+#endif
+
+#define _vsnprintf vsnprintf
+
+#define __cdecl
+
+#define GKI_USE_DYNAMIC_BUFFERS TRUE /* TRUE if using dynamic buffers */
+
+#define GKI_NUM_FIXED_BUF_POOLS 1
+#define GKI_DEF_BUFPOOL_PERM_MASK 0xfffc /* Pool ID 0 is public */
+
+/* Define the total number of buffer pools used, fixed and dynamic (Maximum is 16) */
+#define GKI_NUM_TOTAL_BUF_POOLS 1
+
+#define GKI_BUF0_SIZE 1740
+#ifdef BTUSB_LITE
+#define GKI_BUF0_MAX 10
+#else
+#define GKI_BUF0_MAX 5
+#endif
+
+#define GKI_POOL_ID_0 0
+
+#define HCI_SCO_POOL_ID GKI_POOL_ID_0 // all SCO data to/from the device
+
+/* Set this flag to non zero if you want to do buffer corruption checks.
+** If set, GKI will check buffer tail corruption every time it processes
+** a buffer. This is very useful for debug, and is minimal overhead in
+** a running system.
+*/
+#define GKI_ENABLE_BUF_CORRUPTION_CHECK 1
+
+#define L2CAP_MTU_SIZE 1691
+//#define L2CAP_MTU_SIZE 200
+
+/* Maximum size in bytes of the codec capabilities information element. */
+#ifndef AVDT_CODEC_SIZE
+#define AVDT_CODEC_SIZE 10
+#endif
+
+/* Number of streams for dual stack */
+#ifndef BTM_SYNC_INFO_NUM_STR
+#define BTM_SYNC_INFO_NUM_STR 2
+#endif
+
+/* Number of streams for dual stack in BT Controller (simulation) */
+#ifndef BTM_SYNC_INFO_NUM_STR_BTC
+#define BTM_SYNC_INFO_NUM_STR_BTC 2
+#endif
+
+#ifndef BTA_AV_NUM_STRS
+#define BTA_AV_NUM_STRS 2
+#endif
+
+#define BTU_STACK_LITE_ENABLED TRUE
+#define BTU_MULTI_AV_INCLUDED TRUE
+
+/* Number of simultaneous links to different peer devices. */
+#ifndef AVDT_NUM_LINKS
+#define AVDT_NUM_LINKS 2
+#endif
+
+/* Number of simultaneous stream endpoints. */
+#ifndef AVDT_NUM_SEPS
+#define AVDT_NUM_SEPS 2
+#endif
+
+#endif
diff --git a/btusb_1_6_29_1/src/.svn/all-wcprops b/btusb_1_6_29_1/src/.svn/all-wcprops
new file mode 100755
index 0000000..635e606
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/all-wcprops
@@ -0,0 +1,53 @@
+K 25
+svn:wc:ra_dav:version-url
+V 72
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src
+END
+btusb_lite_avdt.c
+K 25
+svn:wc:ra_dav:version-url
+V 90
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb_lite_avdt.c
+END
+btusb_isoc.c
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb_isoc.c
+END
+btusb_lite.c
+K 25
+svn:wc:ra_dav:version-url
+V 85
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb_lite.c
+END
+btusb_lite_l2c.c
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb_lite_l2c.c
+END
+btusb_dev.c
+K 25
+svn:wc:ra_dav:version-url
+V 84
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb_dev.c
+END
+btusb.c
+K 25
+svn:wc:ra_dav:version-url
+V 80
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb.c
+END
+btusb_lite_hci.c
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb_lite_hci.c
+END
+btusb_lite_av.c
+K 25
+svn:wc:ra_dav:version-url
+V 88
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/btusb_lite_av.c
+END
diff --git a/btusb_1_6_29_1/src/.svn/entries b/btusb_1_6_29_1/src/.svn/entries
new file mode 100755
index 0000000..6dd8271
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/entries
@@ -0,0 +1,303 @@
+10
+
+dir
+941
+http://10.10.29.8/svn/SiP/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src
+http://10.10.29.8/svn/SiP
+
+
+
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+e48500f2-7125-4e9d-852c-c0ee60673d08
+
+gki
+dir
+
+btusb_lite_avdt.c
+file
+
+
+
+
+2014-08-14T08:53:29.712694Z
+96e56af7608a2483f31e8be2670a74c4
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13339
+
+btusb_isoc.c
+file
+
+
+
+
+2014-08-14T08:53:29.696694Z
+c7a1595ae14bd4bc54e1328e59842609
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+9907
+
+btusb_lite_l2c.c
+file
+
+
+
+
+2014-08-14T08:53:29.696694Z
+7af6b7cffd47addfab3f40ce66a262c6
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+8409
+
+btusb_lite.c
+file
+
+
+
+
+2014-08-14T08:53:29.696694Z
+dbfebe033d70c0fe73fcf7e9ae866ef9
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+58849
+
+btusb_dev.c
+file
+
+
+
+
+2014-08-14T08:53:29.696694Z
+25ec78a3bf1f9fec81c0d671cc88ef3d
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+83812
+
+btusb_lite_hci.c
+file
+
+
+
+
+2014-08-14T08:53:29.712694Z
+1b19eacf4b53b70988c2688bae676bfb
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+13843
+
+btusb.c
+file
+
+
+
+
+2014-08-14T08:53:29.712694Z
+66ab3af0259c5840e3a666ab81dcea36
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+52984
+
+btusb_lite_av.c
+file
+
+
+
+
+2014-08-14T08:53:29.696694Z
+7e8bf3f1f79838f5b4d3ea6ad11bcaeb
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+40155
+
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb.c.svn-base
new file mode 100755
index 0000000..9300a02
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb.c.svn-base
@@ -0,0 +1,1625 @@
+/*
+ *
+ * btusb.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "btusb.h"
+#include "hcidefs.h"
+
+#define BTUSB_VID_BRCM 0x0A5C
+
+// forward reference
+struct usb_driver btusb_driver;
+
+// table of devices that work with this driver
+static struct usb_device_id btusb_table [] =
+{
+#if defined(BTUSB_VID) && defined(BTUSB_PID)
+ /* If a specific Vid/Pid is specified at compilation time */
+ { USB_DEVICE(BTUSB_VID, BTUSB_PID) },
+#else
+ // all BT devices
+ { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS |
+ USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ .bDeviceClass = USB_CLASS_WIRELESS_CONTROLLER,
+ // 0x01 / 0x01 = Bluetooth programming interface
+ .bDeviceSubClass = 0x01,
+ .bDeviceProtocol = 0x01
+ },
+ // all BRCM BT interfaces
+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+ .idVendor = BTUSB_VID_BRCM,
+ .bInterfaceClass = USB_CLASS_WIRELESS_CONTROLLER,
+ // 0x01 / 0x01 = Bluetooth programming interface
+ .bInterfaceSubClass = 0x01,
+ .bInterfaceProtocol = 0x01
+ },
+ // all BRCM vendor specific with Bluetooth programming interface
+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_DEV_CLASS |
+ USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ .idVendor = BTUSB_VID_BRCM,
+ .bDeviceClass = USB_CLASS_VENDOR_SPEC,
+ // 0x01 / 0x01 = Bluetooth programming interface
+ .bDeviceSubClass = 0x01,
+ .bDeviceProtocol = 0x01
+ },
+#endif
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, btusb_table);
+
+static const struct file_operations btusb_debug_fops =
+{
+ .open = btusb_debug_open,
+ .read = seq_read,
+ .write = btusb_debug_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations btusb_scosniff_fops =
+{
+ .open = btusb_scosniff_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = btusb_scosniff_release,
+};
+
+static struct file_operations btusb_fops =
+{
+ .owner = THIS_MODULE,
+ .read = btusb_read,
+ .write = btusb_write,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+ .unlocked_ioctl = btusb_ioctl,
+#else
+ .ioctl = btusb_ioctl,
+#endif
+ .poll = btusb_poll,
+ .open = btusb_open,
+ .release = btusb_release,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver btusb_class =
+{
+ .name = "usb/btusb%d",
+ .fops = &btusb_fops,
+ .minor_base = BTUSB_MINOR_BASE,
+};
+
+
+// static functions
+static int btusb_create(tBTUSB_CB *p_dev, struct usb_interface *p_interface, const struct usb_device_id *p_id);
+
+// module parameter to enable suspend/resume with remote wakeup
+bool autopm = 0;
+
+// module parameter to enable debug flags
+int dbgflags = BTUSB_DBGFLAGS;
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit
+ **
+ ** Description Submit a BTUSB transaction
+ **
+ ** Parameters p_dev: driver control block
+ ** p_anchor: anchor to hook URB to when submitting
+ ** p_trans: transaction to submit
+ ** mem_flags: memory flags to submit the URB with
+ **
+ ** Returns 0 upon success, error core else.
+ **
+ *******************************************************************************/
+int btusb_submit(tBTUSB_CB *p_dev, struct usb_anchor *p_anchor, tBTUSB_TRANSACTION *p_trans, int mem_flags)
+{
+ int status;
+ struct urb *p_urb = p_trans->p_urb;
+
+ BTUSB_DBG("urb %p b=%p\n", p_urb, p_urb->transfer_buffer);
+
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ return -ENODEV;
+ }
+
+ usb_anchor_urb(p_urb, p_anchor);
+ status = usb_submit_urb(p_urb, mem_flags);
+ if (unlikely(status))
+ {
+ BTUSB_ERR("usb_submit_urb failed(%d)\n", status);
+ usb_unanchor_urb(p_urb);
+ p_dev->stats.urb_submit_err++;
+ }
+ else
+ {
+ p_dev->stats.urb_submit_ok++;
+ }
+
+ return status;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_acl_read_complete
+ **
+ ** Description ACL Bulk pipe completion routine
+ **
+ ** Parameters p_urb: URB that completed
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_acl_read_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ int count = p_urb->actual_length;
+
+ BTUSB_DBG("urb %p status %d count %d flags x%x\n", p_urb,
+ p_urb->status, count, p_urb->transfer_flags);
+
+ // number of ACL URB completed
+ p_dev->stats.acl_rx_completed++;
+
+ // check if device is disconnecting, has been unplugged or is closing
+ if (unlikely((p_urb->status == -ESHUTDOWN) ||
+ (p_urb->status == -ENOENT) ||
+ (p_urb->status == -EILSEQ)))
+ {
+ BTUSB_DBG("not queuing URB\n");
+ goto exit;
+ }
+
+ // if there was an error or no data, do not forward to upper layers
+ if (unlikely(p_urb->status || !count))
+ {
+ p_dev->stats.acl_rx_resubmit++;
+ goto resubmit;
+ }
+
+ // increment the number of bytes transferred
+ p_dev->stats.acl_rx_bytes += count;
+
+ // forward up the data
+ btusb_dump_data(p_urb->transfer_buffer, count, "btusb_acl_read_complete");
+ btusb_enqueue(p_dev, p_trans, HCIT_TYPE_ACL_DATA);
+
+ // Do not resubmit since it was forwarded to the user
+ goto exit;
+
+resubmit:
+ if (unlikely(btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_ATOMIC)))
+ p_dev->stats.acl_rx_submit_err++;
+ else
+ p_dev->stats.acl_rx_submit_ok++;
+
+exit:
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_diag_read_complete
+ **
+ ** Description Diag Bulk pipe completion routine
+ **
+ ** Parameters p_urb: URB that completed
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_diag_read_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ int count = p_urb->actual_length;
+
+ BTUSB_DBG("urb %p status %d count %d flags %x\n", p_urb,
+ p_urb->status, count, p_urb->transfer_flags);
+
+ p_dev->stats.diag_rx_completed++;
+
+ // check if device is disconnecting, has been unplugged or is closing
+ if (unlikely((p_urb->status == -ESHUTDOWN) ||
+ (p_urb->status == -ENOENT) ||
+ (p_urb->status == -EILSEQ)))
+ {
+ BTUSB_DBG("not queuing URB\n");
+ goto exit;
+ }
+
+ // if there was an error or no data or no more submitted diags, do not forward to upper layers
+ if (unlikely(p_urb->status || !count || usb_anchor_empty(&p_dev->diag_rx_submitted)))
+ {
+ p_dev->stats.diag_rx_resubmit++;
+ goto resubmit;
+ }
+
+ // increment the number of bytes transferred
+ p_dev->stats.diag_rx_bytes += count;
+
+ // forward up the data
+ btusb_dump_data(p_urb->transfer_buffer, count, "btusb_diag_read_complete");
+ btusb_enqueue(p_dev, p_trans, HCIT_TYPE_LM_DIAG);
+
+ goto exit;
+
+resubmit:
+ if (unlikely(btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_ATOMIC)))
+ p_dev->stats.diag_rx_submit_err++;
+ else
+ p_dev->stats.diag_rx_submit_ok++;
+
+exit:
+ return;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_event_complete
+ **
+ ** Description Interrupt pipe completion routine
+ **
+ ** Parameters p_urb: URB that completed
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_event_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ int count = p_urb->actual_length;
+#if defined (BTUSB_LITE)
+ BT_HDR *p_buf;
+#endif
+
+ BTUSB_DBG("urb %p status %d count %d flags %x\n", p_urb,
+ p_urb->status, count, p_urb->transfer_flags);
+
+ p_dev->stats.event_completed++;
+
+ // check if device is disconnecting, has been unplugged or is closing
+ if (unlikely((p_urb->status == -ESHUTDOWN) ||
+ (p_urb->status == -ENOENT) ||
+ (p_urb->status == -EILSEQ)))
+ {
+ BTUSB_DBG("not queuing URB\n");
+ goto exit;
+ }
+
+ // if there was an error or no data, do not forward to upper layers
+ if (unlikely(p_urb->status || !count))
+ {
+ p_dev->stats.event_resubmit++;
+ goto resubmit;
+ }
+
+#ifdef BTUSB_LITE
+ /* Filter Events received from BT Controller*/
+ if (btusb_lite_hci_event_filter(p_dev, p_trans->dma_buffer, count) == 0)
+ {
+ p_buf = &p_trans->bt_hdr;
+ p_buf->offset = 0;
+ p_buf->event = HCIT_TYPE_EVENT;
+ p_buf->len = p_trans->p_urb->actual_length;
+ btusb_dequeued(p_dev, p_buf);
+ }
+ else
+#endif
+ {
+ /* increment the number of bytes transferred */
+ p_dev->stats.event_bytes += count;
+
+ /* forward up the event */
+ btusb_dump_data(p_urb->transfer_buffer, count, "btusb_event_complete");
+ btusb_enqueue(p_dev, p_trans, HCIT_TYPE_EVENT);
+ }
+
+ /* Do not resubmit since it was forwarded to the user */
+ goto exit;
+
+resubmit:
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_ATOMIC)))
+ p_dev->stats.event_submit_err++;
+ else
+ p_dev->stats.event_submit_ok++;
+
+exit:
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_probe
+ **
+ ** Description Device probe callback
+ ** assuming the following USB device configuration :
+ **
+ ** NumInterfaces = 4
+ ** Interface 0 Alt settings 0
+ ** 3 end point excluding end point 0
+ ** 1 interrupt end point -> event
+ ** 2 bulk for acl in and out
+ ** Interface 1 Alt settings 0
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 1
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 2
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 3
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 4
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 5
+ ** 2 Iso end point excluding end point 0
+ ** Interface 2 Alt settings 0
+ ** 2 bulk end point for diags
+ ** Interface 3 Alt settings 0
+ ** 0 end point point i.e. only the control endpoint is used
+ ** Parameters
+ **
+ ** Returns 0 upon success, error core else.
+ **
+ *******************************************************************************/
+static int btusb_probe(struct usb_interface *p_interface, const struct usb_device_id *p_id)
+{
+ tBTUSB_CB *p_dev;
+ struct usb_ctrlrequest *p_dr;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+ struct urb *p_urb;
+ int idx, jdx;
+ tBTUSB_TRANSACTION *p_trans;
+ int retval = -ENOMEM;
+ char procname[64];
+
+ BTUSB_INFO("p_interface=%p, p_id=%p\n", p_interface, p_id);
+ BTUSB_INFO("p_interface->cur_altsetting->desc.bInterfaceNumber=%d\n", p_interface->cur_altsetting->desc.bInterfaceNumber);
+ BTUSB_DBG("match=0x%x VID=0x%x PID=0x%x class=0x%x subclass=0x%x protocol=0x%x\n",
+ p_id->match_flags, p_id->idVendor, p_id->idProduct, p_id->bDeviceClass, p_id->bDeviceSubClass,
+ p_id->bDeviceProtocol);
+
+ // Bluetooth core Interface number must be 0 (hardcoded in the spec)
+ if (p_interface->cur_altsetting->desc.bInterfaceNumber != 0)
+ {
+ BTUSB_INFO("InterfaceNumber is not 0. This is not a Bluetooth Interface\n");
+ return -ENODEV;
+ }
+
+ // allocate memory for our device
+ p_dev = kzalloc(sizeof(tBTUSB_CB), GFP_KERNEL);
+ if (p_dev == NULL)
+ {
+ dev_err(&p_interface->dev, "Out of memory\n");
+ goto error;
+ }
+ BTUSB_DBG("allocated p_dev=%p\n", p_dev);
+
+ if (btusb_create(p_dev, p_interface, p_id))
+ {
+ goto error;
+ }
+
+ // set up the endpoint information
+ // use only the first bulk-in and bulk-out endpoints
+ p_host_intf = p_interface->cur_altsetting;
+ BTUSB_DBG("%u endpoints\n", p_host_intf->desc.bNumEndpoints);
+
+ for (idx = 0; idx < p_host_intf->desc.bNumEndpoints; ++idx)
+ {
+ p_ep_desc = &p_host_intf->endpoint[idx].desc;
+ BTUSB_DBG("endpoint addr 0x%x attr 0x%x\n",
+ p_ep_desc->bEndpointAddress, p_ep_desc->bmAttributes);
+ if ((!p_dev->p_acl_in) &&
+ BTUSB_EP_DIR_IN(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk in endpoint
+ p_dev->p_acl_in = &p_host_intf->endpoint[idx];
+ }
+
+ if ((!p_dev->p_event_in) &&
+ BTUSB_EP_DIR_IN(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_INT))
+ {
+ // we found an interrupt in end point
+ p_dev->p_event_in = &p_host_intf->endpoint[idx];
+ }
+
+ if ((!p_dev->p_acl_out) &&
+ BTUSB_EP_DIR_OUT(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk out end point
+ p_dev->p_acl_out = &p_host_intf->endpoint[idx];
+ }
+ }
+
+ // now start looking at the voice interface (check if it a BT interface)
+ p_dev->p_voice_intf = usb_ifnum_to_if(p_dev->p_udev, 1);
+ if (p_dev->p_voice_intf)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[0];
+ if (((p_host_intf->desc.bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER) ||
+ (p_host_intf->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC)) &&
+ (p_host_intf->desc.bInterfaceSubClass == 1) &&
+ (p_host_intf->desc.bInterfaceProtocol == 1))
+ {
+ // can claim here, but prefer to check there are ISO endpoints
+ }
+ else
+ {
+ BTUSB_INFO("Interface 1 is not VOICE\n");
+ goto no_voice;
+ }
+ for (idx = 0; idx < p_dev->p_voice_intf->num_altsetting; idx++)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[idx];
+ for (jdx = 0; jdx < p_host_intf->desc.bNumEndpoints; jdx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[jdx].desc;
+ if (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_ISOC)
+ {
+ // found an ISO endpoint, claim interface and stop here
+ if (usb_driver_claim_interface(&btusb_driver, p_dev->p_voice_intf, p_dev) != 0)
+ {
+ BTUSB_ERR("failed claiming iso interface\n");
+ // reset it to prevent releasing it
+ p_dev->p_voice_intf = NULL;
+ goto error_claim;
+ }
+ BTUSB_DBG("claimed iso interface\n");
+
+ // set it into a disabled state
+ if (usb_set_interface(p_dev->p_udev, 1, 0))
+ {
+ BTUSB_ERR("failed to set iso intf to 0\n");
+ }
+ goto found_voice;
+ }
+ }
+ }
+ }
+no_voice:
+ p_dev->p_voice_intf = NULL;
+found_voice:
+
+ // grab other interfaces if present
+ p_dev->p_diag_intf = usb_ifnum_to_if(p_dev->p_udev, 2);
+ if (p_dev->p_diag_intf)
+ {
+ p_host_intf = &p_dev->p_diag_intf->altsetting[0];
+ if ((p_host_intf->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
+ (p_host_intf->desc.bInterfaceSubClass == 255) &&
+ (p_host_intf->desc.bInterfaceProtocol == 255))
+ {
+ if (usb_driver_claim_interface(&btusb_driver, p_dev->p_diag_intf, p_dev) != 0)
+ {
+ BTUSB_ERR("failed claiming diag interface\n");
+ p_dev->p_diag_intf = NULL;
+ goto no_diag;
+ }
+ }
+ else
+ {
+ BTUSB_INFO("Interface 2 is not DIAG\n");
+ p_dev->p_diag_intf = NULL;
+ goto no_diag;
+ }
+
+ BTUSB_DBG("claimed diag interface bNumEndpoints %d\n", p_host_intf->desc.bNumEndpoints);
+ for (idx = 0; idx < p_host_intf->desc.bNumEndpoints; ++idx)
+ {
+ p_ep_desc = &p_host_intf->endpoint[idx].desc;
+ BTUSB_DBG("diag endpoint addr 0x%x attr 0x%x\n",
+ p_ep_desc->bEndpointAddress, p_ep_desc->bmAttributes);
+ if ((!p_dev->p_diag_in) &&
+ BTUSB_EP_DIR_IN(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk in end point
+ p_dev->p_diag_in = &p_host_intf->endpoint[idx];
+ }
+ if ((!p_dev->p_diag_out) &&
+ BTUSB_EP_DIR_OUT(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk out end point
+ p_dev->p_diag_out = &p_host_intf->endpoint[idx];
+ }
+ }
+ }
+no_diag:
+
+ // try to get the DFU interface
+ p_dev->p_dfu_intf = usb_ifnum_to_if(p_dev->p_udev, 3);
+ if (p_dev->p_dfu_intf)
+ {
+ p_host_intf = &p_dev->p_dfu_intf->altsetting[0];
+ if ((p_host_intf->desc.bInterfaceClass == USB_CLASS_APP_SPEC) &&
+ (p_host_intf->desc.bInterfaceSubClass == 1))
+ {
+ if (usb_driver_claim_interface(&btusb_driver, p_dev->p_dfu_intf, p_dev) != 0)
+ {
+ BTUSB_ERR("failed claiming dfu interface\n");
+ p_dev->p_dfu_intf = NULL;
+ goto no_dfu;
+ }
+ BTUSB_DBG("claimed DFU interface bNumEndpoints %d\n", p_dev->p_dfu_intf->cur_altsetting->desc.bNumEndpoints);
+ }
+ else
+ {
+ BTUSB_INFO("Interface 3 is not DFU\n");
+ p_dev->p_dfu_intf = NULL;
+ goto no_dfu;
+ }
+ }
+no_dfu:
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->cmd_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_CMD_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("cmd_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ p_dr = &p_dev->cmd_req_array[idx];
+ p_dr->bRequestType = USB_TYPE_CLASS;
+ p_dr->bRequest = 0;
+ p_dr->wIndex = 0;
+ p_dr->wValue = 0;
+ p_dr->wLength = 0;
+
+ usb_fill_control_urb(p_urb,
+ p_dev->p_udev,
+ usb_sndctrlpipe(p_dev->p_udev, 0),
+ (void *)p_dr,
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_CMD_SIZE,
+ btusb_cmd_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ // initialize the USB data paths
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_EVT_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("event_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_int_urb(p_urb,
+ p_dev->p_udev,
+ usb_rcvintpipe(p_dev->p_udev, p_dev->p_event_in->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_EVT_SIZE,
+ btusb_event_complete,
+ p_trans,
+ p_dev->p_event_in->desc.bInterval);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("acl_rx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_rcvbulkpipe(p_dev->p_udev, p_dev->p_acl_in->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_acl_read_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_tx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("acl_tx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_sndbulkpipe(p_dev->p_udev, p_dev->p_acl_out->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_write_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ // if it is a composite device, BULK out transfers must be ZERO packet terminated
+ if (p_dev->quirks & BTUSB_QUIRK_ZLP_TX_REQ)
+ {
+ BTUSB_DBG("acl_tx_array[%d]: add ZERO_PACKET\n", idx);
+ p_urb->transfer_flags |= URB_ZERO_PACKET;
+ }
+ }
+
+ if (p_dev->p_diag_in)
+ {
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("diag_rx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_rcvbulkpipe(p_dev->p_udev, p_dev->p_diag_in->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_diag_read_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+ }
+
+ if (p_dev->p_diag_out)
+ {
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_tx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("diag_tx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_sndbulkpipe(p_dev->p_udev, p_dev->p_diag_out->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_write_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+ }
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->voice_rx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_VOICE_BUFFER_MAXSIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(BTUSB_VOICE_FRAMES_PER_URB, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("voice_rx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+
+ p_urb->dev = p_dev->p_udev;
+ p_urb->transfer_buffer = p_trans->dma_buffer;
+ p_urb->transfer_buffer_length = BTUSB_VOICE_BUFFER_MAXSIZE;
+ p_urb->complete = btusb_voicerx_complete;
+ p_urb->context = p_trans;
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP | URB_ISO_ASAP;
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ usb_init_urb(&p_dev->p_voicetxIrpList[idx].urb);
+ }
+
+ // we can register the device now, as it is ready
+ usb_set_intfdata(p_interface, p_dev);
+ retval = usb_register_dev(p_interface, &btusb_class);
+ if (retval)
+ {
+ // something prevented us from registering this driver
+ BTUSB_ERR("Not able to get a minor for this device\n");
+ goto error_claim;
+ }
+
+ // start sending IN tokens
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ if (btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_KERNEL))
+ {
+ p_dev->stats.event_submit_err++;
+ BTUSB_ERR("btusb_submit(event) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.event_submit_ok++;
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ if (btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_KERNEL))
+ {
+ p_dev->stats.acl_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(acl_rx) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.acl_rx_submit_ok++;
+ }
+ if (p_dev->p_diag_in)
+ {
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ if (btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_KERNEL))
+ {
+ p_dev->stats.diag_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(diag) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.diag_rx_submit_ok++;
+ }
+ }
+
+ /* Create the proc filesystem entry. To make it easy to retrieve, the
+ * entry created is called /proc/driver/btusbN where btusbN matches the
+ * file entry in /dev.
+ * The name of the device in /dev comes from the device created when
+ * usb_register_dev was called (in the current fn). The name was built
+ * from the btusb_class structure. usb_register_dev calls device_create
+ * which creates the VFS entry. This can be found in online linux code.
+ */
+ scnprintf(procname, sizeof(procname), "driver/%s", p_interface->usb_dev->kobj.name);
+ p_dev->p_debug_pde = proc_create_data(procname, S_IRUGO | S_IWUGO, NULL, &btusb_debug_fops, p_dev);
+ if (p_dev->p_debug_pde == NULL)
+ {
+ BTUSB_ERR("Couldn't create proc entry\n");
+ }
+ else
+ {
+ BTUSB_DBG("created /proc/%s\n", procname);
+ }
+
+ scnprintf(procname, sizeof(procname), "driver/%s-scosniff", p_interface->usb_dev->kobj.name);
+ p_dev->p_scosniff_pde = proc_create_data(procname, S_IRUGO, NULL, &btusb_scosniff_fops, p_dev);
+ if (p_dev->p_scosniff_pde == NULL)
+ {
+ BTUSB_ERR("Couldn't create proc SCO sniff entry\n");
+ }
+ else
+ {
+ BTUSB_DBG("created /proc/%s\n", procname);
+ INIT_LIST_HEAD(&p_dev->scosniff_list);
+ init_completion(&p_dev->scosniff_completion);
+ }
+
+#ifdef BTUSB_LITE
+ btusb_lite_create(p_dev, p_interface);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+ if(autopm)
+ {
+ BTUSB_INFO("Enabling for remote wakeup\n");
+ p_interface->needs_remote_wakeup = 1;
+
+ BTUSB_INFO("Setting power/wakeup to enabled\n");
+ device_set_wakeup_enable(&p_dev->p_udev->dev, 1);
+
+ BTUSB_INFO("Enabling for autosuspend\n");
+ usb_enable_autosuspend(p_dev->p_udev);
+ }
+#else
+ autopm = 0;
+ BTUSB_INFO("USB suspend/resume not supported for this kernel version\n");
+#endif
+
+ // let the user know what node this device is now attached to
+ BTUSB_DBG("device now attached to minor %d\n", p_interface->minor);
+
+ return 0;
+
+error_bt_submit:
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->acl_tx_submitted);
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->diag_tx_submitted);
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+ usb_kill_anchored_urbs(&p_dev->cmd_submitted);
+ usb_kill_anchored_urbs(&p_dev->voice_rx_submitted);
+
+ usb_deregister_dev(p_interface, &btusb_class);
+
+error_claim:
+ usb_set_intfdata(p_interface, NULL);
+ if (p_dev->p_diag_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_diag_intf);
+ p_dev->p_diag_intf = NULL;
+ BTUSB_DBG("released diag interface\n");
+ }
+ if (p_dev->p_dfu_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_dfu_intf);
+ p_dev->p_dfu_intf = NULL;
+ BTUSB_DBG("released dfu interface\n");
+ }
+ if (p_dev->p_voice_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_voice_intf);
+ p_dev->p_voice_intf = NULL;
+ BTUSB_DBG("released iso interface\n");
+ }
+
+error:
+ if (p_dev)
+ {
+ kref_put(&p_dev->kref, btusb_delete);
+ }
+ return retval;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_cancel_voice
+ **
+ ** Description Cancel all pending voice requests and wait for their cancellations
+ **
+ ** Parameters p_dev: device instance control block
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_cancel_voice(tBTUSB_CB *p_dev)
+{
+ int idx;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ BTUSB_DBG("enter\n");
+
+ // cancel rx
+ BTUSB_DBG("Removing SCO RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->voice_rx_submitted);
+
+ // free any SCO HCI message being consolidated
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->p_msg != NULL)
+ {
+ GKI_freebuf(p_chan->p_msg);
+ p_chan->p_msg = NULL;
+ }
+ }
+ // clear active RX processing
+ p_dev->pending_bytes = 0;
+ p_dev->pp_pending_msg = NULL;
+ p_dev->pending_hdr_size = 0;
+
+
+ // cancel tx
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ if (p_dev->p_voicetxIrpList[idx].used)
+ {
+ BTUSB_DBG("canceling tx URB %d\n", idx);
+ usb_kill_urb(&p_dev->p_voicetxIrpList[idx].urb);
+ p_dev->p_voicetxIrpList[idx].used = 0;
+ BTUSB_DBG("tx URB %d canceled\n", idx);
+ }
+ }
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_cancel_urbs
+ **
+ ** Description Cancel all pending non-voice requests and wait for their cancellations
+ **
+ ** Parameters pointer on usb_bt struck that contains all the btusb info
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_cancel_urbs(tBTUSB_CB *p_dev)
+{
+ BTUSB_DBG("enter\n");
+
+ // stop reading data
+ BTUSB_DBG("Removing ACL RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+
+ // stop reading events
+ BTUSB_DBG("Removing EVENT anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+
+ // stop reading diags
+ BTUSB_DBG("Removing DIAG anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+
+ // cancel ACL writes
+ BTUSB_DBG("Removing ACL TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_tx_submitted);
+
+ // cancel commands
+ BTUSB_DBG("Removing CMD anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->cmd_submitted);
+
+ // cancel diags
+ BTUSB_DBG("Removing DIAG TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_tx_submitted);
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_disconnect
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being disconnected
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static void btusb_disconnect(struct usb_interface *p_interface)
+{
+ tBTUSB_CB *p_dev = usb_get_intfdata(p_interface);
+ int idx;
+ char procname[64];
+
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("p_dev == NULL\n");
+ return;
+ }
+
+ if (p_interface != p_dev->p_main_intf)
+ {
+ BTUSB_DBG("not the main interface\n");
+ return;
+ }
+
+ // clear the interface data information
+ usb_set_intfdata(p_interface, NULL);
+
+ scnprintf(procname, sizeof(procname), "driver/%s", p_interface->usb_dev->kobj.name);
+ remove_proc_entry(procname, NULL);
+
+ scnprintf(procname, sizeof(procname), "driver/%s-scosniff", p_interface->usb_dev->kobj.name);
+ remove_proc_entry(procname, NULL);
+
+#ifdef BTUSB_LITE
+ btusb_lite_stop_all(p_dev);
+ btusb_lite_delete(p_dev, p_interface);
+#endif
+
+ BTUSB_DBG("shutting down HCI intf\n");
+
+ /* prevent more I/O from starting */
+ spin_lock_bh(&p_dev->tasklet_lock);
+ p_dev->p_main_intf = NULL;
+ spin_unlock_bh(&p_dev->tasklet_lock);
+
+ // cancel pending requests
+ btusb_cancel_voice(p_dev);
+ btusb_cancel_urbs(p_dev);
+
+ // give back our minor
+ BTUSB_DBG("unregistering #%d\n", p_interface->minor);
+ usb_deregister_dev(p_interface, &btusb_class);
+
+ // release interfaces
+ if (p_dev->p_diag_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_diag_intf);
+ p_dev->p_diag_intf = NULL;
+ BTUSB_DBG("released diag interface\n");
+ }
+ if (p_dev->p_dfu_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_dfu_intf);
+ p_dev->p_dfu_intf = NULL;
+ BTUSB_DBG("released dfu interface\n");
+ }
+ if (p_dev->p_voice_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_voice_intf);
+ p_dev->p_voice_intf = NULL;
+ BTUSB_DBG("released iso interface\n");
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ p_dev->p_voicetxIrpList[idx].used = 0;
+ }
+
+ if(autopm)
+ {
+ BTUSB_INFO("Disabling for remote wakeup\n");
+ p_dev->p_main_intf->needs_remote_wakeup = 0;
+
+ BTUSB_INFO("Setting power/wakeup to disabled\n");
+ device_set_wakeup_enable(&p_dev->p_udev->dev, 0);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+ BTUSB_INFO("Disabling autosuspend\n");
+ usb_disable_autosuspend(p_dev->p_udev);
+#endif
+ }
+
+ // decrement the reference counter
+ BTUSB_DBG("kref_put -> &p_dev->kref 0x%p \n", &p_dev->kref);
+ kref_put(&p_dev->kref, btusb_delete);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_suspend
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being suspended
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static int btusb_suspend(struct usb_interface *p_interface, pm_message_t message)
+{
+ tBTUSB_CB *p_dev = usb_get_intfdata(p_interface);
+
+ if (unlikely(!p_dev))
+ return 0;
+
+ if (p_dev->p_main_intf == p_interface)
+ {
+ BTUSB_INFO("Suspending USB\n");
+ BTUSB_DBG("main interface (%p)\n",p_dev->p_main_intf);
+
+ // stop reading data
+ BTUSB_DBG("Removing ACL RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+
+ // stop reading events
+ BTUSB_DBG("Removing EVENT anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+
+ // cancel ACL writes
+ BTUSB_DBG("Removing ACL TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_tx_submitted);
+
+ // cancel commands
+ BTUSB_DBG("Removing CMD anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->cmd_submitted);
+
+ }
+ if (p_dev->p_voice_intf == p_interface)
+ {
+ BTUSB_DBG("voice interface (%p)\n",p_dev->p_voice_intf);
+ }
+ if (p_dev->p_dfu_intf == p_interface)
+ {
+ BTUSB_DBG("dfu interface (%p)\n",p_dev->p_dfu_intf);
+ }
+ if (p_dev->p_diag_intf == p_interface)
+ {
+ BTUSB_DBG("diag interface (%p)\n",p_dev->p_diag_intf);
+
+ // stop reading diags
+ BTUSB_DBG("Removing DIAG RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+
+ // cancel diags
+ BTUSB_DBG("Removing DIAG TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_tx_submitted);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_resume
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being resumed
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static int btusb_resume(struct usb_interface *p_interface)
+{
+ tBTUSB_CB *p_dev = usb_get_intfdata(p_interface);
+ int idx;
+ int retval = -ENOMEM;
+ tBTUSB_TRANSACTION *p_trans;
+
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("p_dev == NULL\n");
+ return retval;
+ }
+
+ if (p_dev->p_main_intf == p_interface)
+ {
+ BTUSB_DBG("main interface (%p)\n",p_dev->p_main_intf);
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ if (likely(p_trans->dma_buffer != NULL))
+ {
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_KERNEL)))
+ {
+ p_dev->stats.event_submit_err++;
+ BTUSB_ERR("btusb_submit(event) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.event_submit_ok++;
+ }
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ if (likely(p_trans->dma_buffer != NULL))
+ {
+ if (unlikely(btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_KERNEL)))
+ {
+ p_dev->stats.acl_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(acl_rx) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.acl_rx_submit_ok++;
+ }
+ }
+ }
+ if (p_dev->p_voice_intf == p_interface)
+ {
+ BTUSB_DBG("voice interface (%p)\n",p_dev->p_voice_intf);
+ }
+ if (p_dev->p_dfu_intf == p_interface)
+ {
+ BTUSB_DBG("dfu interface (%p)\n",p_dev->p_dfu_intf);
+ }
+ if (p_dev->p_diag_intf == p_interface)
+ {
+ BTUSB_DBG("diag interface (%p)\n",p_dev->p_diag_intf);
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ if (likely(p_trans->dma_buffer != NULL))
+ {
+ if (unlikely(btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_KERNEL)))
+ {
+ p_dev->stats.diag_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(diag) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.diag_rx_submit_ok++;
+ }
+ }
+ }
+
+ return 0;
+
+error_bt_submit:
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+
+ usb_deregister_dev(p_interface, &btusb_class);
+ return retval;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_reset_resume
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being resumed
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static int btusb_reset_resume(struct usb_interface *p_interface)
+{
+ BTUSB_DBG("enter\n");
+
+ return btusb_resume(p_interface);
+}
+
+
+struct usb_driver btusb_driver =
+{
+ .name = "btusb",
+ .id_table = btusb_table,
+ .probe = btusb_probe,
+ .disconnect = btusb_disconnect,
+ .suspend = btusb_suspend,
+ .resume = btusb_resume,
+ .reset_resume = btusb_reset_resume,
+ .supports_autosuspend = 1
+};
+
+/*******************************************************************************
+ **
+ ** Function btusb_create
+ **
+ ** Description Initialize the control block
+ **
+ ** Returns 0 upon success, error core else.
+ **
+ *******************************************************************************/
+static int btusb_create(tBTUSB_CB *p_dev, struct usb_interface *p_interface, const struct usb_device_id *p_id)
+{
+ unsigned idx;
+ struct usb_host_config *p_config;
+ struct usb_host_interface *p_host_intf;
+
+ // initialize the elements of the device structure
+ mutex_init(&p_dev->open_mutex);
+ spin_lock_init(&p_dev->tasklet_lock);
+ kref_init(&p_dev->kref);
+ GKI_init_q(&p_dev->tx_queue);
+ GKI_init_q(&p_dev->rx_queue);
+ init_waitqueue_head(&p_dev->rx_wait_q);
+ init_usb_anchor(&p_dev->acl_rx_submitted);
+ init_usb_anchor(&p_dev->event_submitted);
+ init_usb_anchor(&p_dev->diag_rx_submitted);
+ init_usb_anchor(&p_dev->acl_tx_submitted);
+ init_usb_anchor(&p_dev->cmd_submitted);
+ init_usb_anchor(&p_dev->diag_tx_submitted);
+ init_usb_anchor(&p_dev->voice_rx_submitted);
+
+ // save the USB information
+ p_dev->p_udev = usb_get_dev(interface_to_usbdev(p_interface));
+ p_dev->p_id = p_id;
+ p_dev->p_main_intf = p_interface;
+
+ // register tx task so we can start sending data to transport
+ tasklet_init(&p_dev->tx_task, btusb_tx_task, (unsigned long)p_dev);
+ BTUSB_DBG("tasklet_init complete\n");
+
+ BTUSB_DBG("sizeof(tBTUSB_ISO_ELEMENT)*BTUSB_NUM_OF_VOICE_TX_BUFFERS=%zu\n",
+ sizeof(tBTUSB_ISO_ELEMENT)*BTUSB_NUM_OF_VOICE_TX_BUFFERS);
+ p_dev->p_voicetxIrpList = kzalloc(sizeof(tBTUSB_ISO_ELEMENT)*BTUSB_NUM_OF_VOICE_TX_BUFFERS, GFP_KERNEL);
+ if (p_dev->p_voicetxIrpList == NULL)
+ {
+ dev_err(&p_interface->dev, "Out of memory for voice TX\n");
+ return -ENOMEM;
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ p_dev->p_voicetxIrpList[idx].packet = kmalloc(BTUSB_MAXIMUM_TX_VOICE_SIZE, GFP_KERNEL);
+ if (p_dev->p_voicetxIrpList[idx].packet == NULL)
+ return -ENOMEM;
+ }
+
+ p_dev->kterm.c_line = N_HCI;
+ p_dev->kterm.c_iflag = IGNPAR | ICRNL;
+ p_dev->kterm.c_oflag = 0;
+ p_dev->kterm.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD;
+ p_dev->kterm.c_lflag = ICANON;
+ p_dev->kterm.c_ispeed = p_dev->kterm.c_ospeed = 115200;
+ p_dev->kterm.c_cc[VEOF] = 4;
+ p_dev->kterm.c_cc[VMIN] = 1;
+
+ // check if there is a WiFi interface in the same device
+ p_config = p_dev->p_udev->actconfig;
+ for (idx = 1; idx < p_config->desc.bNumInterfaces; idx++)
+ {
+ p_host_intf = &p_config->interface[idx]->altsetting[0];
+ if ((p_host_intf->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
+ (p_host_intf->desc.bInterfaceSubClass == 2) &&
+ (p_host_intf->desc.bInterfaceProtocol == 255))
+ {
+ p_dev->issharedusb = true;
+ }
+ }
+
+ // set quirks
+ if (p_dev->issharedusb)
+ {
+ // all shared USB devices need a ZLP to be sent in TX
+ p_dev->quirks |= BTUSB_QUIRK_ZLP_TX_REQ;
+
+ if ((le16_to_cpu(p_dev->p_udev->descriptor.idVendor) == 0x0A5C) &&
+ (le16_to_cpu(p_dev->p_udev->descriptor.idProduct) == 0x0BDC))
+ {
+ // the 43242 has a specific bug that needs to append 1 byte because it
+ // can not send ZLP
+ p_dev->quirks |= BTUSB_QUIRK_ZLP_RX_WA;
+ }
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_delete
+ **
+ ** Description Fully remove the elements for a device
+ **
+ ** Parameters kref: reference counter
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+void btusb_delete(struct kref *kref)
+{
+ tBTUSB_CB *p_dev = container_of(kref, tBTUSB_CB, kref);
+ tBTUSB_TRANSACTION *p_trans;
+ BT_HDR *p_buf = NULL;
+ int idx;
+
+ BTUSB_DBG("enter\n");
+
+#ifdef BTUSB_LITE
+ btusb_lite_stop_all(p_dev);
+#endif
+
+ // stop tx_task and then remove any data packets from tx_q
+ tasklet_kill(&p_dev->tx_task);
+
+ BTUSB_DBG("tasklet_kill complete\n");
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->tx_queue)) != NULL)
+ {
+ GKI_freebuf(p_buf);
+ }
+
+ BTUSB_DBG("dequeued all remaining buffers from TX Q\n");
+
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->rx_queue)) != NULL)
+ {
+ btusb_dequeued(p_dev, p_buf);
+ }
+
+ if (p_dev->p_write_msg)
+ {
+ GKI_freebuf(p_dev->p_write_msg);
+ }
+
+ BTUSB_DBG("dequeued all remaining buffers from RX Q\n");
+
+ // ensure that the process is not hanging on select()/poll()
+ wake_up_interruptible(&p_dev->rx_wait_q);
+
+ // free allocated USB DMA space
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->cmd_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_CMD_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_EVT_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_tx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_tx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->voice_rx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_VOICE_BUFFER_MAXSIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ usb_put_dev(p_dev->p_udev);
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ if (p_dev->p_voicetxIrpList[idx].packet)
+ {
+ kfree(p_dev->p_voicetxIrpList[idx].packet);
+ }
+ }
+
+ if (p_dev->p_voicetxIrpList)
+ {
+ kfree(p_dev->p_voicetxIrpList);
+ }
+ kfree(p_dev);
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_init
+ **
+ ** Description Module init routine
+ **
+ ** Parameters None
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static int __init btusb_init(void)
+{
+ int result;
+
+ BTUSB_DBG("built %s,%s\n", __DATE__, __TIME__);
+
+ // initialize the GKI
+ GKI_init();
+
+ // register this driver with the USB subsystem
+ result = usb_register(&btusb_driver);
+ if (result)
+ {
+ BTUSB_ERR("usb_register failed (%d)\n", result);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_exit
+ **
+ ** Description Module exit routine
+ **
+ ** Parameters None
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static void __exit btusb_exit(void)
+{
+ BTUSB_DBG("enter\n");
+
+ // shutdown the GKI
+ GKI_shutdown();
+
+ // deregister this driver from the USB subsystem
+ usb_deregister(&btusb_driver);
+}
+
+module_init(btusb_init);
+module_exit(btusb_exit);
+
+module_param(autopm, bool, 0644);
+MODULE_PARM_DESC(autopm, "Enable suspend/resume with remote wakeup");
+module_param(dbgflags, int, 0644);
+MODULE_PARM_DESC(dbgflags, "Debug flags");
+
+MODULE_DESCRIPTION("Broadcom Bluetooth USB driver");
+MODULE_LICENSE("GPL");
+
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb_dev.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb_dev.c.svn-base
new file mode 100755
index 0000000..3638b1b
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb_dev.c.svn-base
@@ -0,0 +1,2630 @@
+/*
+ *
+ * btusb_dev.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/serial.h>
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/jiffies.h>
+
+#include "btusb.h"
+
+#include "hcidefs.h"
+
+#include "gki_int.h"
+
+// delay between the voice samples: 3 ms
+#define BTUSB_VOICE_DELAY 3
+
+// local functions declaration
+static int btusb_add_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle, unsigned char burst);
+static int btusb_remove_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle);
+static int btusb_update_voice_channels(tBTUSB_CB *p_dev);
+static void btusb_update_voice_rx(tBTUSB_CB *p_dev);
+static void btusb_submit_voice_tx(tBTUSB_CB *p_dev, UINT8 *p_data, int len);
+static int btusb_submit_cmd(tBTUSB_CB *p_dev, char *packet, unsigned long length);
+static int btusb_submit_acl(tBTUSB_CB *p_dev, char *packet, unsigned long length);
+static int btusb_submit_diag(tBTUSB_CB *p_dev, char *packet, unsigned long length);
+static int btusb_submit_write_voice(tBTUSB_CB *p_dev, void *p_packet, unsigned long length);
+
+/*******************************************************************************
+ **
+ ** Function btusb_alloc_trans
+ **
+ ** Description Allocate a transaction in the array of transactions.
+ **
+ ** Parameters p_array: array of USB transactions
+ ** size: size of the array of transactions
+ **
+ ** Returns Pointer to the next free transaction, NULL if not found
+ **
+ *******************************************************************************/
+static tBTUSB_TRANSACTION *btusb_alloc_trans(tBTUSB_TRANSACTION *p_array, size_t size)
+{
+ int idx;
+ tBTUSB_TRANSACTION *p_trans;
+
+ for (idx = 0; idx < size; idx++)
+ {
+ p_trans = &p_array[idx];
+ if (p_trans->gki_hdr.status == BUF_STATUS_FREE)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+ return p_trans;
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_dump_data
+ **
+ ** Description Print the data into the kernel messages
+ **
+ ** Parameters p: pointer to the data to print
+ ** len: length of the data to print
+ ** p_title: title to print before the data
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_dump_data(const UINT8 *p, int len, const char *p_title)
+{
+ int idx;
+
+ if (likely((dbgflags & BTUSB_DBG_MSG) == 0))
+ {
+ return;
+ }
+
+ if (p_title)
+ {
+ printk("---------------------- %s ----------------------\n", p_title);
+ }
+
+ printk("%p: ", p);
+
+ for(idx = 0; idx < len; idx++)
+ {
+ printk("%02x ", p[idx]);
+ }
+ printk("\n--------------------------------------------------------------------\n");
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_voice_stats
+ **
+ ** Description
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_voice_stats(unsigned long *p_max, unsigned long *p_min,
+ struct timeval *p_result, struct timeval *p_last_time)
+{
+ struct timeval current_time;
+
+ do_gettimeofday(&current_time);
+ // perform the carry for the later subtraction by updating y
+ if (current_time.tv_usec < p_last_time->tv_usec) {
+ int nsec = (p_last_time->tv_usec - current_time.tv_usec) / 1000000 + 1;
+ p_last_time->tv_usec -= 1000000 * nsec;
+ p_last_time->tv_sec += nsec;
+ }
+ if (current_time.tv_usec - p_last_time->tv_usec > 1000000) {
+ int nsec = (current_time.tv_usec - p_last_time->tv_usec) / 1000000;
+ p_last_time->tv_usec += 1000000 * nsec;
+ p_last_time->tv_sec -= nsec;
+ }
+ // compute the time remaining to wait
+ p_result->tv_sec = current_time.tv_sec - p_last_time->tv_sec;
+ p_result->tv_usec = current_time.tv_usec - p_last_time->tv_usec;
+
+ // update the max except the first time where the calculation is wrong
+ // because of the initial value assuming p_last is zero initialized
+ if (p_max != NULL)
+ {
+ if (p_result->tv_usec > *p_max && (p_last_time->tv_sec) && (p_last_time->tv_usec))
+ {
+ *p_max = p_result->tv_usec;
+ }
+ }
+
+ // update the min except the first time where the calculation is wrong
+ // because of the initial value assuming *p_last and p_min are zero initialized
+ if (p_min != NULL)
+ {
+ if ((p_result->tv_usec < *p_min || (*p_min == 0))
+ && (p_last_time->tv_sec) && (p_last_time->tv_usec))
+ {
+ *p_min = p_result->tv_usec;
+ }
+ }
+
+ memcpy(p_last_time, &current_time, sizeof(struct timeval));
+ BTUSB_DBG("btusb_voice_stats len: %lu\n", p_result->tv_usec);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_tx_task
+ **
+ ** Description host to controller tasklet
+ **
+ ** Parameters arg:
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_tx_task(unsigned long arg)
+{
+ tBTUSB_CB *p_dev = (tBTUSB_CB *) arg;
+ BT_HDR *p_buf;
+ UINT8 *p_data;
+ UINT8 msg_type;
+
+ // dequeue data packet and submit to transport
+ if (unlikely((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->tx_queue)) == NULL))
+ {
+ BTUSB_DBG("dequeued data = NULL - just return\n");
+ goto reschedule_task;
+ }
+
+ // bypass the header and retrieve the type
+ p_data = (UINT8 *) (p_buf + 1) + p_buf->offset;
+
+ // extract message type
+ STREAM_TO_UINT8(msg_type, p_data);
+ switch (msg_type)
+ {
+ case HCIT_TYPE_SCO_DATA:
+ btusb_submit_voice_tx(p_dev, p_data, p_buf->len - 4);
+ break;
+ case HCIT_TYPE_COMMAND:
+#ifdef BTUSB_LITE
+ /* Filter User's Write operation to catch some commands(VSCs) */
+ if (btusb_lite_hci_cmd_filter(p_dev, p_buf))
+#endif
+ {
+ btusb_submit_cmd(p_dev, p_data, p_buf->len - 1);
+ }
+ break;
+ case HCIT_TYPE_ACL_DATA:
+ btusb_submit_acl(p_dev, p_data, p_buf->len - 1);
+ break;
+ case HCIT_TYPE_LM_DIAG:
+ btusb_submit_diag(p_dev, p_data, p_buf->len - 1);
+ break;
+ }
+ GKI_freebuf(p_buf);
+
+reschedule_task:
+ if (p_dev->tx_queue.count)
+ tasklet_schedule(&p_dev->tx_task);
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_enqueue
+ **
+ ** Description Add a received USB message into the user queue
+ **
+ ** Parameters p_dev: device instance control block
+ ** p_trans: transaction to forward
+ ** hcitype: type of HCI data in the USB transaction
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_enqueue(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, UINT8 hcitype)
+{
+ BT_HDR *p_buf = &p_trans->bt_hdr;
+ struct urb *p_urb = p_trans->p_urb;
+ UINT8 *p = (UINT8 *)p_urb->transfer_buffer;
+ UINT16 len;
+
+ BTUSB_DBG("len = %d\n", p_urb->actual_length);
+
+ switch (hcitype)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ // retrieve the length in the packet header
+ p += 2;
+ STREAM_TO_UINT16(len, p);
+ len += 4;
+ break;
+
+ case HCIT_TYPE_EVENT:
+ // retrieve the length in the packet header
+ p += 1;
+ STREAM_TO_UINT8(len, p);
+ len += 2;
+ break;
+
+ case HCIT_TYPE_LM_DIAG:
+ len = HCIT_LM_DIAG_LENGTH;
+ break;
+
+ default:
+ BTUSB_ERR("Unsupported HCI type: %d\n", hcitype);
+ len = p_urb->actual_length;
+ break;
+ }
+
+ // quirk for the ZLP HW issue
+ if (unlikely(((len % 16) == 0) && (p_dev->quirks & BTUSB_QUIRK_ZLP_RX_WA) &&
+ (p_urb->actual_length == (len + 1))))
+ {
+ BTUSB_DBG("missing ZLP workaround: %d != %d\n", p_urb->actual_length, len);
+ p_urb->actual_length = len;
+ }
+ // check if the length matches that of the ACL packet
+ if (unlikely(len != p_urb->actual_length))
+ {
+ BTUSB_ERR("URB data length does not match packet %d != %d\n", p_urb->actual_length, len);
+ }
+
+ // fill up the header of the message
+ p_buf->event = hcitype;
+ p_buf->len = p_urb->actual_length;
+ p_buf->offset = 0;
+ p_buf->layer_specific &= ~BTUSB_LS_H4_TYPE_SENT;
+
+ // InQ for user-space to read
+ GKI_enqueue(&p_dev->rx_queue, p_buf);
+
+ // if the process is polling, indicate RX event
+ wake_up_interruptible(&p_dev->rx_wait_q);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_dequeued
+ **
+ ** Description Figure out what to do with a dequeued message
+ **
+ ** Parameters p_dev: driver control block
+ ** p_msg: dequeued message
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_dequeued(tBTUSB_CB *p_dev, BT_HDR *p_msg)
+{
+ tBTUSB_TRANSACTION *p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+
+ switch (p_msg->event)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ if (unlikely(btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_KERNEL)))
+ p_dev->stats.acl_rx_submit_err++;
+ else
+ p_dev->stats.acl_rx_submit_ok++;
+ break;
+
+ case HCIT_TYPE_EVENT:
+#if defined(BTUSB_LITE)
+ // when BTUSB_LITE is defined, EVT may be resubmitted from IRQ context
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_ATOMIC)))
+#else
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_KERNEL)))
+#endif
+ p_dev->stats.event_submit_err++;
+ else
+ p_dev->stats.event_submit_ok++;
+ break;
+
+ case HCIT_TYPE_LM_DIAG:
+ if (unlikely(btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_KERNEL)))
+ p_dev->stats.diag_rx_submit_err++;
+ else
+ p_dev->stats.diag_rx_submit_ok++;
+ break;
+
+ default:
+ GKI_freebuf(p_msg);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_open
+ **
+ ** Description User mode open callback
+ **
+ *******************************************************************************/
+int btusb_open(struct inode *inode, struct file *file)
+{
+ tBTUSB_CB *p_dev;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+ BT_HDR *p_buf;
+
+ BTUSB_INFO("enter\n");
+
+ // retrieve the minor for this inode
+ subminor = iminor(inode);
+
+ // retrieve the USB interface attached to this minor
+ interface = usb_find_interface(&btusb_driver, subminor);
+ if (!interface)
+ {
+ BTUSB_ERR("can't find interface for minor %d\n", subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+ BTUSB_INFO("minor %u\n", subminor);
+
+ // retrieve the device driver structure pointer
+ p_dev = usb_get_intfdata(interface);
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (!p_dev)
+ {
+ BTUSB_ERR("can't find device\n");
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ mutex_lock(&p_dev->open_mutex);
+ if (p_dev->opened)
+ {
+ mutex_unlock(&p_dev->open_mutex);
+ BTUSB_ERR("multiple open not allowed %d\n", p_dev->opened);
+ retval = -EBUSY;
+ goto exit;
+ }
+ // save our object in the file's private structure
+ file->private_data = p_dev;
+ p_dev->opened = true;
+ mutex_unlock(&p_dev->open_mutex);
+
+ // increment our usage count for the device
+ BTUSB_INFO("kref_get -> &p_dev->kref 0x%p\n", &p_dev->kref);
+ kref_get(&p_dev->kref);
+
+ // free all pending messages in Rx queue
+ BTUSB_DBG("Free Rx Queue count:%d\n", p_dev->rx_queue.count);
+ while ((p_buf = (BT_HDR *)GKI_dequeue(&p_dev->rx_queue)) != NULL)
+ {
+ btusb_dequeued(p_dev, p_buf);
+ }
+
+exit:
+ return retval;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_release
+ **
+ ** Description User mode close callback
+ **
+ *******************************************************************************/
+int btusb_release(struct inode *inode, struct file *file)
+{
+ tBTUSB_CB *p_dev;
+ BT_HDR *p_buf = NULL;
+ int idx;
+
+ BTUSB_INFO("enter\n");
+
+ p_dev = (tBTUSB_CB *) file->private_data;
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+#ifdef BTUSB_LITE
+ btusb_lite_stop_all(p_dev);
+#endif
+
+ // indicate driver is closed
+ mutex_lock(&p_dev->open_mutex);
+ p_dev->opened = false;
+ mutex_unlock(&p_dev->open_mutex);
+
+ // free all the pending elements
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->tx_queue)) != NULL)
+ {
+ GKI_freebuf(p_buf);
+ }
+
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->rx_queue)) != NULL)
+ {
+ btusb_dequeued(p_dev, p_buf);
+ }
+
+ // ensure there is no process hanging on poll / select
+ wake_up_interruptible(&p_dev->rx_wait_q);
+
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ if (p_dev->voice_channels[idx].used)
+ {
+ if (btusb_remove_voice_channel(p_dev, p_dev->voice_channels[idx].info.sco_handle))
+ {
+ BTUSB_ERR("btusb_remove_voice_channel failed\n");
+ }
+ }
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ p_dev->p_voicetxIrpList[idx].used = 0;
+ }
+
+ // decrement the usage count on our device
+ BTUSB_INFO("kref_put -> &p_dev->kref 0x%p\n", &p_dev->kref);
+ kref_put(&p_dev->kref, btusb_delete);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_get_rx_packet
+ **
+ ** Description Get (extract) next buffer to sent to User Space
+ **
+ *******************************************************************************/
+static BT_HDR *btusb_get_rx_packet(struct btusb_cb *p_dev)
+{
+ // if there is a pending Rx buffer
+ if (p_dev->p_rx_msg)
+ {
+ return p_dev->p_rx_msg;
+ }
+#ifdef BTUSB_LITE
+ /* If HCI is over IPC */
+ if (btusb_lite_is_hci_over_ipc(p_dev))
+ {
+ return NULL;
+ }
+#endif
+
+ // dequeue the next buffer and store its reference
+ p_dev->p_rx_msg = GKI_dequeue(&p_dev->rx_queue);
+
+ return p_dev->p_rx_msg;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_free_rx_packet
+ **
+ ** Description Free buffer sent to User Space
+ **
+ *******************************************************************************/
+static void btusb_free_rx_packet(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ if (unlikely(p_msg != p_dev->p_rx_msg))
+ {
+ BTUSB_ERR("Dequeued buffer (%p) does not matched working buffer (%p)\n",
+ p_msg, p_dev->p_rx_msg);
+ }
+
+ p_dev->p_rx_msg = NULL;
+
+ if (unlikely(p_msg->layer_specific & BTUSB_LS_GKI_BUFFER))
+ {
+ GKI_freebuf(p_msg);
+ }
+ else
+ {
+ // buffer received from USB -> resubmit
+ btusb_dequeued(p_dev, p_msg);
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_get_rx_packet_buffer
+ **
+ ** Description Get pointer address of data to send to User Space
+ **
+ *******************************************************************************/
+static UINT8 *btusb_get_rx_packet_buffer(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ tBTUSB_TRANSACTION *p_trans;
+
+ switch(p_msg->event)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ case HCIT_TYPE_EVENT:
+ case HCIT_TYPE_LM_DIAG:
+ if (unlikely(p_msg->layer_specific & BTUSB_LS_GKI_BUFFER))
+ {
+ return ((char *)(p_msg + 1) + p_msg->offset);
+ }
+ else
+ {
+ p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+ return (p_trans->dma_buffer + p_msg->offset);
+ }
+ default: // SCO etc...
+ return ((char *)(p_msg + 1) + p_msg->offset);
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_read
+ **
+ ** Description User mode read
+ **
+ ** Returns Number of bytes read, error number if negative
+ **
+ *******************************************************************************/
+ssize_t btusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+{
+ tBTUSB_CB *p_dev = (tBTUSB_CB *)file->private_data;
+ UINT16 len;
+ size_t remainder = count;
+ BT_HDR *p_buf = NULL;
+ char *p_data;
+ char type;
+ int retval;
+
+ BTUSB_DBG("p_dev=%p count=%zu\n", p_dev, count);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->opened))
+ {
+ BTUSB_ERR("driver is not open\n");
+ return -EINVAL;
+ }
+
+ // if read is non blocking and there is no data
+ if (unlikely((file->f_flags & O_NONBLOCK) && (btusb_get_rx_packet(p_dev) == NULL)))
+ {
+ BTUSB_INFO("Non blocking read without any data\n");
+ return -EAGAIN;
+ }
+
+ // wait for an event
+ retval = wait_event_interruptible(p_dev->rx_wait_q,
+ ((p_buf = btusb_get_rx_packet(p_dev)) != NULL));
+ if (unlikely(retval))
+ {
+ BTUSB_DBG("read wait interrupted\n");
+ return retval;
+ }
+ BTUSB_DBG("buffer=%p len=%u ls=%u\n", p_buf, p_buf->len, p_buf->layer_specific);
+
+ switch(p_buf->event)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ case HCIT_TYPE_EVENT:
+ case HCIT_TYPE_LM_DIAG:
+ // if this is the first time buffer is picked, add HCI header in user space
+ if (likely(!(p_buf->layer_specific & BTUSB_LS_H4_TYPE_SENT)))
+ {
+ if (likely(remainder >= 1))
+ {
+ type = p_buf->event;
+ // add the H4 packet header
+ if (unlikely(copy_to_user(buffer, &type, 1)))
+ {
+ BTUSB_ERR("copy to user error\n");
+ return -EINVAL;
+ }
+ buffer += 1;
+ remainder -= 1;
+ }
+ else
+ {
+ BTUSB_ERR("Not enough space to copy H4 ACL header\n");
+ goto read_end;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // retrieve address of the next data to send (depends on event)
+ p_data = btusb_get_rx_packet_buffer(p_dev, p_buf);
+
+ // take the min of remainder and p_buf length
+ if (likely(p_buf->len < remainder))
+ {
+ len = p_buf->len;
+ }
+ else
+ {
+ len = remainder;
+ }
+
+ // copy the message data to the available user space
+ if (unlikely(copy_to_user(buffer, p_data, len)))
+ {
+ BTUSB_ERR("copy to user error\n");
+ return -EINVAL;
+ }
+ remainder -= len;
+ p_buf->len -= len;
+ p_buf->offset += len;
+ p_buf->layer_specific |= BTUSB_LS_H4_TYPE_SENT;
+
+ // free the first buffer if it is empty
+ if (likely(p_buf->len == 0))
+ {
+ // free (fake event) or resubmit (real USB buffer) the buffer sent to app
+ btusb_free_rx_packet(p_dev, p_buf);
+ }
+
+read_end:
+ return (count - remainder);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_write
+ **
+ ** Description User mode write
+ **
+ ** Returns Number of bytes written, error number if negative
+ **
+ *******************************************************************************/
+ssize_t btusb_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos)
+{
+ tBTUSB_CB *p_dev;
+ BT_HDR *p_msg;
+ UINT8 *p_data;
+ size_t remainder = count;
+ int err;
+ UINT16 appended, len;
+
+ p_dev = (tBTUSB_CB *)file->private_data;
+
+ BTUSB_DBG("p_dev=%p count=%zu\n", p_dev, count);
+
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->opened))
+ {
+ return -EINVAL;
+ }
+
+ if (unlikely(count == 0))
+ {
+ return 0;
+ }
+
+ // check that the incoming data is good
+ if (unlikely(!access_ok(VERIFY_READ, (void *)user_buffer, count)))
+ {
+ BTUSB_ERR("buffer access verification failed\n");
+ return -EFAULT;
+ }
+
+ while (remainder)
+ {
+ BTUSB_DBG("remain=%zu p_write_msg=%p\n", remainder, p_dev->p_write_msg);
+ // check if there is already an active transmission buffer
+ p_msg = p_dev->p_write_msg;
+ if (likely(!p_msg))
+ {
+ // get a buffer from the pool
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + BTUSB_H4_MAX_SIZE);
+ if (unlikely(!p_msg))
+ {
+ BTUSB_ERR("unable to get GKI buffer - write failed\n");
+ return -EINVAL;
+ }
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return -EINVAL;
+ }
+ p_dev->p_write_msg = p_msg;
+
+ p_msg->event = 0;
+ p_msg->len = 0;
+ p_msg->offset = 0;
+ p_msg->layer_specific = 0;
+ }
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ // append the entire data to the buffer (not exceeding buffer length)
+ if (likely(remainder < (BTUSB_H4_MAX_SIZE - p_msg->len)))
+ appended = remainder;
+ else
+ appended = BTUSB_H4_MAX_SIZE - p_msg->len;
+ if (unlikely(copy_from_user(p_data + p_msg->len, (void *)user_buffer, appended)))
+ {
+ BTUSB_ERR("copy from user error\n");
+ return -EINVAL;
+ }
+ BTUSB_DBG("msg_len=%u appended=%u\n", p_msg->len, appended);
+
+ // update the size of the buffer
+ p_msg->len += appended;
+
+ // compute the real HCI packet length (by default 0xFFFF to mark incomplete)
+ len = 0xFFFF;
+ switch(p_data[0])
+ {
+ case HCIT_TYPE_SCO_DATA:
+ case HCIT_TYPE_COMMAND:
+ if (likely(p_msg->len >= 4))
+ {
+ // bypass HCI type + opcode/connection handle
+ p_data += 3;
+ STREAM_TO_UINT8(len, p_data);
+ len += 4;
+ BTUSB_DBG("SCO/CMD len=%u cur=%u\n", len, p_msg->len);
+ }
+ break;
+ case HCIT_TYPE_ACL_DATA:
+ if (likely(p_msg->len >= 5))
+ {
+ // bypass HCI type + connection handle
+ p_data += 3;
+ STREAM_TO_UINT16(len, p_data);
+ len += 5;
+ // sanity check : ACL buffer should not be larger than supported
+ if (unlikely(len > BTUSB_H4_MAX_SIZE))
+ {
+ BTUSB_ERR("ACL packet too long (%u)\n", len);
+ GKI_freebuf(p_dev->p_write_msg);
+ p_dev->p_write_msg = NULL;
+ return -EINVAL;
+ }
+ BTUSB_DBG("ACL len=%u cur=%u\n", len, p_msg->len);
+ }
+ break;
+ case HCIT_TYPE_LM_DIAG:
+ // this packet does not have a length, so just send everything
+ len = p_msg->len;
+ BTUSB_DBG("DIAG len=%u cur=%u\n", len, p_msg->len);
+ break;
+ default:
+ BTUSB_ERR("unsupported packet type\n");
+ return count;
+ break;
+ }
+ // check if the buffer length exceeds the packet length
+ if (likely(p_msg->len >= len))
+ {
+ // remove the extra data (belonging to next HCI packet)
+ if (unlikely(p_msg->len > len))
+ {
+ // remove exceeding data
+ appended -= p_msg->len - len;
+ // set len to computed HCI packet length
+ p_msg->len = len;
+ }
+ if (autopm)
+ {
+ err = usb_autopm_get_interface(p_dev->p_main_intf);
+ if (unlikely(err < 0))
+ {
+ BTUSB_ERR("autopm failed\n");
+ autopm = 0;
+ }
+ }
+
+ // add the incoming data and notify the btusb_tx_task to process
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ // wake up tasklet
+ tasklet_schedule(&p_dev->tx_task);
+
+ // new write message
+ p_dev->p_write_msg = NULL;
+ }
+ remainder -= appended;
+ user_buffer += appended;
+ }
+
+ return count;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_poll
+ **
+ ** Description Poll callback (to implement select)
+ **
+ ** Parameters file : file structure of the opened instance
+ ** p_pt : poll table to which the local queue must be added
+ **
+ ** Returns Mask of the type of polling supported, error number if negative
+ **
+ *******************************************************************************/
+unsigned int btusb_poll(struct file *file, struct poll_table_struct *p_pt)
+{
+ tBTUSB_CB *p_dev;
+ unsigned int mask;
+
+ BTUSB_DBG("enter\n");
+
+ // retrieve the device from the file pointer
+ p_dev = (tBTUSB_CB *) file->private_data;
+ BTUSB_DBG("p_dev=%p\n", p_dev);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ // check if the device was disconnected
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->opened))
+ {
+ return -EINVAL;
+ }
+
+ // indicate to the system on which queue it should poll (non blocking call)
+ poll_wait(file, &p_dev->rx_wait_q, p_pt);
+
+ // enable WRITE (select/poll is not write blocking)
+ mask = POLLOUT | POLLWRNORM;
+
+ // enable READ only if data is queued from HCI
+ if (btusb_get_rx_packet(p_dev))
+ {
+ mask |= POLLIN | POLLRDNORM;
+ }
+
+ return mask;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_print_voice_stat
+ **
+ ** Description SCO print voice stats
+ **
+ ** Parameters p_stat buffer holding the statistic to display.
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_print_voice_stat(tBTUSB_STATS * p_stat)
+{
+ printk("______________btusb_print_voice_stat______________\n");
+
+ printk("Number of voice reqs submitted USB stack %lu\n", p_stat->voicerx_submitted);
+ printk("Number of voice rx submitted in error %lu\n", p_stat->voicerx_submitted_error);
+ printk("Number of voice req completions from the USB software stack %lu\n", p_stat->voicerx_completed);
+ printk("Number of Voice req completions in error %lu\n", p_stat->voicerx_completed_error);
+ printk("Voice frames discarded due to bad status %lu\n", p_stat->voicerx_bad_packets);
+ printk("Voice frames discarded due to no headers in data %lu\n", p_stat->voicerx_disc_nohdr);
+
+ printk("Raw bytes received %lu\n",p_stat->voicerx_raw_bytes);
+ printk("Skipped bytes because no header matched %lu\n",p_stat->voicerx_skipped_bytes);
+ printk("Number of Voice Tx reqs submitted %lu\n",p_stat->voicetx_submitted);
+ printk("Number of voice tx submitted in error %lu\n",p_stat->voicetx_submitted_error);
+ printk("Number of Voice Tx reqs completed %lu\n",p_stat->voicetx_completed);
+ printk("Number of Voice Tx reqs completed in error %lu\n",p_stat->voicetx_completed_error);
+ printk("Number of Voice Tx not submitted due to no room on the tx queue %lu\n",
+ p_stat->voicetx_disc_nobuf);
+ printk("Number of Voice tx not submitted due to too long data %lu\n",
+ p_stat->voicetx_disc_toolong);
+
+ printk("voice pending counter %lu, max %lu\n", p_stat->voice_tx_cnt, p_stat->voice_max_tx_cnt);
+ p_stat->voice_tx_cnt=0;p_stat->voice_max_tx_cnt=0;
+
+ printk("Delta time between voice tx_done routine in us max: %lu, min: %lu\n", p_stat->voice_max_tx_done_delta_time, p_stat->voice_min_tx_done_delta_time);
+ memset(&(p_stat->voice_tx_done_delta_time) , 0, sizeof(struct timeval));
+ memset(&(p_stat->voice_last_tx_done_ts) , 0, sizeof(struct timeval));
+ p_stat->voice_max_tx_done_delta_time = 0;
+ p_stat->voice_min_tx_done_delta_time = 0;
+
+ printk("Delta time between voice tx feeding routine in us max: %lu, min: %lu\n", p_stat->voice_max_rx_feeding_interval, p_stat->voice_min_rx_feeding_interval);
+ memset(&(p_stat->voice_rx_feeding_interval) , 0, sizeof(struct timeval));
+ memset(&(p_stat->voice_last_rx_feeding_ts) , 0, sizeof(struct timeval));
+ p_stat->voice_max_rx_feeding_interval = 0;
+ p_stat->voice_min_rx_feeding_interval = 0;
+
+ printk("Delta time between voice rx_rdy routine max in us: %lu, min : %lu\n", p_stat->voice_max_rx_rdy_delta_time, p_stat->voice_min_rx_rdy_delta_time);
+ memset(&(p_stat->voice_rx_rdy_delta_time) , 0, sizeof(struct timeval));
+ memset(&(p_stat->voice_last_rx_rdy_ts) , 0, sizeof(struct timeval));
+ p_stat->voice_max_rx_rdy_delta_time = 0;
+ p_stat->voice_min_rx_rdy_delta_time = 0;
+
+ printk("_______________________________________________________\n");
+}
+
+#define BTUSB_RETURN_STR(__c) case __c: return #__c
+static const char *btusb_ioctl_string(unsigned int cmd)
+{
+ switch(cmd)
+ {
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_GET_STATS);
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_CLEAR_STATS);
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_ADD_VOICE_CHANNEL);
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_REMOVE_VOICE_CHANNEL);
+ BTUSB_RETURN_STR(TCGETS);
+ BTUSB_RETURN_STR(TCSETS);
+ BTUSB_RETURN_STR(TCSETSW);
+ BTUSB_RETURN_STR(TCSETSF);
+ BTUSB_RETURN_STR(TCGETA);
+ BTUSB_RETURN_STR(TCSETA);
+ BTUSB_RETURN_STR(TCSETAW);
+ BTUSB_RETURN_STR(TCSETAF);
+ BTUSB_RETURN_STR(TCSBRK);
+ BTUSB_RETURN_STR(TCXONC);
+ BTUSB_RETURN_STR(TCFLSH);
+ BTUSB_RETURN_STR(TIOCGSOFTCAR);
+ BTUSB_RETURN_STR(TIOCSSOFTCAR);
+ BTUSB_RETURN_STR(TIOCGLCKTRMIOS);
+ BTUSB_RETURN_STR(TIOCSLCKTRMIOS);
+#ifdef TIOCGETP
+ BTUSB_RETURN_STR(TIOCGETP);
+ BTUSB_RETURN_STR(TIOCSETP);
+ BTUSB_RETURN_STR(TIOCSETN);
+#endif
+#ifdef TIOCGETC
+ BTUSB_RETURN_STR(TIOCGETC);
+ BTUSB_RETURN_STR(TIOCSETC);
+#endif
+#ifdef TIOCGLTC
+ BTUSB_RETURN_STR(TIOCGLTC);
+ BTUSB_RETURN_STR(TIOCSLTC);
+#endif
+#ifdef TCGETX
+ BTUSB_RETURN_STR(TCGETX);
+ BTUSB_RETURN_STR(TCSETX);
+ BTUSB_RETURN_STR(TCSETXW);
+ BTUSB_RETURN_STR(TCSETXF);
+#endif
+ BTUSB_RETURN_STR(TIOCMGET);
+ BTUSB_RETURN_STR(TIOCMSET);
+ BTUSB_RETURN_STR(TIOCGSERIAL);
+ BTUSB_RETURN_STR(TIOCMIWAIT);
+ BTUSB_RETURN_STR(TIOCMBIC);
+ BTUSB_RETURN_STR(TIOCMBIS);
+ default:
+ return "unknwown";
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_ioctl
+ **
+ ** Description User mode ioctl
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success or an error code.
+ **
+ *******************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+long btusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#else
+int btusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+#endif
+{
+ const char *s_cmd;
+ tBTUSB_CB *p_dev;
+ tBTUSB_SCO_INFO sco_info;
+ int retval = 0;
+
+ s_cmd = btusb_ioctl_string(cmd);
+
+ BTUSB_INFO("cmd=%s\n", s_cmd);
+
+ p_dev = (tBTUSB_CB *) file->private_data;
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ // check if the device was disconnected
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ switch (cmd)
+ {
+ case IOCTL_BTWUSB_GET_STATS:
+ if (copy_to_user((void *) arg, &p_dev->stats, sizeof(tBTUSB_STATS)))
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case IOCTL_BTWUSB_CLEAR_STATS:
+ memset(&p_dev->stats, 0, sizeof(tBTUSB_STATS));
+ break;
+
+ case IOCTL_BTWUSB_ADD_VOICE_CHANNEL:
+ if (copy_from_user(&sco_info, (void *) arg, sizeof(sco_info)))
+ {
+ BTUSB_ERR("BTUSB_IOCTL_ADD_VOICE_CHANNEL failed getting 1st par\n");
+ retval = -EFAULT;
+ goto err_out;
+ }
+ return btusb_add_voice_channel(p_dev, sco_info.sco_handle, sco_info.burst);
+
+ case IOCTL_BTWUSB_REMOVE_VOICE_CHANNEL:
+ if (copy_from_user(&sco_info, (void *) arg, sizeof(sco_info)))
+ {
+ BTUSB_ERR("BTUSB_IOCTL_ADD_VOICE_CHANNEL failed getting 1st par\n");
+ retval = -EFAULT;
+ goto err_out;
+ }
+ return btusb_remove_voice_channel(p_dev, sco_info.sco_handle);
+
+ case TCGETS:
+ /* dummy support of TTY IOCTLs */
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+#ifndef TCGETS2
+ if (kernel_termios_to_user_termios((struct termios __user *)arg, &p_dev->kterm))
+#else
+ if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &p_dev->kterm))
+#endif
+ {
+ BTUSB_ERR("failure copying termios\n");
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case TCSETSW:
+ case TCSETS:
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+#ifndef TCGETS2
+ if (user_termios_to_kernel_termios(&p_dev->kterm, (struct termios __user *)arg))
+#else
+ if (user_termios_to_kernel_termios_1(&p_dev->kterm, (struct termios __user *)arg))
+#endif
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case TCSETSF:
+ case TCGETA:
+ case TCSETA:
+ case TCSETAW:
+ case TCSETAF:
+ case TCSBRK:
+ case TCXONC:
+ case TCFLSH:
+ case TIOCGSOFTCAR:
+ case TIOCSSOFTCAR:
+ case TIOCGLCKTRMIOS:
+ case TIOCSLCKTRMIOS:
+#ifdef TIOCGETP
+ case TIOCGETP:
+ case TIOCSETP:
+ case TIOCSETN:
+#endif
+#ifdef TIOCGETC
+ case TIOCGETC:
+ case TIOCSETC:
+#endif
+#ifdef TIOCGLTC
+ case TIOCGLTC:
+ case TIOCSLTC:
+#endif
+#ifdef TCGETX
+ case TCGETX:
+ case TCSETX:
+ case TCSETXW:
+ case TCSETXF:
+#endif
+ case TIOCMSET:
+ case TIOCMBIC:
+ case TIOCMBIS:
+ /* dummy support of TTY IOCTLs */
+ BTUSB_DBG("TTY ioctl not implemented\n");
+ break;
+
+ case TIOCGSERIAL:
+ {
+ struct serial_struct tmp;
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = 0;
+ tmp.line = 0;
+ tmp.port = 0;
+ tmp.irq = 0;
+ tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ tmp.xmit_fifo_size = 4096;
+ tmp.baud_base = 115200;
+ tmp.close_delay = 5*HZ;
+ tmp.closing_wait = 30*HZ;
+ tmp.custom_divisor = 0;
+ tmp.hub6 = 0;
+ tmp.io_type = 0;
+ if (copy_to_user((void __user *)arg, &tmp, sizeof(tmp)))
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = 0;
+ break;
+ }
+
+ case TIOCMGET:
+ {
+ int tiocm = TIOCM_RTS | TIOCM_CTS;
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+
+ if (copy_to_user((void __user *)arg, &tiocm, sizeof(tiocm)))
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = 0;
+ break;
+ }
+
+ case TIOCMIWAIT:
+ {
+ DECLARE_WAITQUEUE(wait, current);
+
+ BTUSB_DBG("arg = %lu\n", arg);
+ while (1)
+ {
+ BTUSB_DBG("adding task to wait list\n");
+ add_wait_queue(&p_dev->rx_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ BTUSB_DBG("removing task from wait list\n");
+ remove_wait_queue(&p_dev->rx_wait_q, &wait);
+ /* see if a signal woke us up */
+ if (signal_pending(current))
+ {
+ BTUSB_ERR("signal was pending\n");
+ retval = -ERESTARTSYS;
+ goto err_out;
+ }
+ // do not check the expected signals
+ retval = 0;
+ break;
+ }
+ break;
+ }
+ default:
+ BTUSB_ERR("unknown cmd %u\n", cmd);
+ retval = -ENOIOCTLCMD;
+ break;
+ }
+
+err_out:
+ BTUSB_DBG("returning %d\n", retval);
+ return retval;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_write_complete
+ **
+ ** Description Data write (bulk pipe) completion routine
+ **
+ ** Parameters urb pointer
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_write_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+
+ BTUSB_DBG("status %d length %u flags %x\n", p_urb->status,
+ p_urb->transfer_buffer_length, p_urb->transfer_flags);
+
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+
+ if (unlikely(p_urb->status))
+ {
+ p_dev->stats.writes_completed_error++;
+ printk(KERN_ERR "BTUSB btusb_write_complete failure %d\n", p_urb->status);
+ }
+ else
+ {
+ p_dev->stats.writes_completed++;
+ }
+
+ if(autopm)
+ {
+ usb_autopm_put_interface(p_dev->p_main_intf);
+ }
+
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_strip_off_acl_handle
+ **
+ ** Description Strip off the ACL handle if this is firmware download packet
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_strip_off_acl_handle(char* *packet, unsigned long *length)
+{
+ UINT8* p = (UINT8 *) (*packet);
+
+ BTUSB_DBG("first bytes are %02X %02X\n", *p, *(p+1));
+
+ // check special handle for firmware download packet
+ if ((*p == 0xEF) && (*(p+1) == 0xBE))
+ {
+ *packet = (char *) (p + 4);
+ *length -= 4;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_acl
+ **
+ ** Description ACL write submission to the controller
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success, negative value if error
+ **
+ *******************************************************************************/
+int btusb_submit_acl(tBTUSB_CB *p_dev, char *packet, unsigned long length)
+{
+ int retval;
+ tBTUSB_TRANSACTION *p_trans;
+
+ BTUSB_DBG("%p[%lu]\n", packet, length);
+
+ // strip off the ACL handle if this is a firmware download packet
+ btusb_strip_off_acl_handle (&packet, &length);
+ BTUSB_DBG("after adjusting %p[%lu]\n", packet, length);
+
+ btusb_dump_data(packet, length, "OUTGOING DATA");
+
+
+
+ p_trans = btusb_alloc_trans(p_dev->acl_tx_array, ARRAY_SIZE(p_dev->acl_tx_array));
+ if (unlikely(p_trans == NULL))
+ {
+ return -ENOMEM;
+ }
+
+ if (unlikely(length > BTUSB_HCI_MAX_ACL_SIZE))
+ {
+ retval = -E2BIG;
+ goto error;
+ }
+
+#if 0
+ // if this is called directly from write call
+ if (copy_from_user(p_trans->dma_buffer, user_buffer, length))
+ {
+ retval = -EFAULT;
+ goto error;
+ }
+#else
+ memcpy(p_trans->dma_buffer, packet, length);
+#endif
+ p_trans->p_urb->transfer_buffer_length = length;
+
+ retval = btusb_submit(p_dev, &p_dev->acl_tx_submitted, p_trans, GFP_ATOMIC);
+ if (unlikely(retval))
+ {
+ goto error;
+ }
+ return retval;
+
+error:
+ BTUSB_ERR("failed : %d\n", retval);
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+ return retval;
+#if 0
+ return btusb_submit_bulk(p_dev, packet, length, p_dev->p_acl_out, &p_dev->acl_tx_submitted);
+#endif
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_diag
+ **
+ ** Description Diag write submission to the controller
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success, negative value if error
+ **
+ *******************************************************************************/
+int btusb_submit_diag(tBTUSB_CB *p_dev, char *packet, unsigned long length)
+{
+ int retval;
+ tBTUSB_TRANSACTION *p_trans;
+
+ BTUSB_DBG("%p[%lu]\n", packet, length);
+
+ btusb_dump_data(packet, length, "OUTGOING DIAG");
+ if (unlikely(!p_dev->p_diag_out))
+ {
+ return -ENODEV;
+ }
+
+ p_trans = btusb_alloc_trans(p_dev->diag_tx_array, ARRAY_SIZE(p_dev->diag_tx_array));
+ if (unlikely(p_trans == NULL))
+ {
+ return -ENOMEM;
+ }
+
+ if (unlikely(length > BTUSB_HCI_MAX_ACL_SIZE))
+ {
+ retval = -E2BIG;
+ goto error;
+ }
+
+#if 0
+ // if this is called directly from write call
+ if (copy_from_user(p_trans->dma_buffer, user_buffer, length))
+ {
+ retval = -EFAULT;
+ goto error;
+ }
+#else
+ memcpy(p_trans->dma_buffer, packet, length);
+#endif
+ p_trans->p_urb->transfer_buffer_length = length;
+
+ retval = btusb_submit(p_dev, &p_dev->diag_tx_submitted, p_trans, GFP_ATOMIC);
+ if (unlikely(retval))
+ {
+ goto error;
+ }
+ return retval;
+
+error:
+ BTUSB_ERR("failed : %d\n", retval);
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+ return retval;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_cmd_complete
+ **
+ ** Description Command (control pipe) completion routine
+ **
+ ** Parameters
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_cmd_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+
+ BTUSB_DBG("status %d %u length flags %x\n", p_urb->status,
+ p_urb->transfer_buffer_length, p_urb->transfer_flags);
+
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+
+ if (unlikely(p_urb->status))
+ {
+ BTUSB_ERR("failure %d\n", p_urb->status);
+ p_dev->stats.commands_completed_error++;
+ }
+ else
+ {
+ p_dev->stats.commands_completed++;
+ }
+
+ if(autopm)
+ usb_autopm_put_interface(p_dev->p_main_intf);
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_cmd
+ **
+ ** Description
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success, negative value if error
+ **
+ *******************************************************************************/
+int btusb_submit_cmd(tBTUSB_CB *p_dev, char *packet, unsigned long length)
+{
+ int retval;
+ tBTUSB_TRANSACTION *p_trans;
+ struct usb_ctrlrequest *p_dr = NULL;
+
+ BTUSB_DBG("%p[%lu]\n", packet, length);
+
+ btusb_dump_data(packet, length, "OUTGOING CMD");
+
+ p_trans = btusb_alloc_trans(p_dev->cmd_array, ARRAY_SIZE(p_dev->cmd_array));
+ if (unlikely(p_trans == NULL))
+ {
+ return -ENOMEM;
+ }
+
+ if (unlikely(length > BTUSB_HCI_MAX_CMD_SIZE))
+ {
+ retval = -E2BIG;
+ goto error;
+ }
+
+#if 0
+ // if this is called directly from write call
+ if (copy_from_user(p_trans->dma_buffer, packet, length))
+ {
+ retval = -EFAULT;
+ goto error;
+ }
+#else
+ memcpy(p_trans->dma_buffer, packet, length);
+#endif
+ p_dr = (void *)p_trans->p_urb->setup_packet;
+ p_dr->wLength = __cpu_to_le16(length);
+ p_trans->p_urb->transfer_buffer_length = length;
+
+ retval = btusb_submit(p_dev, &p_dev->cmd_submitted, p_trans, GFP_ATOMIC);
+ if (unlikely(retval))
+ {
+ p_dev->stats.commands_submitted_error++;
+ goto error;
+ }
+ return retval;
+
+error:
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+ return retval;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_voicetx_complete
+ **
+ ** Description Voice write (iso pipe) completion routine.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_voicetx_complete(struct urb *p_urb)
+{
+ tBTUSB_ISO_ELEMENT *pIsoXfer = p_urb->context;
+ tBTUSB_CB *p_dev = (void *) pIsoXfer->dev;
+
+ btusb_voice_stats(&(p_dev->stats.voice_max_tx_done_delta_time), &(p_dev->stats.voice_min_tx_done_delta_time),
+ &(p_dev->stats.voice_tx_done_delta_time), &(p_dev->stats.voice_last_tx_done_ts));
+
+ // keep track on the number of Tx buffer pending
+ p_dev->stats.voice_tx_cnt--;
+
+ if (unlikely(!p_dev->p_main_intf))
+ goto exit;
+
+ pIsoXfer->used = 0;
+
+ if (unlikely(p_urb->status))
+ {
+ BTUSB_ERR("btusb_voicetx_complete failure %d\n", p_urb->status);
+ p_dev->stats.voicetx_completed_error++;
+ }
+ else
+ {
+ p_dev->stats.voicetx_completed++;
+ }
+
+exit:
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_fill_iso_pkts
+ **
+ ** Description Useful voice utility.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_fill_iso_pkts(struct urb *p_urb, int len, int pkt_size)
+{
+ int off = 0, i;
+
+ for (i = 0; len >= pkt_size; i++, off += pkt_size, len -= pkt_size)
+ {
+ p_urb->iso_frame_desc[i].offset = off;
+ p_urb->iso_frame_desc[i].length = pkt_size;
+ }
+
+ // remainder?
+ if (len)
+ {
+ p_urb->iso_frame_desc[i].offset = off;
+ p_urb->iso_frame_desc[i].length = len;
+ i++;
+ }
+
+ p_urb->number_of_packets = i;
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_fill_iso_rx_pkts
+ **
+ ** Description Useful voice utility.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_fill_iso_rx_pkts(struct urb *p_urb, int len, int pkt_size)
+{
+ int off = 0, i;
+
+ for (i = 0; len >= pkt_size; i++, off += ALIGN(pkt_size, 4), len -= ALIGN(pkt_size, 4))
+ {
+ p_urb->iso_frame_desc[i].offset = off;
+ p_urb->iso_frame_desc[i].length = pkt_size;
+ BTUSB_DBG("off=%d pkt_size=%d\n", off, pkt_size);
+ }
+ p_urb->number_of_packets = i;
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_voice_rx
+ **
+ ** Description Resubmit an already filled URB request
+ **
+ ** Parameters
+ **
+ ** Returns
+ **
+ *******************************************************************************/
+void btusb_submit_voice_rx(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, int mem_flags)
+{
+ if (unlikely(btusb_submit(p_dev, &p_dev->voice_rx_submitted, p_trans, mem_flags)))
+ {
+ p_dev->stats.voicerx_submitted_error++;
+ }
+ else
+ {
+ p_dev->stats.voicerx_submitted++;
+ }
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_update_voice_rx
+ **
+ ** Description Finish filling the voice URB and submit them. At this point
+ ** the URBs should NOT be submitted.
+ **
+ ** Parameters
+ **
+ ** Returns
+ **
+ *******************************************************************************/
+static void btusb_update_voice_rx(tBTUSB_CB *p_dev)
+{
+ unsigned int idx;
+ tBTUSB_TRANSACTION *p_trans;
+ struct urb *p_urb;
+ int packet_size;
+
+ BTUSB_DBG("enter\n");
+
+ if (!p_dev->p_main_intf || !p_dev->p_voice_intf || !p_dev->p_voice_in)
+ {
+ BTUSB_ERR("failing (p_dev removed or no voice intf)\n");
+ return;
+ }
+
+ packet_size = le16_to_cpu(p_dev->p_voice_in->desc.wMaxPacketSize);
+ if (!packet_size)
+ {
+ BTUSB_ERR("failing, 0 packet size)\n");
+ return;
+ }
+ BTUSB_DBG("packet_size=%d\n", packet_size);
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->voice_rx_array)
+ {
+ p_urb = p_trans->p_urb;
+ p_urb->pipe = usb_rcvisocpipe(p_dev->p_udev, p_dev->p_voice_in->desc.bEndpointAddress);
+ BTUSB_DBG("ep=%d\n", p_dev->p_voice_in->desc.bEndpointAddress);
+ p_urb->interval = p_dev->p_voice_in->desc.bInterval;
+ BTUSB_DBG("interval=%d\n", p_urb->interval);
+ p_urb->transfer_buffer_length = ALIGN(packet_size, 4) * BTUSB_VOICE_FRAMES_PER_URB;
+ BTUSB_DBG("transfer_buffer_length=%d\n", p_urb->transfer_buffer_length);
+ if (p_urb->transfer_buffer_length > BTUSB_VOICE_BUFFER_MAXSIZE)
+ {
+ BTUSB_ERR("Required buffer size larger than allocated size\n");
+ p_urb->transfer_buffer_length = BTUSB_VOICE_BUFFER_MAXSIZE;
+ }
+ btusb_fill_iso_rx_pkts(p_urb, p_urb->transfer_buffer_length, packet_size);
+
+ btusb_submit_voice_rx(p_dev, p_trans, GFP_KERNEL);
+ }
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_voice_tx
+ **
+ ** Description Voice write submission
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_submit_voice_tx(tBTUSB_CB *p_dev, UINT8 *p_data, int len)
+{
+ int to_send = 0;
+
+ btusb_voice_stats(&(p_dev->stats.voice_max_rx_feeding_interval), &(p_dev->stats.voice_min_rx_feeding_interval),
+ &(p_dev->stats.voice_rx_feeding_interval), &(p_dev->stats.voice_last_rx_feeding_ts));
+
+ while (len > 0)
+ {
+ if (len >= BTUSB_VOICE_BURST_SIZE)
+ {
+ to_send = BTUSB_VOICE_BURST_SIZE;
+ }
+ else
+ {
+ BTUSB_DBG("Sending partial sco data len: %d\n", len);
+ }
+ p_data[2] = to_send;
+ len -= to_send;
+ btusb_submit_write_voice(p_dev, p_data, to_send + 3);
+
+ if (len)
+ {
+ // copy the header for the next chunk
+ memcpy(p_data + BTUSB_VOICE_BURST_SIZE, p_data , 3);
+ p_data += BTUSB_VOICE_BURST_SIZE;
+ }
+ }
+
+ // we should always have at least 30 ms of audio ready to send
+ // if not fill up with silence
+ if (p_dev->stats.voice_tx_cnt<10)
+ {
+ BTUSB_DBG("less than 10 buffer in the Tx Q %lu insert silence \n", p_dev->stats.voice_tx_cnt);
+ while(p_dev->stats.voice_tx_cnt < 30)
+ {
+ memset(p_data + 3, 0, BTUSB_VOICE_BURST_SIZE );
+ btusb_submit_write_voice(p_dev, p_data, BTUSB_VOICE_BURST_SIZE + 3);
+ }
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_write_voice
+ **
+ ** Description Voice write submission, length should be
+ ** smaller than or equal to VOICE_SAMPLE_SIZE
+ **
+ ** Parameters
+ **
+ ** Returns A zero value upon success.
+ **
+ *******************************************************************************/
+int btusb_submit_write_voice(tBTUSB_CB *p_dev, void *p_packet, unsigned long length)
+{
+ tBTUSB_ISO_ELEMENT *pIsoXfer;
+ struct urb *p_urb;
+ int status, pipe;
+ int packet_size, cur_frame_number;
+
+ if (!p_dev->p_main_intf || !p_dev->p_voice_intf || !p_dev->p_voice_out)
+ {
+ BTUSB_DBG(" failing (p_dev removed or no voice intf)\n");
+ return -1;
+ }
+
+ packet_size = le16_to_cpu(p_dev->p_voice_out->desc.wMaxPacketSize);
+ if ((length > BTUSB_MAXIMUM_TX_VOICE_SIZE) || !packet_size)
+ {
+ BTUSB_ERR("failing (%lu bytes - too many for %d packet size)\n", length, packet_size);
+ p_dev->stats.voicetx_disc_toolong++;
+ return -11;
+ }
+
+ // advance to the next voice tx IRP
+ if (++p_dev->voicetxIrpIndex == BTUSB_NUM_OF_VOICE_TX_BUFFERS)
+ p_dev->voicetxIrpIndex = 0;
+
+ // keep track on the number of tx buffer for stats debug and optimization
+ p_dev->stats.voice_tx_cnt++;
+ if (p_dev->stats.voice_tx_cnt>p_dev->stats.voice_max_tx_cnt)
+ {
+ p_dev->stats.voice_max_tx_cnt = p_dev->stats.voice_tx_cnt;
+ }
+
+ pIsoXfer = &p_dev->p_voicetxIrpList[p_dev->voicetxIrpIndex];
+
+ // buffer available?
+ if (pIsoXfer->used)
+ {
+ BTUSB_ERR("failed, no buf!\n");
+ p_dev->stats.voicetx_disc_nobuf++;
+ return -111;
+ }
+
+ p_urb = &pIsoXfer->urb;
+ pIsoXfer->index = p_dev->voicetxIrpIndex;
+ pIsoXfer->dev = p_dev;
+ memcpy(pIsoXfer->packet, p_packet, length);
+ pipe = usb_sndisocpipe(p_dev->p_udev, p_dev->p_voice_out->desc.bEndpointAddress);
+ p_urb->complete = btusb_voicetx_complete;
+ p_urb->context = pIsoXfer;
+ p_urb->dev = p_dev->p_udev;
+ p_urb->pipe = pipe;
+ p_urb->interval = p_dev->p_voice_out->desc.bInterval;
+ p_urb->transfer_buffer = pIsoXfer->packet;
+ p_urb->transfer_buffer_length = length;
+ btusb_fill_iso_pkts(p_urb, length, packet_size);
+ // p_urb->transfer_flags = 0;
+ p_urb->transfer_flags = URB_ISO_ASAP;
+ cur_frame_number = usb_get_current_frame_number(p_dev->p_udev);
+
+ BTUSB_INFO("len %lu idx %lu frm %u\n", length, pIsoXfer->index, cur_frame_number);
+ pIsoXfer->used = 1;
+ status = usb_submit_urb(p_urb, GFP_ATOMIC);
+ if (status)
+ {
+ BTUSB_ERR("usb_submit_urb failed %d\n", status);
+ p_dev->stats.voicetx_submitted_error++;
+ pIsoXfer->used = 0;
+ }
+ else
+ {
+ p_dev->stats.voicetx_submitted++;
+ BTUSB_DBG("success\n");
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_set_voice
+ **
+ ** Description Change voice interface setting processor
+ ** NOTE: Must be called at low execution level
+ **
+ ** Parameters p_dev: pointer to the device control block
+ ** setting_number: new voice interface setting number
+ ** submit_urb: true if the URBs must be submitted
+ **
+ ** Returns 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_set_voice(tBTUSB_CB *p_dev, unsigned char setting_number,
+ bool submit_urb)
+{
+ int idx;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+
+ BTUSB_DBG("setting_number=%d submit_urb=%u\n", setting_number, submit_urb);
+
+ // cancel all voice requests before switching buffers
+ p_dev->p_voice_in = NULL;
+ p_dev->p_voice_out = NULL;
+ btusb_cancel_voice(p_dev);
+
+ // configure the voice interface to the proper setting
+ if (usb_set_interface(p_dev->p_udev, 1, setting_number))
+ {
+ BTUSB_ERR("failed to set iso intf to %u\n", setting_number);
+ return -EFAULT;
+ }
+
+ // find the endpoints
+ p_host_intf = p_dev->p_voice_intf->cur_altsetting;
+
+ for (idx = 0; idx < p_host_intf->desc.bNumEndpoints; idx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[idx].desc;
+ if (usb_endpoint_type(p_ep_desc) == USB_ENDPOINT_XFER_ISOC)
+ {
+ if (usb_endpoint_dir_in(p_ep_desc))
+ {
+ p_dev->p_voice_in = &p_host_intf->endpoint[idx];
+ }
+ else
+ {
+ p_dev->p_voice_out = &p_host_intf->endpoint[idx];
+ }
+ }
+ }
+
+ if (!p_dev->p_voice_in || !p_dev->p_voice_out)
+ {
+ BTUSB_ERR("no iso pipes found!\n");
+ return -EFAULT;
+ }
+
+ if (submit_urb)
+ {
+ btusb_update_voice_rx(p_dev);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_add_voice_channel
+ **
+ ** Description Add a voice channel in the list of current channels
+ **
+ ** Parameters p_dev: pointer to the device control structure
+ ** sco_handle: handle of the synchronous connection carrying voice
+ ** burst: size of the voice bursts
+ **
+ ** Returns Return 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_add_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle, unsigned char burst)
+{
+ int idx;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ if (!p_dev->p_voice_intf)
+ {
+ BTUSB_ERR("No voice interface detected\n");
+ return -EOPNOTSUPP;
+ }
+
+ // kludge to support the backward compatibility with older BTKRNLs
+ // not supplying the packet size...
+ if (burst == 0)
+ {
+ BTUSB_INFO("fixing legacy req to 48\n");
+ burst = BTUSB_VOICE_BURST_SIZE;
+ }
+
+ // look for an available voice channel entry
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (!p_chan->used)
+ {
+ p_chan->info.sco_handle = sco_handle;
+ p_chan->info.burst = burst;
+ p_chan->used = 1;
+ goto found;
+ }
+ }
+ BTUSB_ERR("Could not find empty slot in internal tables\n");
+ return -EMLINK;
+
+found:
+ if (btusb_update_voice_channels(p_dev))
+ {
+ BTUSB_ERR("Failed adding voice channel\n");
+ // failure, remove the channel just added
+ btusb_remove_voice_channel(p_dev, sco_handle);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_remove_voice_channel
+ **
+ ** Description Remove a voice channel from the list of current channels
+ **
+ ** Parameters p_dev: pointer to the device control structure
+ ** sco_handle: handle of the synchronous connection carrying voice
+ **
+ ** Returns Return 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_remove_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle)
+{
+ int idx;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ if (!p_dev->p_voice_intf)
+ {
+ BTUSB_ERR("No voice interface detected\n");
+ return -EOPNOTSUPP;
+ }
+
+ // find the channel to be removed
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->used && (p_chan->info.sco_handle == sco_handle))
+ {
+ p_chan->used = 0;
+ goto found;
+ }
+ }
+ BTUSB_ERR("Could not find SCO handle in internal tables\n");
+ return -ENOENT;
+
+found:
+ return btusb_update_voice_channels(p_dev);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_update_voice_channels
+ **
+ ** Description Voice channels just updated, reconfigure
+ **
+ ** Parameters p_dev: pointer to the device control structure
+ **
+ ** Returns Return 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_update_voice_channels(tBTUSB_CB *p_dev)
+{
+ int idx, jdx;
+ unsigned char min_burst, max_burst, num_voice_chan, voice_setting;
+ unsigned short desired_packet_size, packet_size;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+
+ BTUSB_DBG("\n");
+
+ // get the number of voice channels and the size information
+ num_voice_chan = 0;
+ min_burst = 0xFF;
+ max_burst = 0;
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->used)
+ {
+ num_voice_chan++;
+ min_burst = min(min_burst, p_chan->info.burst);
+ max_burst = max(max_burst, p_chan->info.burst);
+ }
+ }
+
+ BTUSB_DBG("num_voice_chan=%d\n", num_voice_chan);
+ // now calculate a desired_packet_size
+ switch (num_voice_chan)
+ {
+ case 0:
+ desired_packet_size = 0;
+ break;
+
+ case 1:
+ // single channel: we just need a third of the length (rounded up so we add 2 before dividing)
+ desired_packet_size = ((max_burst + BTUSB_VOICE_HEADER_SIZE) + 2) / 3;
+ break;
+
+ case 2:
+ // two channels: we need the smaller one to fit in completely
+ // and the larger one to fit in into two...
+ packet_size = (max_burst + BTUSB_VOICE_HEADER_SIZE + 1) / 2;
+
+ desired_packet_size = min_burst + BTUSB_VOICE_HEADER_SIZE;
+ if (packet_size > desired_packet_size)
+ desired_packet_size = packet_size;
+ break;
+
+ case 3:
+ // three channels - we need all of them to fit into a single packet
+ desired_packet_size = max_burst + BTUSB_VOICE_HEADER_SIZE;
+ break;
+
+ default:
+ // this can not happen
+ BTUSB_ERR("invalid # (%d) of channels, failing...\n", num_voice_chan);
+ return 0;
+ }
+
+ BTUSB_DBG("desired packet size is %u\n", desired_packet_size);
+
+ // now convert the desired_packet_size into the interface setting number
+ packet_size = BTUSB_USHRT_MAX;
+ voice_setting = 0;
+ for (idx = 0; idx < p_dev->p_voice_intf->num_altsetting; idx++)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[idx];
+ for (jdx = 0; jdx < p_host_intf->desc.bNumEndpoints; jdx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[jdx].desc;
+ if ((usb_endpoint_type(p_ep_desc) == USB_ENDPOINT_XFER_ISOC) &&
+ usb_endpoint_dir_in(p_ep_desc))
+ {
+ // if the MaxPacketSize is large enough and if it is smaller
+ // than the current setting
+ if ((desired_packet_size <= le16_to_cpu(p_ep_desc->wMaxPacketSize)) &&
+ (le16_to_cpu(p_ep_desc->wMaxPacketSize) < packet_size))
+ {
+ packet_size = le16_to_cpu(p_ep_desc->wMaxPacketSize);
+ voice_setting = p_host_intf->desc.bAlternateSetting;
+ }
+ }
+ }
+ }
+ if (packet_size == BTUSB_USHRT_MAX)
+ {
+ BTUSB_ERR("no appropriate ISO interface setting found, failing...\n");
+ return -ERANGE;
+ }
+
+ BTUSB_DBG("desired_packet_size=%d voice_setting=%d\n", desired_packet_size, voice_setting);
+ // store the desired packet size
+ p_dev->desired_packet_size = desired_packet_size;
+
+ // set the voice setting and only submit the URBs if there is a channel
+ return btusb_set_voice(p_dev, voice_setting, num_voice_chan != 0);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_debug_show
+ **
+ ** Description Function called when reading the /proc file created by our driver
+ **
+ *******************************************************************************/
+#define BTUSB_STATS(__n) \
+ seq_printf(s, " - " #__n " = %lu\n", p_dev->stats.__n)
+
+static int btusb_debug_show(struct seq_file *s, void *unused)
+{
+ tBTUSB_CB *p_dev = s->private;
+ struct usb_device *udev = p_dev->p_udev;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+ int idx, jdx;
+
+ seq_printf(s, "USB device :\n");
+ seq_printf(s, " - Match info:\n");
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_VENDOR)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_VENDOR (0x%02X)\n", p_dev->p_id->idVendor);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_PRODUCT 0x%02X)\n", p_dev->p_id->idProduct);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_LO (%u)\n", p_dev->p_id->bcdDevice_lo);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_HI (%u)\n", p_dev->p_id->bcdDevice_hi);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_CLASS (0x%02X)\n", p_dev->p_id->bDeviceClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_SUBCLASS (0x%02X)\n", p_dev->p_id->bDeviceSubClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_PROTOCOL (0x%02X)\n", p_dev->p_id->bDeviceProtocol);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_CLASS (0x%02X)\n", p_dev->p_id->bInterfaceClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_SUBCLASS (0x%02X)\n", p_dev->p_id->bInterfaceSubClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_PROTOCOL (0x%02X)\n", p_dev->p_id->bInterfaceProtocol);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_NUMBER (%u)\n", p_dev->p_id->bInterfaceNumber);
+#endif
+
+ seq_printf(s, " - Address = %d\n", udev->devnum);
+ seq_printf(s, " - VendorId = %04x\n", le16_to_cpu(udev->descriptor.idVendor));
+ seq_printf(s, " - ProductId = %04x\n", le16_to_cpu(udev->descriptor.idProduct));
+ seq_printf(s, " - Manufacturer String = %s\n", udev->manufacturer);
+ seq_printf(s, " - Product String = %s\n", udev->product);
+ seq_printf(s, " - USB bus number = %d\n", udev->bus->busnum);
+ seq_printf(s, " - USB devpath = %s\n", udev->devpath);
+ seq_printf(s, " - USB devnum = %d\n", udev->devnum);
+ seq_printf(s, " - USB ttport = %d\n", udev->ttport);
+ seq_printf(s, " - Interfaces :\n");
+ seq_printf(s, " * MAIN : ");
+ if (p_dev->p_main_intf)
+ {
+ seq_printf(s, "intf = %d (nb alt settings = %d, ",
+ p_dev->p_main_intf->cur_altsetting->desc.bInterfaceNumber,
+ p_dev->p_main_intf->num_altsetting);
+ seq_printf(s, "cur alt setting = %d)\n", p_dev->p_main_intf->cur_altsetting->desc.bAlternateSetting);
+ seq_printf(s, " * HCI EVENT : ");
+ if (p_dev->p_event_in)
+ {
+ seq_printf(s, "ep = 0x%02x\n", p_dev->p_event_in->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "ERROR (endpoint not found)\n");
+ }
+ seq_printf(s, " * ACL RX : ");
+ if (p_dev->p_acl_in)
+ {
+ seq_printf(s, "ep = 0x%02x\n", p_dev->p_event_in->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "ERROR (endpoint not found)\n");
+ }
+ seq_printf(s, " * ACL TX : ");
+ if (p_dev->p_acl_out)
+ {
+ seq_printf(s, "ep = 0x%02x\n", p_dev->p_acl_out->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "ERROR (endpoint not found)\n");
+ }
+ }
+ else
+ {
+
+ }
+ seq_printf(s, " * VOICE :");
+ if (p_dev->p_voice_intf)
+ {
+ seq_printf(s, " intf = %d (nb alt setting = %d, ", p_dev->p_voice_intf->cur_altsetting->desc.bInterfaceNumber, p_dev->p_voice_intf->num_altsetting);
+ seq_printf(s, "cur alt setting = %d)\n", p_dev->p_voice_intf->cur_altsetting->desc.bAlternateSetting);
+ for (idx = 0; idx < p_dev->p_voice_intf->num_altsetting; idx++)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[idx];
+ seq_printf(s, " * alt setting %d (idx %d) : %d enpoints\n",
+ p_host_intf->desc.bAlternateSetting, idx, p_host_intf->desc.bNumEndpoints);
+ for (jdx = 0; jdx < p_host_intf->desc.bNumEndpoints; jdx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[jdx].desc;
+ seq_printf(s, " * ep = 0x%02x : ", p_ep_desc->bEndpointAddress);
+ if (usb_endpoint_type(p_ep_desc) == USB_ENDPOINT_XFER_ISOC)
+ {
+ seq_printf(s, "Isoch ");
+ if (usb_endpoint_dir_out(p_ep_desc))
+ {
+ seq_printf(s, "(OUT) ");
+ }
+ else
+ {
+ seq_printf(s, "(IN) ");
+ }
+ seq_printf(s, "wMaxPacketSize = %d\n", le16_to_cpu(p_ep_desc->wMaxPacketSize));
+ }
+ else
+ {
+ seq_printf(s, "not isochronous endpoint\n");
+ }
+ }
+ }
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+ seq_printf(s, " * DIAG RX : ");
+ if (p_dev->p_diag_in)
+ {
+ seq_printf(s, "intf = %d ep = 0x%02x\n", p_dev->p_diag_intf->cur_altsetting->desc.bInterfaceNumber, p_dev->p_diag_in->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+ seq_printf(s, " * DIAG TX : ");
+ if (p_dev->p_diag_out)
+ {
+ seq_printf(s, "intf = %d ep = 0x%02x\n", p_dev->p_diag_intf->cur_altsetting->desc.bInterfaceNumber, p_dev->p_diag_out->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+ seq_printf(s, " * DFU : ");
+ if (p_dev->p_dfu_intf)
+ {
+ seq_printf(s, "intf = %d\n", p_dev->p_dfu_intf->cur_altsetting->desc.bInterfaceNumber);
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+
+ seq_printf(s, "Memory usage :\n");
+ seq_printf(s, " - p_dev = %p\n", p_dev);
+ seq_printf(s, " - size = %zd\n", sizeof(*p_dev));
+ seq_printf(s, " * CMD = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, cmd_array), sizeof(p_dev->cmd_array));
+ seq_printf(s, " * EVENT = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, event_array), sizeof(p_dev->event_array));
+ seq_printf(s, " * ACL RX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, acl_rx_array), sizeof(p_dev->acl_rx_array));
+ seq_printf(s, " * ACL TX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, acl_tx_array), sizeof(p_dev->acl_tx_array));
+ seq_printf(s, " * DIAG RX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, diag_rx_array), sizeof(p_dev->diag_rx_array));
+ seq_printf(s, " * DIAG TX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, diag_tx_array), sizeof(p_dev->diag_tx_array));
+ seq_printf(s, " * VOICE = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, voice_channels), offsetof(tBTUSB_CB, rx_queue)-offsetof(tBTUSB_CB, voice_channels));
+
+ seq_printf(s, "Status :\n");
+ seq_printf(s, " - issharedusb = %u\n", p_dev->issharedusb);
+ seq_printf(s, " - quirks = %u\n", p_dev->quirks);
+ seq_printf(s, " - opened = %d\n", p_dev->opened);
+ seq_printf(s, "Voice :\n");
+ // calculate number of voice sample per timer expiration
+ // HZ could be 100, 250 or 1000
+ if ((1000 / HZ) <= BTUSB_VOICE_DELAY)
+ {
+ seq_printf(s, " - number of voice samples per timer expiration = 1\n");
+ }
+ else
+ {
+ seq_printf(s, " - number of voice samples per timer expiration = %d\n",
+ (1000 / (HZ * BTUSB_VOICE_DELAY)));
+ }
+ jdx = 0;
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->used)
+ {
+ seq_printf(s, " - channel %d : SCO handle = %d(0x%02x) burst = %d\n", idx,
+ p_chan->info.sco_handle, p_chan->info.sco_handle, p_chan->info.burst);
+ jdx = 1;
+ }
+ }
+ if (jdx)
+ {
+ seq_printf(s, " - desired_packet_size = %d\n", p_dev->desired_packet_size);
+ }
+ else
+ {
+ seq_printf(s, " - No active channels\n");
+ }
+ seq_printf(s, "Statistics :\n");
+ BTUSB_STATS(urb_submit_ok);
+ BTUSB_STATS(urb_submit_err);
+ BTUSB_STATS(acl_rx_submit_ok);
+ BTUSB_STATS(acl_rx_submit_err);
+ BTUSB_STATS(acl_rx_completed);
+ BTUSB_STATS(acl_rx_resubmit);
+ BTUSB_STATS(acl_rx_bytes);
+ BTUSB_STATS(event_submit_ok);
+ BTUSB_STATS(event_submit_err);
+ BTUSB_STATS(event_completed);
+ BTUSB_STATS(event_resubmit);
+ BTUSB_STATS(event_bytes);
+ BTUSB_STATS(diag_rx_submit_ok);
+ BTUSB_STATS(diag_rx_submit_err);
+ BTUSB_STATS(diag_rx_completed);
+ BTUSB_STATS(diag_rx_resubmit);
+ BTUSB_STATS(diag_rx_bytes);
+ BTUSB_STATS(diag_rx_bytes);
+ BTUSB_STATS(writes_submitted);
+ BTUSB_STATS(writes_submitted_error);
+ BTUSB_STATS(writes_completed);
+ BTUSB_STATS(writes_completed_error);
+ BTUSB_STATS(commands_submitted);
+ BTUSB_STATS(commands_submitted_error);
+ BTUSB_STATS(commands_completed);
+ BTUSB_STATS(commands_completed_error);
+ BTUSB_STATS(voicerx_submitted);
+ BTUSB_STATS(voicerx_submitted_error);
+ BTUSB_STATS(voicerx_completed);
+ BTUSB_STATS(voicerx_completed_error);
+ BTUSB_STATS(voicerx_bad_packets);
+ BTUSB_STATS(voicerx_disc_nohdr);
+ BTUSB_STATS(voicerx_split_hdr);
+ BTUSB_STATS(voicerx_raw_bytes);
+ BTUSB_STATS(voicerx_skipped_bytes);
+ BTUSB_STATS(voicetx_submitted);
+ BTUSB_STATS(voicetx_submitted_error);
+ BTUSB_STATS(voicetx_completed);
+ BTUSB_STATS(voicetx_completed_error);
+ BTUSB_STATS(voicetx_disc_nobuf);
+ BTUSB_STATS(voicetx_disc_toolong);
+ BTUSB_STATS(voice_tx_cnt);
+ BTUSB_STATS(voice_max_tx_cnt);
+
+ {
+ struct btusb_scosniff *p, *n;
+ seq_printf(s, "SCO sniffing:\n");
+ seq_printf(s, " - list: %p\n", &p_dev->scosniff_list);
+ seq_printf(s, " - list.next: %p\n", p_dev->scosniff_list.next);
+ seq_printf(s, " - list.prev: %p\n", p_dev->scosniff_list.prev);
+ seq_printf(s, " - whole list:\n");
+ list_for_each_entry_safe(p, n, &p_dev->scosniff_list, lh)
+ {
+ seq_printf(s, " > %p\n", p);
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_debug_write
+ **
+ ** Description Write handler of the debug /proc interface
+ **
+ *******************************************************************************/
+ssize_t btusb_debug_write(struct file *file, const char *buf,
+ size_t count, loff_t *pos)
+{
+ struct seq_file *s = file->private_data;
+ tBTUSB_CB *p_dev = s->private;
+ unsigned char cmd;
+
+ // copy the first byte from the data written
+ if (copy_from_user(&cmd, buf, 1))
+ {
+ return -EFAULT;
+ }
+
+ // unconditional print on purpose
+ BTUSB_INFO("'%c'\n", cmd);
+
+ switch (cmd)
+ {
+ case '0':
+ // reset the stats
+ memset(&p_dev->stats, 0, sizeof(p_dev->stats));
+ break;
+ case '1':
+ btusb_add_voice_channel(p_dev, 6, BTUSB_VOICE_BURST_SIZE);
+ break;
+
+ case '2':
+ btusb_remove_voice_channel(p_dev, 6);
+ break;
+
+ case '3':
+ if (p_dev->scosniff_active)
+ {
+ struct btusb_scosniff *bs;
+ bs = kmalloc(sizeof(*bs), GFP_ATOMIC);
+ if (bs)
+ {
+
+ BTUSB_INFO("SCOSNIFF: adding %p\n", bs);
+ bs->n = 0;
+ list_add_tail(&bs->lh, &p_dev->scosniff_list);
+ complete(&p_dev->scosniff_completion);
+ }
+ }
+ break;
+
+#ifdef BTUSB_LITE
+ case '4':
+ BTUSB_INFO("Mute PCM0\n");
+ pcm0_mute = 1;
+ break;
+
+ case '5':
+ BTUSB_INFO("Unmute PCM0\n");
+ pcm0_mute = 0;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ return count;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_debug_open
+ **
+ ** Description Open handler of the debug /proc interface
+ **
+ *******************************************************************************/
+int btusb_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, btusb_debug_show, BTUSB_PDE_DATA(inode));
+}
+
+static void * btusb_scosniff_start(struct seq_file *s, loff_t *pos)
+{
+ tBTUSB_CB *p_dev = s->private;
+ struct btusb_scosniff *bs;
+ int rv;
+
+ BTUSB_INFO("waiting %p\n", p_dev);
+ rv = wait_for_completion_interruptible(&p_dev->scosniff_completion);
+ if (rv < 0)
+ return NULL;
+
+ BTUSB_INFO("triggered\n");
+
+ if (!list_empty(&p_dev->scosniff_list))
+ {
+ bs = list_first_entry(&p_dev->scosniff_list, struct btusb_scosniff, lh);
+
+ // remove the element from the list
+ list_del(&bs->lh);
+ BTUSB_INFO("receiving %p\n", bs);
+
+ return bs;
+ }
+ return NULL;
+}
+
+static void btusb_scosniff_stop(struct seq_file *s, void *v)
+{
+ BTUSB_INFO("stop\n");
+}
+
+static void * btusb_scosniff_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct btusb_scosniff *bs = v;
+ BTUSB_INFO("next\n");
+
+ kfree(bs);
+
+ (*pos)++;
+
+ /* if you do not want to buffer the data, just return NULL, otherwise, call start
+ * again in order to use as much of the allocated PAGE in seq_read
+ *
+ * optional:
+ * return btusb_scosniff_start(s, pos);
+ */
+ return NULL;
+}
+
+ static int btusb_scosniff_show(struct seq_file *s, void *v)
+{
+ struct btusb_scosniff *bs = v;
+ unsigned int i, j;
+ unsigned char *p_buf, *p_c;
+ unsigned char c;
+ struct usb_iso_packet_descriptor *p_uipd;
+ const char hexdigit[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+ seq_printf(s, "%u %u %d \n", bs->n, bs->l, bs->s);
+ p_buf = (unsigned char *)&bs->d[bs->n];
+ for (i = 0; i < bs->n; i++)
+ {
+ p_uipd = &bs->d[i];
+ seq_printf(s, " %d %u %u %u\n", p_uipd->status, p_uipd->actual_length, p_uipd->length, p_uipd->offset);
+ for (j = 0, p_c = &p_buf[p_uipd->offset]; j < p_uipd->actual_length; j++, p_c++)
+ {
+ c = *p_c;
+ seq_putc(s, hexdigit[c >> 4]);
+ seq_putc(s, hexdigit[c & 0xF]);
+ seq_putc(s, ' ');
+ }
+ seq_putc(s, '\n');
+ }
+
+ return 0;
+}
+
+static const struct seq_operations btusb_scosniff_seq_ops = {
+ .start = btusb_scosniff_start,
+ .next = btusb_scosniff_next,
+ .stop = btusb_scosniff_stop,
+ .show = btusb_scosniff_show,
+};
+
+int btusb_scosniff_open(struct inode *inode, struct file *file)
+{
+ int rv;
+ tBTUSB_CB *p_dev = BTUSB_PDE_DATA(inode);
+
+ rv = seq_open(file, &btusb_scosniff_seq_ops);
+ if (!rv)
+ {
+ p_dev->scosniff_active = true;
+ ((struct seq_file *)file->private_data)->private = p_dev;
+ }
+ return rv;
+}
+
+int btusb_scosniff_release(struct inode *inode, struct file *file)
+{
+ struct btusb_scosniff *p, *n;
+ tBTUSB_CB *p_dev = BTUSB_PDE_DATA(inode);
+
+ p_dev->scosniff_active = false;
+
+ list_for_each_entry_safe(p, n, &p_dev->scosniff_list, lh)
+ {
+ list_del(&p->lh);
+ kfree(p);
+ }
+
+ return seq_release(inode, file);
+}
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb_isoc.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb_isoc.c.svn-base
new file mode 100755
index 0000000..bc3acff
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb_isoc.c.svn-base
@@ -0,0 +1,311 @@
+/*
+ *
+ * btusb_isoc.c
+ *
+ *
+ *
+ * Copyright (C) 2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+// for kmalloc
+#include <linux/slab.h>
+#include "btusb.h"
+#include "hcidefs.h"
+
+/*******************************************************************************
+ **
+ ** Function btusb_isoc_reset_msg
+ **
+ ** Description Reset the currently receiving voice message
+ **
+ ** Parameters p_dev: device instance control block
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_isoc_reset_msg(tBTUSB_CB *p_dev)
+{
+ p_dev->pending_bytes = 0;
+ if (p_dev->pp_pending_msg && *p_dev->pp_pending_msg)
+ {
+ GKI_freebuf(*p_dev->pp_pending_msg);
+ }
+ p_dev->pp_pending_msg = NULL;
+ p_dev->pending_hdr_size = 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_isoc_check_hdr
+ **
+ ** Description Check the packet header
+ **
+ ** Parameters p_dev: device instance control block
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static bool btusb_isoc_check_hdr(tBTUSB_CB *p_dev)
+{
+ unsigned char *p_data = p_dev->pending_hdr;
+ int idx;
+ unsigned short sco_handle;
+ unsigned char size;
+ BT_HDR *p_hdr;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ STREAM_TO_UINT16(sco_handle, p_data);
+ sco_handle &= 0x0fff;
+ STREAM_TO_UINT8(size, p_data);
+
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if ((p_chan->used) &&
+ (sco_handle == p_chan->info.sco_handle) &&
+ (size <= (2 * p_chan->info.burst)))
+ {
+ // check if there is already a message being consolidated
+ if (unlikely(p_chan->p_msg == NULL))
+ {
+ p_hdr = (BT_HDR *) GKI_getpoolbuf(HCI_SCO_POOL_ID);
+ if (unlikely(p_hdr == NULL))
+ {
+ return false;
+ }
+ p_hdr->event = BT_EVT_TO_BTU_HCI_SCO;
+ p_hdr->len = 1 + BTUSB_VOICE_HEADER_SIZE; // sizeof(data_type) + SCO header
+ p_hdr->offset = 0;
+ p_hdr->layer_specific = 0;
+
+ p_data = (void *) (p_hdr + 1);
+
+ // add data type
+ UINT8_TO_STREAM(p_data, HCIT_TYPE_SCO_DATA);
+ UINT16_TO_STREAM(p_data, sco_handle);
+
+ p_chan->p_msg = p_hdr;
+ }
+ p_dev->pending_bytes = size;
+ p_dev->pp_pending_msg = &p_chan->p_msg;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_isoc_check_msg
+ **
+ ** Description Check the currently receiving message
+ **
+ ** Parameters p_dev: device instance control block
+ ** pp_hdr: pointer to the receiving message
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_isoc_check_msg(tBTUSB_CB *p_dev, BT_HDR **pp_hdr)
+{
+ BT_HDR *p_hdr = *pp_hdr;
+ unsigned char *p_data;
+
+ // if enough data was received
+ if (unlikely(p_hdr->len >= (1 + BTUSB_VOICE_HEADER_SIZE + SCO_RX_MAX_LEN)))
+ {
+ p_data = (void *)(p_hdr + 1);
+ p_data[BTUSB_VOICE_HEADER_SIZE] = p_hdr->len - BTUSB_VOICE_HEADER_SIZE - 1;
+ GKI_enqueue(&p_dev->rx_queue, p_hdr);
+
+ // notify RX event(in case of select/poll
+ wake_up_interruptible(&p_dev->rx_wait_q);
+
+ *pp_hdr = NULL;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_voicerx_complete
+ **
+ ** Description Voice read (iso pipe) completion routine.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_voicerx_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ BT_HDR **pp_hdr, *p_hdr;
+ unsigned int length, packet_length;
+ unsigned char *p_packet, *p_frame, *p_data;
+ struct usb_iso_packet_descriptor *p_uipd, *p_end;
+
+ BTUSB_INFO("enter");
+
+ btusb_voice_stats(&(p_dev->stats.voice_max_rx_rdy_delta_time), &(p_dev->stats.voice_min_rx_rdy_delta_time),
+ &(p_dev->stats.voice_rx_rdy_delta_time), &(p_dev->stats.voice_last_rx_rdy_ts));
+
+ p_dev->stats.voicerx_completed++;
+
+ if (unlikely(!p_dev->p_main_intf || !p_dev->p_voice_in))
+ {
+ BTUSB_DBG("intf is down\n");
+ return;
+ }
+
+ // entire URB error?
+ if (unlikely(p_urb->status))
+ {
+ BTUSB_ERR("failure %d\n", p_urb->status);
+ p_dev->stats.voicerx_completed_error++;
+ return;
+ }
+
+ if (unlikely(p_dev->scosniff_active))
+ {
+ struct btusb_scosniff *bs;
+
+ bs = kmalloc(sizeof(struct btusb_scosniff) +
+ (p_urb->number_of_packets * sizeof(p_urb->iso_frame_desc[0])) +
+ p_urb->transfer_buffer_length, GFP_ATOMIC);
+ if (bs)
+ {
+ bs->s = p_urb->start_frame;
+ bs->n = p_urb->number_of_packets;
+ bs->l = p_urb->transfer_buffer_length;
+ // copy the descriptors
+ memcpy(bs->d, p_urb->iso_frame_desc, bs->n * sizeof(p_urb->iso_frame_desc[0]));
+ // then copy the content of the buffer
+ memcpy(&bs->d[bs->n], p_urb->transfer_buffer, bs->l);
+ list_add_tail(&bs->lh, &p_dev->scosniff_list);
+ complete(&p_dev->scosniff_completion);
+ }
+ else
+ {
+ BTUSB_ERR("Failed allocating scosniff buffer");
+ }
+ }
+
+ p_frame = p_urb->transfer_buffer;
+ p_end = &p_urb->iso_frame_desc[p_urb->number_of_packets];
+ for (p_uipd = p_urb->iso_frame_desc; p_uipd < p_end; p_uipd++)
+ {
+ if (unlikely(p_uipd->status))
+ {
+ p_dev->stats.voicerx_bad_packets++;
+ // should we do something if there is expected data?
+ continue;
+ }
+
+ p_packet = p_frame + p_uipd->offset;
+ packet_length = p_uipd->actual_length;
+ p_dev->stats.voicerx_raw_bytes += packet_length;
+
+ // waiting for data?
+ if (likely(p_dev->pending_bytes))
+ {
+ fill_data:
+ if (likely(p_dev->pending_bytes >= packet_length))
+ {
+ length = packet_length;
+ }
+ else
+ {
+ length = p_dev->pending_bytes;
+ }
+ pp_hdr = p_dev->pp_pending_msg;
+ p_hdr = *pp_hdr;
+ p_data = (void *)(p_hdr + 1) + p_hdr->len;
+ // add data at the tail of the current message
+ memcpy(p_data, p_packet, length);
+ p_hdr->len += length;
+
+ // decrement the number of bytes remaining
+ p_dev->pending_bytes -= length;
+ if (likely(p_dev->pending_bytes))
+ {
+ // data still needed -> next descriptor
+ continue;
+ }
+ // no more pending bytes, check if it is full
+ btusb_isoc_check_msg(p_dev, pp_hdr);
+ packet_length -= length;
+ if (likely(!packet_length))
+ continue;
+ // more bytes -> increment pointer
+ p_packet += length;
+ }
+
+ // if there is still data in the packet
+ if (likely(packet_length))
+ {
+ // at this point, there is NO SCO packet pending
+ if (likely(packet_length >= (BTUSB_VOICE_HEADER_SIZE - p_dev->pending_hdr_size)))
+ {
+ length = BTUSB_VOICE_HEADER_SIZE - p_dev->pending_hdr_size;
+ }
+ else
+ {
+ length = packet_length;
+ }
+
+ // fill the hdr (in case header is split across descriptors)
+ memcpy(&p_dev->pending_hdr[p_dev->pending_hdr_size], p_packet, length);
+ p_dev->pending_hdr_size += length;
+
+ if (likely(p_dev->pending_hdr_size == BTUSB_VOICE_HEADER_SIZE))
+ {
+ p_dev->pending_hdr_size = 0;
+
+ if (likely(btusb_isoc_check_hdr(p_dev)))
+ {
+ p_packet += length;
+ packet_length -= length;
+ // a correct header was found, get the data
+ goto fill_data;
+ }
+ p_dev->stats.voicerx_disc_nohdr++;
+ p_dev->stats.voicerx_skipped_bytes += packet_length;
+ // this is not a correct header -> next descriptor
+ continue;
+ }
+ else if (likely(p_dev->pending_hdr_size < BTUSB_VOICE_HEADER_SIZE))
+ {
+ p_dev->stats.voicerx_split_hdr++;
+ // header not complete -> next descriptor
+ continue;
+ }
+ else
+ {
+ BTUSB_ERR("ISOC Header larger than possible. This is a major failure.\n");
+ btusb_isoc_reset_msg(p_dev);
+ }
+ }
+ }
+
+ btusb_submit_voice_rx(p_dev, p_trans, GFP_ATOMIC);
+}
+
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb_lite.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite.c.svn-base
new file mode 100755
index 0000000..f6d1374
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite.c.svn-base
@@ -0,0 +1,1794 @@
+/*
+ *
+ * btusb_lite.c
+ *
+ *
+ *
+ * Copyright (C) 2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#include <linux/proc_fs.h>
+#include <linux/poll.h>
+
+#include "btusb.h"
+#include "bd.h"
+
+
+/*
+ * Defines
+ */
+
+#define BTUSB_LITE_IPC_AVDT_SYNC_INFO_RSP_LEN (1 + BTM_SYNC_INFO_NUM_STR * (1+6+2+2+1+2))
+
+/*
+ * Local functions
+ */
+static void btusb_lite_init(struct btusb_cb *p_dev);
+static int btusb_lite_open(struct inode *inode, struct file *file);
+static int btusb_lite_close(struct inode *inode, struct file *file);
+static ssize_t btusb_lite_write(struct file *file, const char *buf, size_t count,
+ loff_t *p_off);
+static ssize_t btusb_lite_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *p_off);
+static unsigned int btusb_lite_poll(struct file *file, struct poll_table_struct *p_pt);
+
+static BT_HDR *btusb_lite_msg_to_app_get(struct btusb_cb *p_dev);
+static void btusb_lite_msg_to_app_free(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static UINT8 *btusb_lite_msg_to_app_get_data_addr(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+static char *btusb_lite_ipc_event_desc(UINT16 event);
+
+static void btusb_lite_ipc_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_hci_cmd_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_hci_acl_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_mgt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_btu_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_btm_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_l2c_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_avdt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+static void btusb_lite_ipc_rsp_send(struct btusb_cb *p_dev, UINT16 event, UINT8 op_code,
+ UINT8 *p_param, UINT8 param_len);
+static void btusb_lite_ipc_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len);
+static void btusb_lite_ipc_avdt_sync_info_send(struct btusb_cb *p_dev,
+ tAVDT_SYNC_INFO *p_sync_rsp);
+
+static void btusb_lite_ipc_sent_to_user(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+/*
+ * Globals
+ */
+static const struct file_operations btusb_lite_fops =
+{
+ .open = btusb_lite_open,
+ .read = btusb_lite_read,
+ .poll = btusb_lite_poll,
+ .write = btusb_lite_write,
+ .release = btusb_lite_close,
+};
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_open
+ **
+ ** Description Open BTUSB Lite interface
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static void btusb_lite_init(struct btusb_cb *p_dev)
+{
+ struct proc_dir_entry *p_lite_pde;
+
+ /* Save p_lite_pde */
+ p_lite_pde = p_dev->lite_cb.p_lite_pde;
+
+ /* Clear Control Block */
+ memset(&p_dev->lite_cb, 0x00, sizeof(p_dev->lite_cb));
+
+ /* Restore p_lite_pde */
+ p_dev->lite_cb.p_lite_pde = p_lite_pde;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_open
+ **
+ ** Description Open BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+static int btusb_lite_open(struct inode *inode, struct file *file)
+{
+ int rv;
+ struct btusb_cb *p_dev = BTUSB_PDE_DATA(inode);
+
+ BTUSB_INFO("btusb_lite_open\n");
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ rv = -ENODEV;
+ goto out;
+ }
+
+ if (p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface already opened\n");
+ rv = -EBUSY;;
+ goto out;
+ }
+
+ file->private_data = p_dev; /* Save our private p_dev */
+
+ p_dev->lite_cb.opened = 1; /* Lite Interface opened */
+
+ /* Clear Every Lite Stack Control Block */
+ memset(&p_dev->lite_cb.stat, 0, sizeof(p_dev->lite_cb.stat));
+ memset(&p_dev->lite_cb.from_app, 0, sizeof(p_dev->lite_cb.from_app));
+ memset(&p_dev->lite_cb.to_app, 0, sizeof(p_dev->lite_cb.to_app));
+ memset(&p_dev->lite_cb.mgt, 0, sizeof(p_dev->lite_cb.mgt));
+ memset(&p_dev->lite_cb.btu, 0, sizeof(p_dev->lite_cb.btu));
+ memset(&p_dev->lite_cb.l2c, 0, sizeof(p_dev->lite_cb.l2c));
+ memset(&p_dev->lite_cb.av, 0, sizeof(p_dev->lite_cb.av));
+ memset(&p_dev->lite_cb.avdt, 0, sizeof(p_dev->lite_cb.avdt));
+
+ rv = 0;
+
+out:
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_close
+ **
+ ** Description Close BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+static int btusb_lite_close(struct inode *inode, struct file *file)
+{
+ int rv;
+ struct btusb_cb *p_dev = BTUSB_PDE_DATA(inode);
+
+ BTUSB_INFO("btusb_lite_close\n");
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ rv = -ENODEV;
+ goto out;
+ }
+
+ if (!p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ rv = -EBUSY;;
+ goto out;
+ }
+
+ BTUSB_ERR("To do, flush/free pending data\n");
+ btusb_lite_init(p_dev);
+
+ rv = 0;
+
+out:
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_write
+ **
+ ** Description Write handler of the BTUSB Lite interface
+ **
+ ** Returns Nb bytes written
+ **
+ *******************************************************************************/
+static ssize_t btusb_lite_write(struct file *file, const char *p_user_buffer,
+ size_t count, loff_t *p_off)
+{
+ struct btusb_cb *p_dev = file->private_data;
+ size_t remainder;
+ struct btusb_lite_cb *p_lite_cb;
+ unsigned long copy_len;
+ ssize_t copied_len;
+ UINT8 *p;
+ UINT16 rx_event;
+ BT_HDR *p_msg;
+
+ BTUSB_DBG("btusb_lite_write count=%zu\n", count);
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ return -ENODEV;
+ }
+
+ if (!p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ return -EBUSY;
+ }
+
+ if (unlikely(count == 0))
+ {
+ return 0;
+ }
+
+ /* check that the incoming data is good */
+ if (unlikely(!access_ok(VERIFY_READ, (void *)p_user_buffer, count)))
+ {
+ BTUSB_ERR("buffer access verification failed\n");
+ return -EFAULT;
+ }
+
+ p_lite_cb = &p_dev->lite_cb;
+
+ copied_len = 0;
+ remainder = count;
+
+ while(remainder)
+ {
+ /* If a full Header has not yet been received */
+ if (p_lite_cb->from_app.rx_header_len < BTUSB_LITE_IPC_HDR_SIZE)
+ {
+ /* How many bytes are needed (1 to 4) */
+ copy_len = BTUSB_LITE_IPC_HDR_SIZE - p_lite_cb->from_app.rx_header_len;
+
+ /* If less bytes are available */
+ if (remainder < copy_len)
+ {
+ copy_len = remainder;
+ }
+
+ /* Copy the header (or a part of it) */
+ if (copy_from_user(&p_lite_cb->from_app.rx_header[p_lite_cb->from_app.rx_header_len],
+ (void *)p_user_buffer, copy_len))
+ {
+ BTUSB_ERR("Copy header from user error\n");
+ return -EINVAL;
+ }
+ remainder -= copy_len;
+ p_lite_cb->from_app.rx_header_len += copy_len;
+ p_user_buffer += copy_len;
+ copied_len += copy_len;
+
+ /* If the buffer has been read */
+ if (p_lite_cb->from_app.rx_header_len == BTUSB_LITE_IPC_HDR_SIZE)
+ {
+ p = p_lite_cb->from_app.rx_header;
+ STREAM_TO_UINT16(p_lite_cb->from_app.rx_len, p);
+ STREAM_TO_UINT16(rx_event, p);
+
+ BTUSB_DBG("Rx Len=%d RxEvent=0x%X\n", p_lite_cb->from_app.rx_len, rx_event);
+
+ p_lite_cb->from_app.rx_len -= sizeof(UINT16); /* Do not count Event Field */
+
+ /* get a buffer from the pool (add one byte for HCI_Type) */
+ if (unlikely((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + p_lite_cb->from_app.rx_len + 1)) == NULL))
+ {
+ BTUSB_ERR("unable to get GKI buffer - write failed\n");
+ return -EINVAL;
+ }
+ p_msg->event = rx_event;
+ p_msg->layer_specific = 0;
+ p_msg->offset = 1;
+ p_msg->len = 0;
+
+ p_lite_cb->from_app.p_rx_msg = p_msg;
+ }
+ }
+ /* If Header already received */
+ else
+ {
+ p_msg = p_lite_cb->from_app.p_rx_msg;
+
+ if (!p_msg)
+ {
+ BTUSB_ERR("no Rx buffer\n");
+ return EINVAL;
+ }
+ p = (UINT8 *)(p_msg + 1) + p_msg->len + p_msg->offset;
+
+ /* How many payload bytes are expected */
+ copy_len = p_lite_cb->from_app.rx_len;
+
+ /* If less bytes are available */
+ if (remainder < copy_len)
+ {
+ copy_len = remainder;
+ }
+
+ /* Copy the Payload (or a part of it) */
+ if (copy_from_user(p, (void *)p_user_buffer, copy_len))
+ {
+ BTUSB_ERR("Copy payload from user error\n");
+ return -EINVAL;
+ }
+ remainder -= copy_len;
+ p_user_buffer += copy_len;
+ copied_len += copy_len;
+ p_lite_cb->from_app.rx_len -= copy_len;
+ p_msg->len += copy_len;
+
+ if (p_lite_cb->from_app.rx_len == 0)
+ {
+ /* Handle the received message */
+ btusb_lite_ipc_hndl(p_dev, p_msg);
+
+ p_lite_cb->from_app.p_rx_msg = NULL;
+ p_lite_cb->from_app.rx_header_len = 0; /* Ready to receive a new header */
+ }
+ }
+ }
+
+ return copied_len;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_msg_to_app_get
+ **
+ ** Description Get next message to send to IPC
+ **
+ ** Returns GKI buffer to send (or Null)
+ **
+ *******************************************************************************/
+static BT_HDR *btusb_lite_msg_to_app_get(struct btusb_cb *p_dev)
+{
+ BT_HDR *p_msg;
+ BT_HDR *p_hdr_msg;
+ UINT8 *p_data;
+
+ /* First, check if a locally generated Event (IPC) message is pending */
+ p_msg = p_dev->lite_cb.to_app.p_ipc_msg;
+ if (p_msg)
+ {
+ return p_msg;
+ }
+
+ /* Secondly, check if a locally generated IPC Header message is pending */
+ p_msg = p_dev->lite_cb.to_app.p_hdr_msg;
+ if (p_msg)
+ {
+ return p_msg;
+ }
+
+ /* Thirdly, check if an HCI message is pending */
+ p_msg = p_dev->lite_cb.to_app.p_hci_msg;
+ if (p_msg)
+ {
+ return p_msg;
+ }
+
+ /*
+ * No pending message. Check queues now
+ */
+
+ /* First, check if a locally generated Event (UIPC) message is enqueued */
+ p_msg = GKI_dequeue(&p_dev->lite_cb.to_app.ipc_queue);
+ if (p_msg)
+ {
+ p_dev->lite_cb.to_app.p_ipc_msg = p_msg;
+ return p_msg;
+ }
+
+ /* If HCI is not over IPC */
+ if (!btusb_lite_is_hci_over_ipc(p_dev))
+ {
+ return NULL; /* Nothing more to send on IPC */
+ }
+
+ /* Check if an HCI message (from BT controller) is ready */
+ p_msg = GKI_getfirst(&p_dev->rx_queue);
+ if (p_msg)
+ {
+ /* We need to Build an IPC Header to send the HCI packet */
+ p_hdr_msg = GKI_getbuf(sizeof(BT_HDR) + BTUSB_LITE_IPC_HDR_SIZE);
+ if (p_hdr_msg == NULL)
+ {
+ /* Leave the Received HCI packet in the queue (for next time) */
+ BTUSB_ERR("No more buffer\n");
+ p_dev->lite_cb.to_app.p_hci_msg = NULL;
+ return NULL;
+ }
+ p_hdr_msg->len = BTUSB_LITE_IPC_HDR_SIZE;
+ p_hdr_msg->offset = 0;
+ p_hdr_msg->layer_specific = 0;
+ p_hdr_msg->event = 0;
+ p_data = (UINT8 *)(p_hdr_msg + 1) + p_hdr_msg->offset;
+
+ /* Write Length */
+ UINT16_TO_STREAM(p_data, p_msg->len + BTUSB_LITE_IPC_HDR_EVT_SIZE);
+
+ /* Write Event code */
+ switch(p_msg->event)
+ {
+ case HCIT_TYPE_EVENT:
+ {
+ tBTUSB_TRANSACTION *p_trans;
+ p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+ BTUSB_INFO("Event=0x%02X Received from BT Controller\n",
+ *(p_trans->dma_buffer + p_msg->offset));
+ BTUSB_INFO("IPC Buffer TxEvent=BT_EVT_TO_BTU_HCI_EVT(%X) Length=%d\n",
+ BT_EVT_TO_BTU_HCI_EVT, p_msg->len);
+ }
+ UINT16_TO_STREAM(p_data, BT_EVT_TO_BTU_HCI_EVT);
+ break;
+
+ case HCIT_TYPE_ACL_DATA:
+ BTUSB_INFO("IPC Buffer TxEvent=BT_EVT_BTU_IPC_ACL_EVT(%X) Length=%d\n", BT_EVT_BTU_IPC_ACL_EVT, p_msg->len);
+ UINT16_TO_STREAM(p_data, BT_EVT_BTU_IPC_ACL_EVT);
+ break;
+
+ case HCIT_TYPE_LM_DIAG:
+ BTUSB_INFO("IPC Buffer TxEvent=BT_EVT_TO_LM_DIAG(%X) Length=%d\n", BT_EVT_TO_LM_DIAG, p_msg->len);
+ UINT16_TO_STREAM(p_data, BT_EVT_TO_LM_DIAG);
+ break;
+
+ default:
+ /* Should not append. Set Event to 0xFFFF for debug */
+ BTUSB_ERR("Unknown event=0x%x\n", p_msg->event);
+ UINT16_TO_STREAM(p_data, 0xFFFF);
+ break;
+ }
+
+ /* Store Header */
+ p_dev->lite_cb.to_app.p_hdr_msg = p_hdr_msg;
+
+ /* Dequeue HCI message */
+ p_msg = GKI_dequeue(&p_dev->rx_queue);
+ p_dev->lite_cb.to_app.p_hci_msg = p_msg;
+
+ return p_hdr_msg; /* Return pointer on Header */
+ }
+
+ return p_msg;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_msg_to_app_get_data_addr
+ **
+ ** Description Retrieve the data from a GKI Buffer pointer
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_msg_to_app_get_data_addr(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ tBTUSB_TRANSACTION *p_trans;
+
+ /* If the message is a "real" GKI buffer */
+ if ((p_dev->lite_cb.to_app.p_ipc_msg == p_msg) ||
+ (p_dev->lite_cb.to_app.p_hdr_msg == p_msg))
+ {
+ return (UINT8 *)(p_msg + 1) + p_msg->offset;
+ }
+
+ /* If the message is an HCI message, the data is located in the USB transaction */
+
+ /* Check if the message is an HCI message */
+ if (p_dev->lite_cb.to_app.p_hci_msg == p_msg)
+ {
+ p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+ return (p_trans->dma_buffer + p_msg->offset);
+ }
+
+ BTUSB_ERR("Unknown buffer=%p\n", p_msg);
+
+ return NULL;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_msg_to_app_free
+ **
+ ** Description Free a message which has been sent to IPC
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static void btusb_lite_msg_to_app_free(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ /* Check if the message is a locally generated Event (IPC) message */
+ if (p_dev->lite_cb.to_app.p_ipc_msg == p_msg)
+ {
+ GKI_freebuf(p_msg);
+ p_dev->lite_cb.to_app.p_ipc_msg = NULL;
+ return;
+ }
+
+ /* Check if the message is a locally generated Header (IPC) message */
+ if (p_dev->lite_cb.to_app.p_hdr_msg == p_msg)
+ {
+ GKI_freebuf(p_msg);
+ p_dev->lite_cb.to_app.p_hdr_msg = NULL;
+ return;
+ }
+
+ /* Check if the message is an HCI message */
+ if (p_dev->lite_cb.to_app.p_hci_msg == p_msg)
+ {
+ p_dev->lite_cb.to_app.p_hci_msg = NULL;
+ /* The buffer must not be freed. It has to be re-enqueue in USB core */
+ btusb_dequeued(p_dev, p_msg);
+ return;
+ }
+
+ BTUSB_ERR("Unknown buffer=%p\n", p_msg);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_read
+ **
+ ** Description Read handler of the BTUSB Lite interface
+ **
+ ** Returns Nb bytes written
+ **
+ *******************************************************************************/
+static ssize_t btusb_lite_read(struct file *file, char __user *p_user_buffer, size_t count, loff_t *p_off)
+{
+ struct btusb_cb *p_dev = file->private_data;
+ ssize_t size;
+ UINT8 *p_data;
+ unsigned long copy_len;
+ BT_HDR *p_msg;
+ int rv;
+
+ BTUSB_DBG("btusb_lite_read\n");
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ size = -ENODEV;
+ goto out;
+ }
+
+ if (!p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ size = -EBUSY;;
+ goto out;
+ }
+
+ if (count == 0)
+ {
+ size = 0;
+ goto out;
+ }
+
+ /* Check that the user buffer is good */
+ if (unlikely(!access_ok(VERIFY_WRITE, (void *)p_user_buffer, count)))
+ {
+ BTUSB_ERR("buffer access verification failed\n");
+ size = -EFAULT;
+ goto out;
+ }
+
+ /* Sleep while nothing for the application */
+ rv = wait_event_interruptible(p_dev->rx_wait_q,
+ ((p_msg = btusb_lite_msg_to_app_get(p_dev)) != NULL));
+
+ if (unlikely(rv))
+ {
+ BTUSB_DBG("read wait interrupted");
+ return rv;
+ }
+
+ if (p_msg)
+ {
+ if (p_msg->len < count)
+ {
+ copy_len = p_msg->len;
+ }
+ else
+ {
+ copy_len = count; /* User asks for count bytes */
+ }
+
+ BTUSB_DBG("p_msg=%p msg->len=%d count=%zu copy_len=%lu\n", p_msg, p_msg->len, count, copy_len);
+
+ p_data = btusb_lite_msg_to_app_get_data_addr(p_dev, p_msg);
+ if (p_data == NULL)
+ {
+ size = -EFAULT;
+ goto out;
+ }
+
+ /* copy the message data to the available user space */
+ if (unlikely(copy_to_user(p_user_buffer, p_data, copy_len)))
+ {
+ BTUSB_ERR("copy to user error\n");
+ size = -EINVAL;
+ goto out;
+ }
+
+ BTUSB_DBG("copied %ld bytes\n", copy_len);
+
+ p_msg->offset += copy_len;
+ p_msg->len -= copy_len;
+ size = copy_len;
+
+ if (p_msg->len == 0)
+ {
+ BTUSB_DBG("free gki buffer\n");
+ btusb_lite_msg_to_app_free(p_dev, p_msg);
+ }
+ goto out;
+ }
+ else
+ {
+ BTUSB_ERR("No Buffer\n");
+ }
+
+ size = 0; /* should not happen */
+
+out:
+ return size;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_poll
+ **
+ ** Description Poll callback (to implement select)
+ **
+ ** Parameters file : file structure of the opened instance
+ ** p_pt : poll table to which the local queue must be added
+ **
+ ** Returns Mask of the type of polling supported, error number if negative
+ **
+ *******************************************************************************/
+static unsigned int btusb_lite_poll(struct file *file, struct poll_table_struct *p_pt)
+{
+ struct btusb_cb *p_dev = file->private_data;
+ unsigned int mask;
+
+ BTUSB_DBG("enter\n");
+
+ /* retrieve the device from the file pointer*/
+ BTUSB_DBG("p_dev=%p\n", p_dev);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ // check if the device was disconnected
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->lite_cb.opened))
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ return -EINVAL;
+ }
+
+ /* indicate to the system on which queue it should poll (non blocking call) */
+ poll_wait(file, &p_dev->rx_wait_q, p_pt);
+
+ /* enable WRITE (select/poll is not write blocking) */
+ mask = POLLOUT | POLLWRNORM;
+
+ /* enable READ only if data is queued from HCI */
+ if (btusb_lite_msg_to_app_get(p_dev))
+ {
+ mask |= POLLIN | POLLRDNORM;
+ }
+
+ return mask;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_create
+ **
+ ** Description Create BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+int btusb_lite_create(struct btusb_cb *p_dev, struct usb_interface *p_interface)
+{
+ int rv;
+ char procname[64];
+
+ btusb_lite_init(p_dev);
+
+ scnprintf(procname, sizeof(procname), "driver/%s-lite", p_interface->usb_dev->kobj.name);
+ p_dev->lite_cb.p_lite_pde = proc_create_data(procname, S_IRUGO | S_IWUGO, NULL, &btusb_lite_fops, p_dev);
+ if (p_dev->lite_cb.p_lite_pde == NULL)
+ {
+ BTUSB_ERR("Couldn't create %s entry\n", procname);
+ rv = -1;
+ }
+ else
+ {
+ BTUSB_INFO("Created /proc/%s\n", procname);
+ rv = 0;
+ }
+
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_delete
+ **
+ ** Description Delete BTUSB Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+void btusb_lite_delete(struct btusb_cb *p_dev, struct usb_interface *p_interface)
+{
+ char procname[64];
+
+ scnprintf(procname, sizeof(procname), "driver/%s-lite", p_interface->usb_dev->kobj.name);
+ remove_proc_entry(procname, NULL);
+ BTUSB_INFO("/proc/%s deleted\n", procname);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_is_hci_over_ipc
+ **
+ ** Description Check if HCI is over IPC (Lite Interface).
+ **
+ ** Returns int (1 if HCI is over IPC otherwise 0)
+ **
+ *******************************************************************************/
+int btusb_lite_is_hci_over_ipc(struct btusb_cb *p_dev)
+{
+ if ((p_dev->lite_cb.opened) && /* User Space opened the Lite interface */
+ (p_dev->lite_cb.mgt.opened) && /* IPC MGT Opened */
+ /* Lite Transport is opened */
+ ((p_dev->lite_cb.btu.transport_state == BTU_LITE_STACK_ACTIVE) ||
+ (p_dev->lite_cb.btu.transport_state == BTU_LITE_TRANSPORT_ACTIVE)))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_stop_all
+ **
+ ** Description Stop all sound streams
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_lite_stop_all(struct btusb_cb *p_dev)
+{
+ int i;
+
+ BTUSB_INFO("");
+
+ for (i = 0 ; i < BTA_AV_NUM_STRS ; i++)
+ {
+ btusb_lite_av_stop(p_dev, i, 0);
+ btusb_lite_av_remove(p_dev, i, 0, 0);
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_hndl
+ **
+ ** Description Handle received message from BTUSB Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ BTUSB_INFO("IPC Buffer RxEvent=%s(0x%X) Length=%d\n",
+ btusb_lite_ipc_event_desc(p_msg->event), p_msg->event, p_msg->len);
+
+ if (unlikely(dbgflags & BTUSB_DBG_MSG) && p_msg->len)
+ {
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ int len = p_msg->len>20?20:p_msg->len;
+ int i;
+
+ for (i = 0 ; i < len ; i++, p++)
+ {
+ printk("%02X ", *p);
+ }
+ if (p_msg->len>20)
+ printk("...\n");
+ else
+ printk("\n");
+ }
+
+ switch(p_msg->event)
+ {
+ case BT_EVT_TO_LM_HCI_CMD:
+ btusb_lite_ipc_hci_cmd_hndl(p_dev, p_msg);
+ /* NO GKI_freebuf here */
+ break;
+
+ case BT_EVT_TO_LM_HCI_ACL:
+ btusb_lite_ipc_hci_acl_hndl(p_dev, p_msg);
+ /* NO GKI_freebuf here */
+ break;
+
+ case BT_EVT_BTU_IPC_MGMT_EVT:
+ btusb_lite_ipc_mgt_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_BTU_EVT:
+ btusb_lite_ipc_btu_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_L2C_EVT:
+ btusb_lite_ipc_l2c_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_BTM_EVT:
+ btusb_lite_ipc_btm_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_AVDT_EVT:
+ btusb_lite_ipc_avdt_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_SLIP_EVT:
+ case BT_EVT_BTU_IPC_BTTRC_EVT:
+ case BT_EVT_BTU_IPC_BURST_EVT:
+ case BT_EVT_BTU_IPC_ACL_EVT:
+ case BT_EVT_BTU_IPC_L2C_MSG_EVT:
+ BTUSB_INFO("Event=0x%X Not expected\n", p_msg->event);
+ GKI_freebuf(p_msg);
+ break;
+
+ default:
+ BTUSB_INFO("Event=0x%X Unknown\n", p_msg->event);
+ GKI_freebuf(p_msg);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_hci_cmd_hndl
+ **
+ ** Description Handle HCI CMD packet received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_hci_cmd_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p;
+ UINT16 hci_opcode;
+ UINT8 hci_status;
+
+ /* First check if this HCI command must be caught by BTUSB */
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ STREAM_TO_UINT16(hci_opcode, p); /* Extract HCI Opcode */
+
+ /* If the HCI Opcode must be caught */
+ switch(hci_opcode)
+ {
+ case HCI_BRCM_PAUSE_TRANSPORT:
+ BTUSB_INFO("HCI TransportPause VSC (%X) caught\n", hci_opcode);
+ hci_status = HCI_SUCCESS;
+ btusb_lite_ipc_cmd_cplt_evt_send(p_dev, hci_opcode,
+ &hci_status, sizeof(hci_status));
+ GKI_freebuf(p_msg);
+ return;
+
+ case HCI_BRCM_TRANSPORT_RESUME:
+ BTUSB_INFO("HCI TransportResume VSC (%X) caught\n", hci_opcode);
+
+ hci_status = HCI_SUCCESS;
+ btusb_lite_ipc_cmd_cplt_evt_send(p_dev, hci_opcode,
+ &hci_status, sizeof(hci_status));
+ GKI_freebuf(p_msg);
+ return;
+
+ default:
+ break;
+ }
+
+ BTUSB_INFO("HCI OpCode=0x%04X Sent to BT Controller\n", hci_opcode);
+
+ if (p_msg->offset < 1)
+ {
+ BTUSB_ERR("Offset=%d too small\n", p_msg->offset);
+ GKI_freebuf(p_msg);
+ return;
+ }
+
+ p_msg->offset--; /* Reduce Offset to add H4 HCI Type (Command) */
+ p_msg->len++;
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ UINT8_TO_STREAM(p, HCIT_TYPE_COMMAND);
+
+ /* add the incoming data and notify the btusb_tx_task to process */
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ // wake up tasklet
+ tasklet_schedule(&p_dev->tx_task);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_hci_acl_hndl
+ **
+ ** Description Handle HCI ACL packet received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_hci_acl_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p;
+
+ if (p_msg->offset < 1)
+ {
+ BTUSB_ERR("Offset=%d too small\n", p_msg->offset);
+ GKI_freebuf(p_msg);
+ return;
+ }
+
+ p_msg->offset--; /* Reduce Offset to add H4 HCI Type (Command) */
+ p_msg->len++;
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ UINT8_TO_STREAM(p, HCIT_TYPE_ACL_DATA);
+
+ /* add the incoming data and notify the btusb_tx_task to process */
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ // wake up tasklet
+ tasklet_schedule(&p_dev->tx_task);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_mgt_hndl
+ **
+ ** Description Handle Mgt messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_mgt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ UINT8 response[6];
+ UINT8 *p_response = response;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_MGMT Request */
+
+ switch(cmd)
+ {
+ case UIPC_OPEN_REQ:
+ BTUSB_INFO("IPC_MGT:OpenReq received\n");
+ /* If Mgt already opened */
+ if (p_dev->lite_cb.mgt.opened)
+ {
+ BTUSB_ERR("IPC_MGT Was already opened\n");
+ UINT8_TO_STREAM(p_response, UIPC_STATUS_FAIL); /* Status */
+ }
+ else
+ {
+ p_dev->lite_cb.mgt.opened = 1;
+ UINT8_TO_STREAM(p_response, UIPC_STATUS_SUCCESS); /* Status */
+ }
+ UINT16_TO_STREAM(p_response, UIPC_VERSION_MAJOR); /* version_major */
+ UINT16_TO_STREAM(p_response, UIPC_VERSION_MINOR); /* version_minor */
+ UINT8_TO_STREAM(p_response, BTM_SYNC_INFO_NUM_STR); /* Number of simultaneous streams supported by the light stack */
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_MGMT_EVT, UIPC_OPEN_RSP,
+ response, p_response - response);
+ break;
+
+ case UIPC_CLOSE_REQ:
+ BTUSB_INFO("IPC_MGT:CloseReq received\n");
+ p_dev->lite_cb.mgt.opened = 0;
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_MGMT_EVT, UIPC_CLOSE_RSP, NULL, 0);
+ break;
+
+ default:
+ BTUSB_INFO("Unknown IPC_MGT command=%d\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_btu_hndl
+ **
+ ** Description Handle BTU messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_btu_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 byte;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_BTU Request */
+
+ switch(cmd)
+ {
+ case BTU_IPC_CMD_SET_TRANSPORT_STATE:
+ STREAM_TO_UINT8(byte, p); /* Extract Param */
+ BTUSB_INFO("IPC_BTU:SetTransportState (%d) received\n", byte);
+ p_dev->lite_cb.btu.transport_state = byte;
+ break;
+
+ case BTU_IPC_CMD_DISABLE_TRANSPORT:
+ STREAM_TO_UINT8(byte, p); /* Extract Param */
+ BTUSB_INFO("IPC_BTU:DisableTransport (%d) received\n", byte);
+ p_dev->lite_cb.btu.transport_disabled = byte;
+ break;
+
+ default:
+ BTUSB_INFO("Unknown IPC_BTU command=%d\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_btm_hndl
+ **
+ ** Description Handle BTM messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_btm_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ tBTA_AV_SYNC_INFO sync_info;
+ UINT8 scb_idx;
+ tBTA_AV_AUDIO_CODEC_INFO codec_cfg;
+ UINT8 start_stop_flag;
+ UINT8 multi_av_supported;
+ UINT16 curr_mtu;
+ UINT8 audio_open_cnt;
+ UINT8 response[1];
+ UINT8 *p_response = response;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_BTU Request */
+
+ switch(cmd)
+ {
+ case BTA_AV_SYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvSyncToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(sync_info.avdt_handle, p);
+ STREAM_TO_UINT8(sync_info.chnl, p);
+ STREAM_TO_UINT8(sync_info.codec_type, p);
+ STREAM_TO_UINT8(sync_info.cong, p);
+ STREAM_TO_UINT8(sync_info.hdi, p);
+ STREAM_TO_UINT8(sync_info.hndl, p);
+ STREAM_TO_UINT8(sync_info.l2c_bufs, p);
+ STREAM_TO_UINT16(sync_info.l2c_cid, p);
+ STREAM_TO_ARRAY (sync_info.peer_addr, p, BD_ADDR_LEN);
+ STREAM_TO_UINT8(multi_av_supported, p);
+ STREAM_TO_UINT16(curr_mtu, p);
+ BTUSB_INFO("avdt_hdl=0x%x chnl=0x%x codec_type=0x%x cong=%d hdi=%d hndl=0x%x\n",
+ sync_info.avdt_handle, sync_info.chnl, sync_info.codec_type,
+ sync_info.cong, sync_info.hdi, sync_info.hndl);
+ BTUSB_INFO("l2c_bufs=%d l2c_cid=0x%x multi_av_sup=%d curr_mtu=%d\n",
+ sync_info.l2c_bufs, sync_info.l2c_cid, multi_av_supported, curr_mtu);
+ BTUSB_INFO("BdAddr=%02X-%02X-%02X-%02X-%02X-%02X\n",
+ sync_info.peer_addr[0], sync_info.peer_addr[1],sync_info.peer_addr[2],
+ sync_info.peer_addr[3], sync_info.peer_addr[4],sync_info.peer_addr[5]);
+
+ /* Add AV channel */
+ btusb_lite_av_add(p_dev, &sync_info, multi_av_supported, curr_mtu);
+
+ UINT8_TO_STREAM(p_response, sync_info.hdi);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_SYNC_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_START_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrStartToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ STREAM_TO_UINT16 (codec_cfg.bit_rate, p);
+ STREAM_TO_UINT16 (codec_cfg.bit_rate_busy, p);
+ STREAM_TO_UINT16 (codec_cfg.bit_rate_swampd, p);
+ STREAM_TO_UINT8 (codec_cfg.busy_level, p);
+ STREAM_TO_ARRAY (codec_cfg.codec_info, p, AVDT_CODEC_SIZE);
+ STREAM_TO_UINT8 (codec_cfg.codec_type, p);
+ STREAM_TO_UINT8 (start_stop_flag, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d busy_level=%d start_stop_flag=%d\n",
+ scb_idx, audio_open_cnt,
+ codec_cfg.busy_level, start_stop_flag);
+ BTUSB_INFO(" codec_type=0x%x bit_rate=%d busy_level=%d bit_rate_busy=%d bit_rate_swampd=%d\n",
+ codec_cfg.codec_type, codec_cfg.bit_rate, codec_cfg.busy_level,
+ codec_cfg.bit_rate_busy, codec_cfg.bit_rate_swampd);
+ BTUSB_INFO(" CodecInfo:%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
+ codec_cfg.codec_info[0], codec_cfg.codec_info[1], codec_cfg.codec_info[2],
+ codec_cfg.codec_info[3], codec_cfg.codec_info[4], codec_cfg.codec_info[5],
+ codec_cfg.codec_info[6], codec_cfg.codec_info[7], codec_cfg.codec_info[8],
+ codec_cfg.codec_info[9]);
+
+ /* Start AV */
+ btusb_lite_av_start(p_dev, scb_idx, start_stop_flag, audio_open_cnt, &codec_cfg);
+
+ /* Send the response */
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_START_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_STOP_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrStopToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+
+ btusb_lite_av_stop(p_dev, scb_idx, audio_open_cnt);
+
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_STOP_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_SUSPEND_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrSuspendToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+ btusb_lite_av_suspend(p_dev, scb_idx, audio_open_cnt);
+
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_SUSPEND_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_CLEANUP_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrCleanupToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ STREAM_TO_UINT16(curr_mtu, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d curr_mtu=%d\n", scb_idx, audio_open_cnt,
+ curr_mtu);
+
+ btusb_lite_av_remove(p_dev, scb_idx, audio_open_cnt, curr_mtu);
+
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_CLEANUP_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ /* BTC commands (unexpected) */
+ case A2DP_START_REQ:
+ case A2DP_START_RESP:
+ case A2DP_STOP_REQ:
+ case A2DP_STOP_RESP:
+ case A2DP_CLEANUP_REQ:
+ case A2DP_CLEANUP_RESP:
+ case A2DP_SUSPEND_REQ:
+ case A2DP_SUSPEND_RESP:
+ case A2DP_JITTER_DONE_IND:
+
+ /* BTA AV Response commands (unexpected) */
+ case BTA_AV_SYNC_TO_LITE_RESP:
+ case BTA_AV_STR_START_TO_LITE_RESP:
+ case BTA_AV_STR_STOP_TO_LITE_RESP:
+ case BTA_AV_STR_CLEANUP_TO_LITE_RESP:
+ case BTA_AV_STR_SUSPEND_TO_LITE_RESP:
+ case BTA_AV_SYNC_ERROR_RESP:
+ BTUSB_INFO("IPC_BTM: Unexpected Cmd=%d received\n", cmd);
+ break;
+
+ default:
+ BTUSB_INFO("IPC_BTM: Unknown Cmd=%d received\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_avdt_hndl
+ **
+ ** Description Handle AVDT messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_avdt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ tAVDT_SYNC_INFO sync_req;
+ tAVDT_SYNC_INFO sync_rsp;
+ int stream;
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 avdt_status;
+
+ STREAM_TO_UINT8(sync_req.op_code, p); /* Extract UIPC_AVDT Request */
+
+ switch(sync_req.op_code)
+ {
+ case AVDT_SYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtSyncToLiteReq (%d) received\n", sync_req.op_code);
+ break;
+
+ case AVDT_RESYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtReSyncToLiteReq (%d) received\n", sync_req.op_code);
+ break;
+
+ case AVDT_SYNC_TO_FULL_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtSyncToFullReq (%d) received\n", sync_req.op_code);
+ break;
+
+ case AVDT_REMOVE_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtRemoveToLiteReq (%d)\n", sync_req.op_code);
+ break;
+
+ case AVDT_SYNC_CP_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtSyncCpToLiteReq (%d)\n", sync_req.op_code);
+ break;
+
+ case AVDT_SYNC_TO_LITE_RESP:
+ case AVDT_RESYNC_TO_LITE_RESP:
+ case AVDT_SYNC_TO_FULL_RESP:
+ case AVDT_REMOVE_TO_LITE_RESP:
+ case AVDT_SYNC_CP_TO_LITE_RESP:
+ BTUSB_INFO("IPC_AVDT: Unexpected Cmd=%d received\n", sync_req.op_code);
+ sync_rsp.op_code = 0xFF;
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+
+ default:
+ BTUSB_INFO("IPC_AVDT: Unknown Cmd=%d received\n", sync_req.op_code);
+ sync_rsp.op_code = 0xFE;
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+
+ /* Extract parameters */
+ STREAM_TO_UINT8(sync_req.status, p);
+
+ /* Decode Sync CP parameters */
+ if (sync_req.op_code == AVDT_SYNC_CP_TO_LITE_REQ)
+ {
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++ )
+ {
+ STREAM_TO_UINT8(sync_req.scb_info[stream].handle, p);
+ STREAM_TO_UINT16(sync_req.scb_info[stream].cp.id, p);
+ STREAM_TO_UINT8(sync_req.scb_info[stream].cp.scms_hdr, p);
+ if (sync_req.scb_info[stream].handle)
+ {
+ BTUSB_INFO(" stream[%d]: handle=0x%x cp_id=0x%04X scms_hdr=0x%x\n",
+ stream, sync_req.scb_info[stream].handle,
+ sync_req.scb_info[stream].cp.id,
+ sync_req.scb_info[stream].cp.scms_hdr);
+ }
+ else
+ {
+ BTUSB_INFO(" stream[%d]: No Data\n", stream);
+ }
+ }
+ }
+ /* Decode other Sync message parameters */
+ else
+ {
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++ )
+ {
+ STREAM_TO_UINT8(sync_req.scb_info[stream].handle, p);
+ STREAM_TO_BDADDR(sync_req.scb_info[stream].peer_addr, p)
+ STREAM_TO_UINT16(sync_req.scb_info[stream].local_cid, p);
+ STREAM_TO_UINT16(sync_req.scb_info[stream].peer_mtu, p);
+ STREAM_TO_UINT8(sync_req.scb_info[stream].mux_tsid_media, p);
+ STREAM_TO_UINT16(sync_req.scb_info[stream].media_seq, p);
+ if (sync_req.scb_info[stream].handle)
+ {
+ BTUSB_INFO(" stream[%d]:\n", stream);
+ BTUSB_INFO(" BdAddr=%02X-%02X-%02X-%02X-%02X-%02X\n",
+ sync_req.scb_info[stream].peer_addr[0],
+ sync_req.scb_info[stream].peer_addr[1],
+ sync_req.scb_info[stream].peer_addr[2],
+ sync_req.scb_info[stream].peer_addr[3],
+ sync_req.scb_info[stream].peer_addr[4],
+ sync_req.scb_info[stream].peer_addr[5]);
+ BTUSB_INFO(" handle=0x%x local_cid=0x%x peer_mtu=%d mux_tsid_media=%d media_seq=%d\n",
+ sync_req.scb_info[stream].handle,
+ sync_req.scb_info[stream].local_cid,
+ sync_req.scb_info[stream].peer_mtu,
+ sync_req.scb_info[stream].mux_tsid_media,
+ sync_req.scb_info[stream].media_seq);
+ }
+ else
+ {
+ BTUSB_INFO(" stream[%d]: No data\n", stream);
+ }
+ }
+ }
+ memset(&sync_rsp, 0, sizeof(sync_rsp));
+
+ switch(sync_req.op_code)
+ {
+ case AVDT_SYNC_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_SYNC_TO_LITE_RESP;
+
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ if(btusb_lite_avdt_init_scb(p_dev, &(sync_req.scb_info[stream])) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_RESYNC_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_RESYNC_TO_LITE_RESP;
+
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ if((p_scb = btusb_lite_avdt_scb_by_hdl(p_dev, sync_req.scb_info[stream].handle)) != NULL)
+ {
+ memcpy(p_scb->p_ccb->peer_addr, sync_req.scb_info[stream].peer_addr, BD_ADDR_LEN);
+ p_scb->p_ccb->lcid = sync_req.scb_info[stream].local_cid;
+ p_scb->p_ccb->peer_mtu = sync_req.scb_info[stream].peer_mtu;
+ p_scb->mux_tsid_media = sync_req.scb_info[stream].mux_tsid_media;
+ p_scb->media_seq = sync_req.scb_info[stream].media_seq;
+ }
+ else if(btusb_lite_avdt_init_scb(p_dev, &(sync_req.scb_info[stream])) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_SYNC_TO_FULL_REQ:
+ sync_rsp.op_code = AVDT_SYNC_TO_FULL_RESP;
+
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ {
+ sync_rsp.scb_info[stream].handle = 0;
+ continue;
+ }
+
+ if(btusb_lite_avdt_remove_scb(p_dev, sync_req.scb_info[stream].handle,
+ &sync_rsp.scb_info[stream]) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_REMOVE_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_REMOVE_TO_LITE_RESP;
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ if(btusb_lite_avdt_remove_scb(p_dev, sync_req.scb_info[stream].handle,
+ &sync_rsp.scb_info[stream]) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_SYNC_CP_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_SYNC_CP_TO_LITE_RESP;
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ switch(sync_req.scb_info[stream].cp.id)
+ {
+ case AVDT_SYNC_CP_ID_NONE:
+ avdt_status = btusb_lite_avdt_cp_set_scms(p_dev,
+ sync_req.scb_info[stream].handle, FALSE, 0x00);
+ break;
+
+ case AVDT_SYNC_CP_ID_SCMS:
+ avdt_status = btusb_lite_avdt_cp_set_scms(p_dev,
+ sync_req.scb_info[stream].handle, TRUE,
+ sync_req.scb_info[stream].cp.scms_hdr);
+ break;
+
+ default:
+ avdt_status = AVDT_SYNC_FAILURE;
+ break;
+ }
+ if (avdt_status != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_avdt_sync_info_send
+ **
+ ** Description Build and send an IPC AVDT Sync Info Response
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_avdt_sync_info_send(struct btusb_cb *p_dev, tAVDT_SYNC_INFO *p_sync_rsp)
+{
+ int stream;
+ UINT8 response[BTUSB_LITE_IPC_AVDT_SYNC_INFO_RSP_LEN];
+ UINT8 *p_response = response;
+
+ UINT8_TO_STREAM(p_response, p_sync_rsp->status);
+
+ if (p_sync_rsp->op_code != AVDT_SYNC_CP_TO_LITE_RESP)
+ {
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ UINT8_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].handle);
+ BDADDR_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].peer_addr)
+ UINT16_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].local_cid);
+ UINT16_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].peer_mtu);
+ UINT8_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].mux_tsid_media);
+ UINT16_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].media_seq);
+ }
+ }
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_AVDT_EVT, p_sync_rsp->op_code,
+ response, p_response - response);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_l2c_hndl
+ **
+ ** Description Handle L2C messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_l2c_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ UINT8 response[3];
+ UINT8 *p_response = response;
+ struct btusb_lite_l2c_cb *p_l2c = &p_dev->lite_cb.l2c;
+ int stream;
+ tL2C_STREAM_INFO l2c_stream;
+ UINT16 local_cid;
+ UINT8 num_stream;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_MGMT Request */
+
+ switch(cmd)
+ {
+ case L2C_SYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_L2C:L2cSyncToLiteReq (%d) received\n", L2C_SYNC_TO_LITE_REQ);
+ STREAM_TO_UINT16(p_l2c->light_xmit_quota, p);
+ STREAM_TO_UINT16(p_l2c->acl_data_size, p);
+ STREAM_TO_UINT16(p_l2c->non_flushable_pbf, p);
+ STREAM_TO_UINT8(p_l2c->multi_av_data_cong_start, p);
+ STREAM_TO_UINT8(p_l2c->multi_av_data_cong_end, p);
+ STREAM_TO_UINT8(p_l2c->multi_av_data_cong_discard, p);
+ STREAM_TO_UINT8(num_stream, p);
+ BTUSB_INFO("Xquota=%d AclSize=%d NFpbf=%d congStart=%d congEnd=%d congDisc=%d NbStr=%d\n",
+ p_l2c->light_xmit_quota, p_l2c->acl_data_size, p_l2c->non_flushable_pbf,
+ p_l2c->multi_av_data_cong_start, p_l2c->multi_av_data_cong_end,
+ p_l2c->multi_av_data_cong_discard, num_stream);
+
+ /* Start building the response */
+ UINT16_TO_STREAM(p_response, p_l2c->light_xmit_unacked);
+ UINT8_TO_STREAM(p_response, num_stream);
+
+ for(stream = 0; stream < num_stream; stream++)
+ {
+ STREAM_TO_UINT16(l2c_stream.local_cid, p);
+ STREAM_TO_UINT16(l2c_stream.remote_cid, p);
+ STREAM_TO_UINT16(l2c_stream.out_mtu, p);
+ STREAM_TO_UINT16(l2c_stream.handle, p);
+ STREAM_TO_UINT16(l2c_stream.link_xmit_quota, p);
+ STREAM_TO_UINT8(l2c_stream.is_flushable, p);
+ BTUSB_INFO(" Stream[%d]:lcid=0x%X rcid=0x%X mtu=%d handle=0x%X xmit_quota=%d flushable=%d\n",
+ stream, l2c_stream.local_cid, l2c_stream.remote_cid,
+ l2c_stream.out_mtu, l2c_stream.handle,
+ l2c_stream.link_xmit_quota, l2c_stream.is_flushable);
+
+ /* Resume building the response */
+ UINT16_TO_STREAM(p_response, l2c_stream.local_cid);
+
+ /* Synchronize (add) this L2CAP Stream */
+ if (btusb_lite_l2c_add(p_dev, &l2c_stream) < 0)
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_FAILURE);
+ }
+ else
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_SUCCESS);
+ }
+ }
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_L2C_EVT, L2C_SYNC_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case L2C_REMOVE_TO_LITE_REQ:
+ BTUSB_INFO("IPC_L2C:L2cRemoveToLiteReq (%d) received\n", L2C_REMOVE_TO_LITE_REQ);
+ STREAM_TO_UINT16(p_l2c->light_xmit_quota, p);
+ STREAM_TO_UINT8(num_stream, p);
+ BTUSB_INFO("Xquota=%d NbStr=%d\n", p_l2c->light_xmit_quota, num_stream);
+
+ /* Start building the response */
+ UINT16_TO_STREAM(p_response, p_l2c->light_xmit_unacked);
+ UINT8_TO_STREAM(p_response, num_stream);
+
+ for(stream = 0; stream < num_stream; stream++)
+ {
+ STREAM_TO_UINT16(local_cid, p);
+ BTUSB_INFO(" Stream[%d]:lcid=0x%X\n", stream, p_l2c->ccb[stream].local_cid);
+
+ /* Resume building the response */
+ UINT16_TO_STREAM(p_response, local_cid);
+
+ /* Synchronize (remove) this L2CAP Stream */
+ if (btusb_lite_l2c_remove(p_dev, local_cid) < 0)
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_FAILURE);
+ }
+ else
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_SUCCESS);
+ }
+ }
+
+ /* Send the response to the full stack */
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_L2C_EVT, L2C_REMOVE_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ default:
+ BTUSB_INFO("Unknown IPC_MGT command=%d\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_rsp_send
+ **
+ ** Description Send an Response over Lite interface.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_rsp_send(struct btusb_cb *p_dev,
+ UINT16 event, UINT8 op_code, UINT8 *p_param, UINT8 param_len)
+{
+ BT_HDR *p_msg;
+ UINT16 size = param_len + BTUSB_LITE_IPC_HDR_SIZE + sizeof(UINT8);
+ UINT8 *p;
+
+ BTUSB_INFO("Event=%s(0x%X), opcode=%d len=%d\n", btusb_lite_ipc_event_desc(event),
+ event, op_code, param_len);
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = 0;
+ p_msg->len = size;
+
+ p = (UINT8 *)(p_msg + 1);
+
+ UINT16_TO_STREAM(p, param_len + BTUSB_LITE_IPC_HDR_EVT_SIZE + sizeof(UINT8)); /* Length */
+ UINT16_TO_STREAM(p, event); /* Event */
+ UINT8_TO_STREAM(p, op_code); /* Opcode */
+ if (p_param)
+ {
+ ARRAY_TO_STREAM(p, p_param, param_len)
+ }
+
+ /* Send message to User Space */
+ btusb_lite_ipc_sent_to_user(p_dev, p_msg);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_cmd_cplt_evt_send
+ **
+ ** Description Send an UIPC_Over_HCI VSC Cmd Complete.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len)
+{
+ BT_HDR *p_msg;
+ UINT16 size = param_len + BTUSB_LITE_IPC_HDR_SIZE + 5;
+ UINT8 *p;
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = 0;
+ p_msg->len = size;
+
+ p = (UINT8 *)(p_msg + 1);
+
+ UINT16_TO_STREAM(p, param_len + BTUSB_LITE_IPC_HDR_EVT_SIZE + 5); /* length */
+ UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_EVT); /* IPC OpCode */
+ UINT8_TO_STREAM(p, HCI_COMMAND_COMPLETE_EVT); /* Command Complete Evt */
+ UINT8_TO_STREAM(p, param_len + 3); /* Param Length (param + NumCmd + OpCode) */
+ UINT8_TO_STREAM(p, 0x01); /* HCI Num Command */
+ UINT16_TO_STREAM(p, opcode); /* HCI OpCode */
+
+ if (p_param)
+ {
+ ARRAY_TO_STREAM(p, p_param, param_len)
+ }
+
+ /* Send message to User Space */
+ btusb_lite_ipc_sent_to_user(p_dev, p_msg);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_sent_to_user
+ **
+ ** Description Send message to User Space (via IPC Interface).
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_sent_to_user(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ /* Update Lite Statistics */
+ p_dev->lite_cb.stat.event_bytes += p_msg->len;
+ p_dev->lite_cb.stat.event_completed++;
+
+ /* Enqueue message in IPC queue */
+ GKI_enqueue(&p_dev->lite_cb.to_app.ipc_queue, p_msg);
+
+ /* WakeUp IPC read */
+ wake_up_interruptible(&p_dev->rx_wait_q);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_event_desc
+ **
+ ** Description Get IPC Event description
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+static char *btusb_lite_ipc_event_desc(UINT16 event)
+{
+ switch(event)
+ {
+ case BT_EVT_TO_LM_HCI_CMD:
+ return "BT_EVT_TO_LM_HCI_CMD";
+ case BT_EVT_TO_LM_HCI_ACL:
+ return "BT_EVT_TO_LM_HCI_ACL";
+ case BT_EVT_BTU_IPC_MGMT_EVT:
+ return "BT_EVT_BTU_IPC_MGMT_EVT";
+ case BT_EVT_BTU_IPC_BTU_EVT:
+ return "BT_EVT_BTU_IPC_BTU_EVT";
+ case BT_EVT_BTU_IPC_L2C_EVT:
+ return "BT_EVT_BTU_IPC_L2C_EVT";
+ case BT_EVT_BTU_IPC_ACL_EVT:
+ return "BT_EVT_BTU_IPC_ACL_EVT";
+ case BT_EVT_BTU_IPC_BTM_EVT:
+ return "BT_EVT_BTU_IPC_BTM_EVT";
+ case BT_EVT_BTU_IPC_L2C_MSG_EVT:
+ return "BT_EVT_BTU_IPC_L2C_MSG_EVT";
+ case BT_EVT_BTU_IPC_AVDT_EVT:
+ return "BT_EVT_BTU_IPC_AVDT_EVT";
+ case BT_EVT_BTU_IPC_SLIP_EVT:
+ return "BT_EVT_BTU_IPC_SLIP_EVT";
+ case BT_EVT_BTU_IPC_BTTRC_EVT:
+ return "BT_EVT_BTU_IPC_BTTRC_EVT";
+ case BT_EVT_BTU_IPC_BURST_EVT:
+ return "BT_EVT_BTU_IPC_BURST_EVT";
+ default:
+ return "Unknown Event";
+ }
+}
+
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_av.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_av.c.svn-base
new file mode 100755
index 0000000..b2a1400
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_av.c.svn-base
@@ -0,0 +1,1322 @@
+/*
+ *
+ * btusb_lite_av.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include <linux/moduleparam.h>
+#include "btusb.h"
+#include "bd.h"
+#include "btpcm_api.h"
+#include "btsbc_api.h"
+#ifdef BTUSB_LITE_SEC
+#include "btsec_api.h"
+#endif
+
+/*
+ * Definitions
+ */
+#define BTUSB_LITE_AV_PCM_CHANNEL 0
+
+struct btusb_lite_av_sbc_param
+{
+ int frequency;
+ unsigned char nb_blocks;
+ unsigned char nb_subbands;
+ unsigned char mode;
+ unsigned char allocation;
+ unsigned char bitpool_min;
+ unsigned char bitpool_max;
+};
+
+
+/* Codec (From BT Spec) */
+#define A2D_MEDIA_TYPE_AUDIO 0x00
+
+#define A2D_MEDIA_CT_SBC 0x00 /* SBC Codec */
+#define A2D_MEDIA_CT_VEND 0xFF /* Vendor specific */
+
+/* SBC Codec (From BT Spec) */
+#define CODEC_SBC_LOSC 6
+
+#define CODEC_SBC_FREQ_MASK 0xF0
+#define CODEC_SBC_FREQ_48 0x10
+#define CODEC_SBC_FREQ_44 0x20
+#define CODEC_SBC_FREQ_32 0x40
+#define CODEC_SBC_FREQ_16 0x80
+
+#define CODEC_MODE_MASK 0x0F
+#define CODEC_MODE_JOIN_STEREO 0x01
+#define CODEC_MODE_STEREO 0x02
+#define CODEC_MODE_DUAL 0x04
+#define CODEC_MODE_MONO 0x08
+
+#define CODEC_SBC_BLOCK_MASK 0xF0
+#define CODEC_SBC_BLOCK_16 0x10
+#define CODEC_SBC_BLOCK_12 0x20
+#define CODEC_SBC_BLOCK_8 0x40
+#define CODEC_SBC_BLOCK_4 0x80
+
+#define CODEC_SBC_NBBAND_MASK 0x0C
+#define CODEC_SBC_NBBAND_8 0x04
+#define CODEC_SBC_NBBAND_4 0x08
+
+#define CODEC_SBC_ALLOC_MASK 0x03
+#define CODEC_SBC_ALLOC_LOUDNESS 0x01
+#define CODEC_SBC_ALLOC_SNR 0x02
+
+/* SEC codec */
+#ifdef BTUSB_LITE_SEC
+#define A2D_MEDIA_CT_SEC 0x07 /* Internal SEC Codec type */
+
+struct btusb_lite_av_sec_param
+{
+ int frequency;
+ unsigned char mode;
+};
+#endif
+
+
+/*
+ * Globals
+ */
+int pcm0_mute = 0;
+module_param(pcm0_mute, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(pcm0_mute, "Mute PCM channel 0");
+
+#define SILENSE_PCM_BUF_SIZE (2 * 128) /* 128 samples, Stereo */
+static const unsigned short btusb_lite_silence_pcm[SILENSE_PCM_BUF_SIZE] = {0};
+
+/*
+ * Local functions
+ */
+static int btusb_lite_av_parse_sbc_codec(struct btusb_lite_av_sbc_param *p_sbc, UINT8 *p_codec);
+static int btusb_lite_sbc_get_bitpool(struct btusb_lite_av_sbc_param *p_sbc_param, int target_bitrate);
+static void btusb_lite_av_pcm_cback(int pcm_stream, void *p_dev, void *p_data,
+ int nb_pcm_frames);
+static void btusb_lite_av_send_packet(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+static int btusb_lite_av_sbc_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg);
+
+static int btusb_lite_av_parse_vendor_codec(UINT8 *p_codec_info, UINT32 *p_vendor_id, UINT16 *p_vendor_codec_id);
+
+#ifdef BTUSB_LITE_SEC
+static int btusb_lite_av_parse_sec_codec(struct btusb_lite_av_sec_param *p_sec_param,
+ UINT8 *p_codec_info);
+static int btusb_lite_av_sec_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg);
+#endif
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_add
+**
+** Description Add (Sync) an AV channel.
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_add(struct btusb_cb *p_dev, tBTA_AV_SYNC_INFO *p_sync_info,
+ UINT8 multi_av_supported, UINT16 curr_mtu)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int rv;
+
+ p_av_cb->curr_mtu = curr_mtu; /* Update MTU */
+
+ if (p_sync_info->hdi >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad AV Index=%d\n", p_sync_info->hdi);
+ return;
+ }
+
+#if (BTU_MULTI_AV_INCLUDED == TRUE)
+ p_av_cb->multi_av &= ~(BTA_AV_MULTI_AV_SUPPORTED);
+ p_av_cb->multi_av |= multi_av_supported;
+#endif
+
+ p_av_scb = &p_av_cb->scb[p_sync_info->hdi];
+
+ p_av_scb->avdt_handle = p_sync_info->avdt_handle;
+ p_av_scb->chnl = p_sync_info->chnl;
+ p_av_scb->codec_type = p_sync_info->codec_type;
+ p_av_scb->cong = p_sync_info->cong;
+ p_av_scb->hdi = p_sync_info->hdi;
+ p_av_scb->hndl = p_sync_info->hndl;
+ p_av_scb->l2c_bufs = p_sync_info->l2c_bufs;
+ p_av_scb->l2c_cid = p_sync_info->l2c_cid;
+ memcpy(p_av_scb->peer_addr, p_sync_info->peer_addr, BD_ADDR_LEN);
+
+ if (p_av_cb->pcm.state == BTPCM_LITE_PCM_CLOSED)
+ {
+ /* Open the PCM Channel */
+ rv = btpcm_open(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_open failed\n");
+ return;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_OPENED;
+ p_av_cb->pcm.frequency = -1;
+ p_av_cb->pcm.channel = BTUSB_LITE_AV_PCM_CHANNEL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_remove
+**
+** Description Remove (Cleanup) an AV channel.
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_remove(struct btusb_cb *p_dev, UINT8 scb_idx,
+ UINT8 audio_open_cnt, UINT16 curr_mtu)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int av_scb;
+ int cleanup_needed = 1;
+ int rv;
+
+ p_av_cb->curr_mtu = curr_mtu; /* Update MTU */
+ p_av_cb->audio_open_cnt = audio_open_cnt; /* Update audio_open_cnt */
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad Index=%d\n", scb_idx);
+ return;
+ }
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ /* Remove AVDT CCB and SCB */
+ btusb_lite_avdt_remove_scb(p_dev, p_av_scb->avdt_handle, NULL);
+
+ /* Clear the AV Stream Control Clock */
+ memset(p_av_scb, 0, sizeof(*p_av_scb));
+
+ /* Check this is the last AV channel removed */
+ p_av_scb = &p_av_cb->scb[0];
+ for (av_scb = 0 ; av_scb < BTA_AV_NUM_STRS ; av_scb++, p_av_scb++)
+ {
+ if (p_av_scb->hndl)
+ {
+ cleanup_needed = 0;
+ break;
+ }
+ }
+
+ if (cleanup_needed)
+ {
+ if (p_av_cb->pcm.state == BTPCM_LITE_PCM_STARTED)
+ {
+ /* Stop the PCM Channel */
+ rv = btpcm_stop(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_close failed\n");
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CONFIGURED;
+ }
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_CLOSED)
+ {
+ /* Close the PCM Channel */
+ rv = btpcm_close(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_close failed\n");
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CLOSED;
+ }
+
+ if (p_av_cb->encoder.opened)
+ {
+ switch(p_av_cb->encoder.type)
+ {
+ case A2D_MEDIA_CT_SBC:
+ btsbc_free(p_av_cb->encoder.channel);
+ break;
+#ifdef BTUSB_LITE_SEC
+ case A2D_MEDIA_CT_SEC:
+ btsec_free(p_av_cb->encoder.channel);
+ break;
+#endif
+ default:
+ BTUSB_ERR("Unknown Encoder type=%d\n", p_av_cb->encoder.encoder.codec_type);
+ break;
+ }
+ p_av_cb->encoder.opened = 0;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_start
+**
+** Description Start AV
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_start(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 start_stop_flag,
+ UINT8 audio_open_cnt, tBTA_AV_AUDIO_CODEC_INFO *p_codec_cfg)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ UINT32 vendor_id;
+ UINT16 vendor_codec_id;
+ struct btusb_lite_av_scb *p_av_scb;
+
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return;
+ }
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ if (start_stop_flag)
+ {
+ p_av_cb->scb[scb_idx].started = FALSE;
+ BTUSB_ERR("start_stop_flag TODO!!!");
+ }
+ else
+ {
+ /* If the Codec Type is SBC */
+ if (p_codec_cfg->codec_type == A2D_MEDIA_CT_SBC)
+ {
+ if (btusb_lite_av_sbc_start(p_dev, scb_idx, p_codec_cfg) < 0)
+ {
+ BTUSB_ERR("SBC Stream not started\n");
+ return;
+ }
+ }
+ /* Else if the Codec Type is a Vendor Specific Codec */
+ else if (p_codec_cfg->codec_type == A2D_MEDIA_CT_VEND)
+ {
+ if (btusb_lite_av_parse_vendor_codec(p_codec_cfg->codec_info, &vendor_id, &vendor_codec_id) < 0)
+ {
+ BTUSB_ERR("Unable to parse Vendor Codec\n");
+ return;
+ }
+#ifdef BTUSB_LITE_SEC
+ /* If This is the SEC Encoder */
+ if ((vendor_id == BTSEC_VENDOR_ID) &&
+ (vendor_codec_id == BTSEC_VENDOR_CODEC_ID))
+ {
+ btusb_lite_av_sec_start(p_dev, scb_idx, p_codec_cfg);
+ }
+ else
+#endif
+ /* Add other Vendor Specific Vendor coder Here... */
+ {
+ BTUSB_ERR("Unsupported Codec VendorId=0x%08x VendorCodecId=0x%04x\n", vendor_id, vendor_codec_id);
+ }
+ }
+ else
+ {
+ BTUSB_ERR("Unsupported Encoder type=%d\n", p_codec_cfg->codec_type);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_parse_vendor_codec
+**
+** Description Parse Vendor Id and Vendor Codec Id from Codec information
+**
+** Returns Status, VendorId and VendorCodecId
+**
+*******************************************************************************/
+static int btusb_lite_av_parse_vendor_codec(UINT8 *p_codec_info, UINT32 *p_vendor_id, UINT16 *p_vendor_codec_id)
+{
+ UINT8 byte;
+ UINT32 vendor_id;
+ UINT16 vendor_codec_id;
+
+ if (!p_codec_info || !p_vendor_id || !p_vendor_codec_id)
+ {
+ BTUSB_ERR("Bad parameter\n");
+ return -1;
+ }
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract LOSC */
+ if (byte < (1 + 1 + 4 + 2)) /* Media Type, Media Codec Type, Vid, VCId */
+ {
+ BTUSB_ERR("Codec LOSC=%d too small\n", byte);
+ return -1;
+ }
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Type */
+ if (byte != A2D_MEDIA_TYPE_AUDIO)
+ {
+ BTUSB_ERR("Unsupported Media Type=0x%x\n", byte);
+ return -1;
+ }
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Codec Type */
+ if (byte != A2D_MEDIA_CT_VEND)
+ {
+ BTUSB_ERR("Media codec Type=0x%x is not Vendor(0xFF)\n", byte);
+ return -1;
+ }
+
+ STREAM_TO_UINT32(vendor_id, p_codec_info); /* Extract Vendor Id */
+ STREAM_TO_UINT16(vendor_codec_id, p_codec_info); /* Extract Vendor Codec Id */
+
+ *p_vendor_id = vendor_id;
+ *p_vendor_codec_id = vendor_codec_id;
+
+ BTUSB_INFO("Extracted Codec VendorId=0x%08x VendorCodecId=0x%04x\n", vendor_id, vendor_codec_id);
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_sbc_start
+**
+** Description Start AV SBC Stream
+**
+** Returns Status
+**
+*******************************************************************************/
+static int btusb_lite_av_sbc_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_encoder_ccb *p_encoder;
+ struct btusb_lite_av_scb *p_av_scb;
+ int nb_sbc_frames;
+ int rv;
+ int bitpool;
+ struct btusb_lite_av_sbc_param sbc_param;
+ int av_header_len;
+
+ /* Parse SBC Codec Info */
+ if (btusb_lite_av_parse_sbc_codec(&sbc_param, p_codec_cfg->codec_info) < 0)
+ {
+ BTUSB_ERR("Bad SBC Codec. Stream not started\n");
+ return -1;
+ }
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return -1;
+ }
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ /* Calculate the BitPool for this BitRate */
+ bitpool = btusb_lite_sbc_get_bitpool(&sbc_param, p_codec_cfg->bit_rate);
+ if (bitpool <= 0)
+ {
+ BTUSB_ERR("btusb_lite_sbc_get_bitpool return wrong bitpool=%d\n", bitpool);
+ return -1;
+ }
+ BTUSB_INFO("SBC BitPool=%d\n", bitpool);
+
+ p_av_cb->timestamp = 0; /* Reset TimeStamp */
+ p_av_cb->option = 0; /* No specific Option (RTP and Media Payload Header presents) */
+ p_av_cb->m_pt = AVDT_RTP_PAYLOAD_TYPE | A2D_MEDIA_CT_SBC;
+ p_av_cb->m_pt &= ~AVDT_MARKER_SET;
+
+ /* Calculate Packet Header Size (HCI, L2CAP, RTP and MediaPayloadHeader) */
+ p_av_cb->header_len = BTUSB_LITE_HCI_ACL_HDR_SIZE +
+ BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE +
+ BTUSB_LITE_SCMS_SIZE +
+ BTUSB_LITE_MEDIA_SIZE;
+ /* Calculate AV Header Size */
+ av_header_len = BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE +
+ BTUSB_LITE_SCMS_SIZE +
+ BTUSB_LITE_MEDIA_SIZE;
+
+ /* clear the congestion flag: full stack made it congested when opening */
+ p_av_scb->cong = FALSE;
+ p_av_scb->started = TRUE;
+
+ /* Get reference to AV's encoder */
+ p_encoder = &p_av_cb->encoder;
+
+ if (p_encoder->opened == 0)
+ {
+ /* Allocate an SBC Channel */
+ rv = btsbc_alloc();
+ if (rv < 0)
+ {
+ BTUSB_ERR("btsbc_alloc failed\n");
+ return -1;
+ }
+ p_encoder->opened = 1;
+ p_encoder->channel = rv;
+ p_encoder->type = A2D_MEDIA_CT_SBC;
+ }
+
+ /* Configure the SBC Channel */
+ rv = btsbc_config(p_encoder->channel,
+ sbc_param.frequency,
+ sbc_param.nb_blocks,
+ sbc_param.nb_subbands,
+ sbc_param.mode,
+ sbc_param.allocation,
+ (unsigned char)bitpool);
+ if (rv <= 0)
+ {
+ BTUSB_ERR("btsbc_config failed\n");
+ btsbc_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+
+ /* Save the calculated SBC Frame size */
+ p_encoder->encoded_frame_size = rv;
+ BTUSB_INFO("encoded_frame_size=%d\n", rv);
+
+ /* Configure the PCM Channel */
+ rv = btpcm_config(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_dev,
+ sbc_param.frequency,
+ sbc_param.mode==CODEC_MODE_MONO?1:2,
+ 16, /* SBC Encoder requires 16 bits per sample */
+ btusb_lite_av_pcm_cback);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_config failed\n");
+ return -1;
+ }
+
+ /* Calculate and save the PCM frame size */
+ p_encoder->pcm_frame_size = sbc_param.nb_blocks * sbc_param.nb_subbands;
+ BTUSB_INFO("pcm_frame_size=%d\n", p_encoder->pcm_frame_size);
+
+ /* Calculate nb_sbc_frames depending on MTU */
+ nb_sbc_frames = (p_av_cb->curr_mtu - av_header_len) / p_encoder->encoded_frame_size;
+
+ /* Calculate the size of the Payload */
+ p_av_cb->payload_len = nb_sbc_frames * p_encoder->encoded_frame_size;
+
+ BTUSB_INFO("nb_sbc_frames=%d payload_len=%d\n", nb_sbc_frames, p_av_cb->payload_len);
+
+ /* Start the PCM stream */
+ rv = btpcm_start(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_encoder->pcm_frame_size, nb_sbc_frames, 0);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_start failed\n");
+ return -1;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_STARTED;
+ return 0;
+}
+
+
+#ifdef BTUSB_LITE_SEC
+/*******************************************************************************
+**
+** Function btusb_lite_av_parse_vendor_codec
+**
+** Description Parse Vendor Id and Vendor Codec Id from Codec information
+**
+** Returns Status, VendorId and VendorCodecId
+**
+*******************************************************************************/
+static int btusb_lite_av_parse_sec_codec(struct btusb_lite_av_sec_param *p_sec_param,
+ UINT8 *p_codec_info)
+{
+ UINT8 byte;
+ UINT32 vendor_id;
+ UINT16 vendor_codec_id;
+
+ if (!p_codec_info || !p_sec_param)
+ {
+ BTUSB_ERR("Bad parameter\n");
+ return -1;
+ }
+
+ /* Extract/Ignore parameters already checked */
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract LOSC */
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Type */
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Codec Type */
+ STREAM_TO_UINT32(vendor_id, p_codec_info); /* Extract Vendor Id */
+ STREAM_TO_UINT16(vendor_codec_id, p_codec_info); /* Extract Vendor Codec Id */
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* SEC codec configuration */
+
+ /* Check Frequency */
+ switch(byte & BTSEC_FREQ_MASK)
+ {
+ case BTSEC_FREQ_48K:
+ p_sec_param->frequency = 48000;
+ break;
+ case BTSEC_FREQ_44K:
+ p_sec_param->frequency = 44100;
+ break;
+ case BTSEC_FREQ_32K:
+ p_sec_param->frequency = 32000;
+ break;
+ default:
+ BTUSB_ERR("SEC Frequency=0x%x unsupported\n", byte & BTSEC_FREQ_MASK);
+ return -1;
+ }
+
+ /* Check Mode */
+ switch(byte & BTSEC_MODE_MASK)
+ {
+ case BTSEC_MODE_MONO:
+ p_sec_param->mode = BTSEC_MODE_MONO;
+ break;
+ case BTSEC_MODE_STEREO:
+ p_sec_param->mode = BTSEC_MODE_STEREO;
+ break;
+ default:
+ BTUSB_ERR("SEC Mode=0x%x unsupported\n", byte & BTSEC_FREQ_MASK);
+ return -1;
+ }
+
+ BTUSB_INFO("SEC Frequency=%d Mode=%s\n", p_sec_param->frequency,
+ p_sec_param->mode == BTSEC_MODE_MONO?"Mono":"Stereo");
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_sec_start
+**
+** Description Start AV SBC Stream
+**
+** Returns Status
+**
+*******************************************************************************/
+static int btusb_lite_av_sec_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_encoder_ccb *p_encoder;
+ struct btusb_lite_av_scb *p_av_scb;
+ int nb_sec_frames;
+ int rv;
+ struct btusb_lite_av_sec_param sec_param;
+ int av_header_len;
+
+ /* Parse SBC Codec Info */
+ if (btusb_lite_av_parse_sec_codec(&sec_param, p_codec_cfg->codec_info) < 0)
+ {
+ BTUSB_ERR("Bad SEC Codec parameters. Stream not started\n");
+ return -1;
+ }
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return -1;
+ }
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ BTUSB_INFO("SEC Bitrate =%d\n", p_codec_cfg->bit_rate);
+
+ p_av_cb->timestamp = 0; /* Reset TimeStamp */
+ p_av_cb->option = BTUSB_LITE_AVDT_OPT_NO_MPH; /* No Media Payload Header */
+ p_av_cb->m_pt = AVDT_RTP_PAYLOAD_TYPE | A2D_MEDIA_CT_VEND;
+ p_av_cb->m_pt &= ~AVDT_MARKER_SET;
+
+ /* Calculate Packet Header Size (HCI, L2CAP, RTP) */
+ p_av_cb->header_len = BTUSB_LITE_HCI_ACL_HDR_SIZE +
+ BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE;
+ /* Calculate AV Header Size */
+ av_header_len = BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE;
+
+ /* Clear the congestion flag: full stack made it congested when opening */
+ p_av_scb->cong = FALSE;
+ p_av_scb->started = TRUE;
+
+ /* Get reference to AV's encoder */
+ p_encoder = &p_av_cb->encoder;
+
+ if (p_encoder->opened == 0)
+ {
+ /* Allocate a SEC Channel */
+ rv = btsec_alloc();
+ if (rv < 0)
+ {
+ BTUSB_ERR("btsec_alloc failed\n");
+ return -1;
+ }
+ p_encoder->opened = 1;
+ p_encoder->channel = rv;
+ p_encoder->type = A2D_MEDIA_CT_SEC;
+
+ }
+
+ /* Configure the SEC Channel */
+ rv = btsec_config(p_encoder->channel,
+ sec_param.frequency,
+ sec_param.mode,
+ p_codec_cfg->bit_rate * 1000);
+ if (rv <= 0)
+ {
+ BTUSB_ERR("btsec_config failed\n");
+ btsec_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+
+ /* Save the calculated SEC Frame size */
+ p_encoder->encoded_frame_size = rv;
+ BTUSB_INFO("encoded_frame_size=%d\n", rv);
+
+ /* Configure the PCM Channel */
+ rv = btpcm_config(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_dev,
+ sec_param.frequency,
+ sec_param.mode==BTSEC_MODE_MONO?1:2,
+ 16, /* SBC Encoder requires 16 bits per sample */
+ btusb_lite_av_pcm_cback);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_config failed\n");
+ btsec_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+
+ /* SEC requires a fixed number of PCM Samples */
+ p_encoder->pcm_frame_size = BTSEC_FRAME_SIZE;
+ BTUSB_INFO("pcm_frame_size=%d\n", p_encoder->pcm_frame_size);
+
+ /* Calculate nb_sbc_frames depending on MTU */
+ nb_sec_frames = (p_av_cb->curr_mtu - av_header_len) / p_encoder->encoded_frame_size;
+
+ /* Calculate the size of the Payload */
+ p_av_cb->payload_len = nb_sec_frames * p_encoder->encoded_frame_size;
+
+ BTUSB_INFO("nb_sec_frames=%d payload_len=%d\n", nb_sec_frames, p_av_cb->payload_len);
+
+ /* Start the PCM stream */
+ rv = btpcm_start(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_encoder->pcm_frame_size, nb_sec_frames, 0);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_start failed\n");
+ btsec_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_STARTED;
+ return 0;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_stop
+**
+** Description Start AV
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_stop(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int rv;
+
+ BTUSB_INFO("scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return;
+ }
+
+ p_av_cb->audio_open_cnt = audio_open_cnt;
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ p_av_cb->scb[scb_idx].started = FALSE;
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_STARTED)
+ {
+ BTUSB_ERR("BTPCM was not started\n");
+ return;
+ }
+
+ /* Stop the PCM stream */
+ rv = btpcm_stop(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_stop failed\n");
+ return;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CONFIGURED;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_suspend
+**
+** Description Suspend AV
+**
+** Returns none.
+**
+*******************************************************************************/
+void btusb_lite_av_suspend(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int rv;
+
+ BTUSB_INFO("scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return;
+ }
+
+ p_av_cb->audio_open_cnt = audio_open_cnt;
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ p_av_cb->scb[scb_idx].started = FALSE;
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_STARTED)
+ {
+ BTUSB_ERR("BTPCM was not started\n");
+ return;
+ }
+
+ /* Stop the PCM stream */
+ rv = btpcm_stop(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_stop failed\n");
+ return;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CONFIGURED;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_parse_sbc_codec
+**
+** Description Parse an SBC A2DP Codec
+**
+** Returns Status
+**
+*******************************************************************************/
+static int btusb_lite_av_parse_sbc_codec(struct btusb_lite_av_sbc_param *p_sbc, UINT8 *p_codec)
+{
+ UINT8 byte;
+ unsigned char codec_freq;
+ unsigned char codec_blocks;
+ unsigned char codec_subbands;
+ unsigned char codec_mode;
+ unsigned char codec_alloc;
+ unsigned char bitpool_min;
+ unsigned char bitpool_max;
+
+ if (p_sbc == NULL)
+ {
+ BTUSB_ERR("p_sbc is NULL\n");
+ return -1;
+ }
+
+ /* Extract LOSC */
+ byte = *p_codec++;
+ if (byte != CODEC_SBC_LOSC)
+ {
+ BTUSB_ERR("Bad SBC LOSC=%d", byte);
+ return -1;
+ }
+
+ p_codec++; /* Ignore MT */
+
+ /* Extract Codec Type */
+ byte = *p_codec++;
+ if (byte != A2D_MEDIA_CT_SBC)
+ {
+ BTUSB_ERR("Bad SBC codec type=%d", byte);
+ return -1;
+ }
+
+ /* Extract Freq & Mode */
+ byte = *p_codec++;
+ codec_freq = byte & CODEC_SBC_FREQ_MASK;
+ codec_mode = byte & CODEC_MODE_MASK;
+
+ /* Extract NbBlock NbSubBand and Alloc Method */
+ byte = *p_codec++;
+ codec_blocks = byte & CODEC_SBC_BLOCK_MASK;
+ codec_subbands = byte & CODEC_SBC_NBBAND_MASK;
+ codec_alloc = byte & CODEC_SBC_ALLOC_MASK;
+
+ bitpool_min = *p_codec++;
+ bitpool_max = *p_codec++;
+
+ switch(codec_freq)
+ {
+ case CODEC_SBC_FREQ_48:
+ BTUSB_INFO("SBC Freq=48K\n");
+ p_sbc->frequency = 48000;
+ break;
+ case CODEC_SBC_FREQ_44:
+ BTUSB_INFO("SBC Freq=44.1K\n");
+ p_sbc->frequency = 44100;
+ break;
+ case CODEC_SBC_FREQ_32:
+ BTUSB_INFO("SBC Freq=32K\n");
+ p_sbc->frequency = 32000;
+ break;
+ case CODEC_SBC_FREQ_16:
+ BTUSB_INFO("SBC Freq=16K\n");
+ p_sbc->frequency = 16000;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC Freq=%d\n", codec_freq);
+ return -1;
+ }
+
+ switch(codec_mode)
+ {
+ case CODEC_MODE_JOIN_STEREO:
+ BTUSB_INFO("SBC Join Stereo\n");
+ p_sbc->mode = CODEC_MODE_JOIN_STEREO;
+ break;
+ case CODEC_MODE_STEREO:
+ BTUSB_INFO("SBC Stereo\n");
+ p_sbc->mode = CODEC_MODE_STEREO;
+ break;
+ case CODEC_MODE_DUAL:
+ BTUSB_INFO("SBC Dual\n");
+ p_sbc->mode = CODEC_MODE_DUAL;
+ break;
+ case CODEC_MODE_MONO:
+ BTUSB_INFO("SBC Mono\n");
+ p_sbc->mode = CODEC_MODE_MONO;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC mode=%d\n", codec_mode);
+ return -1;
+ }
+
+ switch(codec_blocks)
+ {
+ case CODEC_SBC_BLOCK_16:
+ BTUSB_INFO("SBC Block=16\n");
+ p_sbc->nb_blocks = 16;
+ break;
+ case CODEC_SBC_BLOCK_12:
+ BTUSB_INFO("SBC Block=12\n");
+ p_sbc->nb_blocks = 12;
+ break;
+ case CODEC_SBC_BLOCK_8:
+ BTUSB_INFO("SBC Block=8\n");
+ p_sbc->nb_blocks = 8;
+ break;
+ case CODEC_SBC_BLOCK_4:
+ BTUSB_INFO("SBC Block=4\n");
+ p_sbc->nb_blocks = 4;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC Block=%d\n", codec_blocks);
+ return -1;
+ }
+
+ switch(codec_subbands)
+ {
+ case CODEC_SBC_NBBAND_8:
+ BTUSB_INFO("SBC NbSubBand=8\n");
+ p_sbc->nb_subbands = 8;
+ break;
+ case CODEC_SBC_NBBAND_4:
+ BTUSB_INFO("SBC NbSubBand=4\n");
+ p_sbc->nb_subbands = 4;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC NbSubBand=%d\n", codec_blocks);
+ return -1;
+ }
+
+ switch(codec_alloc)
+ {
+ case CODEC_SBC_ALLOC_LOUDNESS:
+ BTUSB_INFO("SBC Loudness\n");
+ p_sbc->allocation = CODEC_SBC_ALLOC_LOUDNESS;
+ break;
+ case CODEC_SBC_ALLOC_SNR:
+ BTUSB_INFO("SBC SNR\n");
+ p_sbc->allocation = CODEC_SBC_ALLOC_SNR;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC AllocMethod=%d\n", codec_blocks);
+ return -1;
+ }
+
+ BTUSB_INFO("BitpoolMin=%d BitpoolMax=%d\n", bitpool_min, bitpool_max);
+
+ p_sbc->bitpool_min = bitpool_min;
+ p_sbc->bitpool_max = bitpool_max;
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_sbc_get_bitpool
+ **
+ ** Description Calculate the BitPool for a specified BitRate (and other parameters)
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static int btusb_lite_sbc_get_bitpool(struct btusb_lite_av_sbc_param *p_sbc_param, int target_bitrate)
+{
+ int nb_channels;
+ int frame_length;
+ int bitpool = p_sbc_param->bitpool_max + 1;
+ int bitrate;
+
+ /* Required number of channels */
+ if (p_sbc_param->mode == CODEC_MODE_MONO)
+ nb_channels = 1;
+ else
+ nb_channels = 2;
+
+ target_bitrate *= 1000; /* Bitrate from app is in Kbps */
+
+ do
+ {
+ bitpool--; /* Reduce Bit Pool by one */
+
+ /* Calculate common SBC Frame length */
+ frame_length = 4 + (4 * p_sbc_param->nb_subbands * nb_channels) / 8;
+
+ /* Add specific SBC Frame length (depending on mode) */
+ switch(p_sbc_param->mode)
+ {
+ case CODEC_MODE_MONO:
+ case CODEC_MODE_DUAL:
+ frame_length += (p_sbc_param->nb_blocks * nb_channels * bitpool) / 8;
+ break;
+ case CODEC_MODE_JOIN_STEREO:
+ frame_length += (p_sbc_param->nb_subbands + p_sbc_param->nb_blocks * bitpool) / 8;
+ break;
+ case CODEC_MODE_STEREO:
+ frame_length += (p_sbc_param->nb_blocks * bitpool) / 8;
+ break;
+ }
+
+ /* Calculate bit rate */
+ bitrate = 8 * frame_length * p_sbc_param->frequency / p_sbc_param->nb_subbands / p_sbc_param->nb_blocks;
+
+ } while (bitrate > target_bitrate); /* While bitrate is too big */
+
+ BTUSB_INFO("final bitpool=%d frame_length=%d bitrate=%d\n", bitpool, frame_length, bitrate);
+
+ return (int)bitpool;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_av_pcm_cback
+ **
+ ** Description BTUSB Lte AV PCM Callback function.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_av_pcm_cback(int pcm_stream, void *p_dev, void *p_data,
+ int nb_pcm_frames)
+{
+ struct btusb_lite_av_cb *p_av_cb;
+ int pcm_frame_size_byte;
+ void *p_dest;
+ int written_enc_size;
+ struct btusb_lite_encoder_ccb *p_encoder;
+
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("Null _p_dev\n");
+ return;
+ }
+
+ if (p_data == NULL)
+ {
+ BTUSB_ERR("Null p_data\n");
+ return;
+ }
+
+ if (pcm_stream != BTUSB_LITE_AV_PCM_CHANNEL)
+ {
+ BTUSB_ERR("Bad stream=%d\n", pcm_stream);
+ return;
+ }
+
+ /* Get Reference on the SBC Stream (which is the same than the Encoder channel) */
+ p_av_cb = &((struct btusb_cb *)p_dev)->lite_cb.av;
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_STARTED)
+ {
+ BTUSB_ERR("BTPCM is not started\n");
+ btpcm_stop(pcm_stream);
+ return;
+ }
+
+ /* Get reference to AV's encoder */
+ p_encoder = &p_av_cb->encoder;
+
+ /* Calculate the size (in byte) of an Input PCM buffer (holding one encoded frame) */
+ pcm_frame_size_byte = p_av_cb->encoder.pcm_frame_size;
+ pcm_frame_size_byte *= 2; /* Stereo */
+ pcm_frame_size_byte *= 2; /* 16 bits per sample */
+
+ /* Sanity Check */
+ if (pcm_frame_size_byte == 0)
+ {
+ BTUSB_ERR("Bad PCM Frame size=%d\n", pcm_frame_size_byte);
+ return;
+ }
+
+ /* While received buffer is not empty */
+ while (nb_pcm_frames)
+ {
+ /* Check if there are enough remaining frames in the buffer */
+ if ((nb_pcm_frames * 2 * 2) < pcm_frame_size_byte)
+ {
+ BTUSB_ERR("Bad nb_pcm_frames=%d\n", nb_pcm_frames);
+ return;
+ }
+
+ /* If no working buffer allocated */
+ if (p_av_cb->p_buf_working == NULL)
+ {
+ /* Get a buffer from the pool */
+ p_av_cb->p_buf_working = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + p_av_cb->header_len + p_av_cb->payload_len);
+ if(unlikely(p_av_cb->p_buf_working == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer - sent fail\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_av_cb->p_buf_working) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_av_cb->p_buf_working);
+ return;
+ }
+
+ /* Skip headers */
+ p_av_cb->p_buf_working->offset = p_av_cb->header_len;
+ p_av_cb->p_buf_working->len = 0;
+ p_av_cb->p_buf_working->layer_specific = 0; /* Used to store the number of Encoded Frames */
+ }
+
+ /* Fill the ACL Packet with SBC Frames */
+ do
+ {
+ /* Get Write address */
+ p_dest = (UINT8 *)(p_av_cb->p_buf_working + 1) + p_av_cb->p_buf_working->offset +
+ p_av_cb->p_buf_working->len;
+
+ if (p_encoder->type == A2D_MEDIA_CT_SBC)
+ {
+ /* Encode one PCM frame with SBC Encoder*/
+ btsbc_encode(p_encoder->channel,
+ /* If Mute => Zero filled PCM sample*/
+ /* Otherwise => regular PCM data */
+ pcm0_mute?btusb_lite_silence_pcm:p_data,
+ pcm_frame_size_byte,
+ p_dest, /* SBC Output buffer */
+ p_av_cb->encoder.encoded_frame_size, /* Expected Output SBC frame size */
+ &written_enc_size);
+ }
+#ifdef BTUSB_LITE_SEC
+ else if (p_encoder->type == A2D_MEDIA_CT_SEC)
+ {
+ /* Encode one PCM frame with SEC Encoder*/
+ written_enc_size = btsec_encode(p_av_cb->encoder.channel,
+ /* If Mute => Zero filled PCM sample*/
+ /* Otherwise => regular PCM data */
+ pcm0_mute?btusb_lite_silence_pcm:p_data,
+ pcm_frame_size_byte,
+ p_dest, /* SEC Output buffer */
+ p_encoder->encoded_frame_size);/* Expected Output SEC frame size */
+ }
+#endif
+ if (written_enc_size != p_av_cb->encoder.encoded_frame_size)
+ {
+ BTUSB_ERR("Bad Encoded Fame lenght=%d (expected=%d)\n",
+ written_enc_size, p_av_cb->encoder.encoded_frame_size);
+ }
+
+ /* Update Encoded packet length */
+ p_av_cb->p_buf_working->len += (UINT16)p_av_cb->encoder.encoded_frame_size;
+
+ /* One more Encoded Frame */
+ p_av_cb->p_buf_working->layer_specific++;
+
+ p_data += pcm_frame_size_byte; /* Jump to the next PCM sample */
+ nb_pcm_frames -= pcm_frame_size_byte / 4; /* Update number of remaining samples */
+
+ } while (nb_pcm_frames &&
+ (p_av_cb->p_buf_working->layer_specific < A2D_SBC_HDR_NUM_MSK) &&
+ ((p_av_cb->p_buf_working->len + p_av_cb->encoder.encoded_frame_size) < p_av_cb->curr_mtu));
+
+ /* If no more room to store an encoded frame */
+ if (p_av_cb->encoder.encoded_frame_size > (p_av_cb->curr_mtu - p_av_cb->p_buf_working->len))
+ {
+ /* For AV channel, send the packet */
+ btusb_lite_av_send_packet((struct btusb_cb *)p_dev, p_av_cb->p_buf_working);
+
+ /* A new working buffer must be allocated */
+ p_av_cb->p_buf_working = NULL;
+ }
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_av_send_packet
+ **
+ ** Description Send a new BAV packet to the controller
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_av_send_packet(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ struct btusb_lite_av_cb *p_av_cb;
+ struct btusb_lite_av_scb *p_av_scb;
+ int stream;
+ int nb_started_streams;
+ BT_HDR *p_msg_dup;
+
+ if (!p_dev || !p_msg)
+ {
+ BTUSB_ERR("Bad reference p_dev=%p p_msg=%p\n", p_dev, p_msg);
+ return;
+ }
+
+ /* Sanity */
+ if (p_msg->len == 0)
+ {
+ BTUSB_ERR("Length is 0=%d\n", p_msg->len);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+
+ /* Get Reference on the AV Streams */
+ p_av_cb = &((struct btusb_cb *)p_dev)->lite_cb.av;
+
+ /* Update TimeStamp */
+ p_av_cb->timestamp += p_msg->layer_specific * p_av_cb->encoder.pcm_frame_size;
+
+ nb_started_streams = 0;
+ /* Count how many AV stream are started */
+ for (stream = 0, p_av_scb = p_av_cb->scb ; stream < BTA_AV_NUM_STRS ; stream++, p_av_scb++)
+ {
+ if (p_av_scb->started)
+ {
+ nb_started_streams++; /* One more started stream */
+ }
+ }
+
+ if (nb_started_streams == 0)
+ {
+ BTUSB_ERR("No Started AV stream found\n");
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ else if (nb_started_streams == 1)
+ {
+ p_msg_dup = NULL;
+ }
+ else
+ {
+ /*
+ * Duplicate the AV packet
+ */
+ /* Get a buffer from the pool */
+ p_msg_dup = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + p_msg->offset + p_msg->offset);
+ if(p_msg_dup)
+ {
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg_dup) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg_dup);
+ p_msg_dup = NULL; /* Do not use this buffer */
+ }
+ if(p_msg_dup)
+ {
+ /* Duplicate all the data (Header, and payload */
+ memcpy(p_msg_dup, p_msg, sizeof(BT_HDR) + p_msg->offset + p_msg->offset);
+ }
+ }
+ if (nb_started_streams > 2)
+ {
+ BTUSB_ERR("nb_started_streams=%d force it to 2\n", nb_started_streams);
+ nb_started_streams = 2;
+ }
+ }
+
+ /* For every AV stream Started */
+ for (stream = 0, p_av_scb = p_av_cb->scb ; stream < BTA_AV_NUM_STRS ; stream++, p_av_scb++)
+ {
+ if (p_av_scb->started)
+ {
+ if (p_msg)
+ {
+ /* Send the original packet to AVDT */
+ btusb_lite_avdt_send(p_dev, p_msg, p_av_scb->avdt_handle,
+ p_av_cb->m_pt, p_av_cb->option, p_av_cb->timestamp);
+ p_msg = NULL;
+ }
+ else if (p_msg_dup)
+ {
+ /* Send the duplicated packet to AVDT */
+ btusb_lite_avdt_send(p_dev, p_msg_dup, p_av_scb->avdt_handle,
+ p_av_cb->m_pt, p_av_cb->option, p_av_cb->timestamp);
+ p_msg_dup = NULL;
+ }
+ else
+ {
+ BTUSB_ERR("No AV data to send for AV stream=%d \n", stream);
+ }
+ }
+ }
+}
+
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_avdt.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_avdt.c.svn-base
new file mode 100755
index 0000000..46cf0ce
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_avdt.c.svn-base
@@ -0,0 +1,426 @@
+/*
+ *
+ * btusb_lite_avdt.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include "btusb.h"
+#include "bd.h"
+
+/*
+ * Definitions
+ */
+#define AVDT_MULTIPLEXING FALSE
+
+
+/*
+ * Local functions
+ */
+static struct btusb_lite_avdt_scb *btusb_lite_avdt_allocate_scb(struct btusb_cb *p_dev);
+static void btusb_lite_avdt_free_scb(struct btusb_cb *p_dev, struct btusb_lite_avdt_scb *p_scb_free);
+static struct btusb_lite_avdt_ccb *btusb_lite_avdt_allocate_ccb(struct btusb_cb *p_dev);
+static void btusb_lite_avdt_free_ccb(struct btusb_cb *p_dev, struct btusb_lite_avdt_ccb *p_ccb_free);
+static UINT8 *btusb_lite_avdt_write_rtp_header(UINT8 *p_data, UINT8 m_pt, UINT16 seq_number, UINT32 timestamp, UINT32 ssrc);
+
+
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_scb_by_hdl
+**
+** Description Given an scb handle (or seid), return a pointer to the scb.
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+struct btusb_lite_avdt_scb *btusb_lite_avdt_scb_by_hdl(struct btusb_cb *p_dev, UINT8 handle)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 scb;
+
+ p_scb = &p_dev->lite_cb.avdt.scb[0];
+ for(scb = 0; scb < AVDT_NUM_SEPS; scb++, p_scb++ )
+ {
+ if((p_scb->allocated) &&
+ (p_scb->handle == handle))
+ return(p_scb);
+ }
+ return(NULL);
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_init_scb
+**
+** Description allocate and initialize SCB/CCB with received sync info
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_init_scb(struct btusb_cb *p_dev, tAVDT_SCB_SYNC_INFO *p_scb_info)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ struct btusb_lite_avdt_ccb *p_ccb;
+
+ if((p_scb = btusb_lite_avdt_allocate_scb(p_dev)) == NULL)
+ {
+ BTUSB_ERR("No SCB for handle %d\n", p_scb_info->handle);
+ return AVDT_SYNC_FAILURE;
+ }
+ else
+ {
+ if((p_ccb = btusb_lite_avdt_allocate_ccb(p_dev)) == NULL)
+ {
+ BTUSB_ERR("No CCB for handle %d\n", p_scb_info->handle);
+ p_scb->allocated = FALSE;
+ return AVDT_SYNC_FAILURE;
+ }
+ else
+ {
+ memcpy(p_ccb->peer_addr, p_scb_info->peer_addr, BD_ADDR_LEN);
+ p_ccb->lcid = p_scb_info->local_cid;
+ p_ccb->peer_mtu = p_scb_info->peer_mtu;
+#if AVDT_MULTIPLEXING == TRUE
+ GKI_init_q(&p_scb->frag_q);
+#endif
+ p_scb->handle = p_scb_info->handle;
+ p_scb->mux_tsid_media = p_scb_info->mux_tsid_media;
+ p_scb->media_seq = p_scb_info->media_seq;
+ p_scb->p_ccb = p_ccb;
+ BTUSB_INFO("Allocated SCB/CCB for handle %d\n", p_scb_info->handle);
+ }
+ }
+ return AVDT_SYNC_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_remove_scb
+**
+** Description deallocate SCB and CCB
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_remove_scb(struct btusb_cb *p_dev, UINT8 handle, tAVDT_SCB_SYNC_INFO *p_scb_info)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+
+ if((p_scb = btusb_lite_avdt_scb_by_hdl(p_dev, handle)) == NULL)
+ {
+ BTUSB_ERR("No SCB for handle %d\n", handle);
+ return AVDT_SYNC_FAILURE;
+ }
+ else
+ {
+ if (p_scb_info)
+ {
+ p_scb_info->handle = p_scb->handle;
+ p_scb_info->media_seq = p_scb->media_seq;
+ }
+ /* Free CCB first */
+ btusb_lite_avdt_free_ccb(p_dev, p_scb->p_ccb);
+ /* Free SCB */
+ btusb_lite_avdt_free_scb(p_dev, p_scb);
+
+ return AVDT_SYNC_SUCCESS;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_allocate_ccb
+**
+** Description allocate CCB in lite stack
+**
+** Returns pointer of CCB
+**
+*******************************************************************************/
+static struct btusb_lite_avdt_ccb *btusb_lite_avdt_allocate_ccb(struct btusb_cb *p_dev)
+{
+ struct btusb_lite_avdt_ccb *p_ccb;
+ UINT8 ccb;
+
+ p_ccb = &p_dev->lite_cb.avdt.ccb[0];
+ for(ccb = 0; ccb < AVDT_NUM_LINKS; ccb++, p_ccb++)
+ {
+ if (!p_ccb->allocated)
+ {
+ BTUSB_INFO("CCB=%d allocated\n", ccb);
+ memset(p_ccb, 0, sizeof(struct btusb_lite_avdt_ccb));
+ p_ccb->allocated = TRUE;
+ return(p_ccb);
+ }
+ }
+ return(NULL);
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_free_ccb
+**
+** Description Free CCB in lite stack
+**
+** Returns None
+**
+*******************************************************************************/
+static void btusb_lite_avdt_free_ccb(struct btusb_cb *p_dev, struct btusb_lite_avdt_ccb *p_ccb_free)
+{
+ struct btusb_lite_avdt_ccb *p_ccb;
+ UINT8 ccb;
+
+ p_ccb = &p_dev->lite_cb.avdt.ccb[0];
+ for(ccb = 0; ccb < AVDT_NUM_LINKS; ccb++, p_ccb++)
+ {
+ if (p_ccb == p_ccb_free)
+ {
+ /* Sanity */
+ if (!p_ccb_free->allocated)
+ {
+ BTUSB_ERR("CCB=%d was not allocated\n", ccb);
+ }
+ BTUSB_INFO("CCB=%d freed\n", ccb);
+ p_ccb_free->allocated = FALSE;
+ return;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_allocate_scb
+**
+** Description allocate SCB in lite stack
+**
+** Returns pointer of SCB
+**
+*******************************************************************************/
+static struct btusb_lite_avdt_scb *btusb_lite_avdt_allocate_scb(struct btusb_cb *p_dev)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 scb;
+
+ p_scb = &p_dev->lite_cb.avdt.scb[0];
+ for(scb = 0; scb < AVDT_NUM_SEPS; scb++, p_scb++)
+ {
+ if(!p_scb->allocated)
+ {
+ BTUSB_INFO("SCB=%d allocated\n", scb);
+ memset(p_scb, 0, sizeof(struct btusb_lite_avdt_scb));
+ p_scb->allocated = TRUE;
+ return(p_scb);
+ }
+ }
+ return(NULL);
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_free_scb
+**
+** Description Free SCB in lite stack
+**
+** Returns None
+**
+*******************************************************************************/
+static void btusb_lite_avdt_free_scb(struct btusb_cb *p_dev, struct btusb_lite_avdt_scb *p_scb_free)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 scb;
+
+ p_scb = &p_dev->lite_cb.avdt.scb[0];
+ for(scb = 0; scb < AVDT_NUM_SEPS; scb++, p_scb++)
+ {
+ if (p_scb == p_scb_free)
+ {
+ /* Sanity */
+ if (!p_scb_free->allocated)
+ {
+ BTUSB_ERR("SCB=%d was not allocated\n", scb);
+ }
+ BTUSB_INFO("SCB=%d freed\n", scb);
+ p_scb_free->allocated = FALSE;
+ return;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_send
+**
+** Description AVDT packet send
+**
+** Returns None
+**
+*******************************************************************************/
+void btusb_lite_avdt_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT8 avdt_handle,
+ UINT8 m_pt, UINT8 option, UINT32 timestamp)
+{
+ UINT8 *p_data;
+ struct btusb_lite_avdt_scb *p_avdt_scb;
+ struct btusb_lite_avdt_ccb *p_avdt_ccb;
+
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("p_dev is NULL\n");
+ if (p_msg)
+ GKI_freebuf(p_msg);
+ return;
+ }
+
+ if (p_msg == NULL)
+ {
+ BTUSB_ERR("p_msg is NULL\n");
+ return;
+ }
+
+ /* Find the AVDT SCB with this handle */
+ p_avdt_scb = btusb_lite_avdt_scb_by_hdl(p_dev, avdt_handle);
+ if (p_avdt_scb == NULL)
+ {
+ BTUSB_ERR("No AVDT SCB stream found\n");
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+
+ /* Get the associated AVDT CCB */
+ p_avdt_ccb = p_avdt_scb->p_ccb;
+ if (p_avdt_ccb == NULL)
+ {
+ BTUSB_ERR("No AVDT CCB stream found\n");
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+
+ /* Write the Media Payload Header if needed */
+ if ((option & BTUSB_LITE_AVDT_OPT_NO_MPH) == 0)
+ {
+ if (p_msg->offset < BTUSB_LITE_MEDIA_SIZE)
+ {
+ BTUSB_ERR("Offset too small=%d for MediaPayloadHeader\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ p_msg->offset -= BTUSB_LITE_MEDIA_SIZE;
+ p_msg->len += BTUSB_LITE_MEDIA_SIZE;
+ /* Get write address */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ /* Write Media Payload Header (Number of SBC Frames) */
+ UINT8_TO_BE_STREAM(p_data, p_msg->layer_specific & A2D_SBC_HDR_NUM_MSK);
+ }
+
+ /* Write the SCMS content Protection Header if needed */
+ if (p_avdt_scb->scms.enable)
+ {
+ if (p_msg->offset < BTUSB_LITE_SCMS_SIZE)
+ {
+ BTUSB_ERR("Offset too small=%d for CP Header\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ p_msg->offset -= BTUSB_LITE_SCMS_SIZE;
+ p_msg->len += BTUSB_LITE_SCMS_SIZE;
+ /* Get write address */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ /* Write Media Payload Header (Number of SBC Frames) */
+ UINT8_TO_BE_STREAM(p_data, p_avdt_scb->scms.header);
+ }
+
+ /* Write the RTP Header if needed */
+ if ((option & BTUSB_LITE_AVDT_OPT_NO_RTP) == 0)
+ {
+ if (p_msg->offset < BTUSB_LITE_RTP_SIZE)
+ {
+ BTUSB_ERR("Offset too small=%d for RTP Header\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ p_msg->offset -= BTUSB_LITE_RTP_SIZE;
+ p_msg->len += BTUSB_LITE_RTP_SIZE;
+ /* Get write address */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ /* Write RTP Header */
+ p_data = btusb_lite_avdt_write_rtp_header(p_data, m_pt, p_avdt_scb->media_seq, timestamp, 0);
+ }
+
+ p_avdt_scb->media_seq++; /* Increment Sequence number */
+
+ /* Request L2CAP to send this packet */
+ btusb_lite_l2c_send(p_dev, p_msg, p_avdt_ccb->lcid);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_avdt_write_rtp_header
+ **
+ ** Description Write A2DP RTP Header
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_avdt_write_rtp_header(UINT8 *p_data, UINT8 m_pt, UINT16 seq_number,
+ UINT32 timestamp, UINT32 ssrc)
+{
+ /* Write RTP Header */
+ UINT8_TO_BE_STREAM(p_data, AVDT_MEDIA_OCTET1); /* Version, Padding, Ext, CSRC */
+ UINT8_TO_BE_STREAM(p_data, m_pt); /* Marker & Packet Type */
+ UINT16_TO_BE_STREAM(p_data, seq_number); /* Sequence number */
+ UINT32_TO_BE_STREAM(p_data, timestamp); /* TimeStamp */
+ UINT32_TO_BE_STREAM(p_data, ssrc); /* SSRC */
+ return p_data;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_cp_set_scms
+**
+** Description Set SCMS Content Protection for a channel
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_cp_set_scms(struct btusb_cb *p_dev, UINT8 avdt_handle,
+ BOOLEAN enable, UINT8 scms_hdr)
+{
+ struct btusb_lite_avdt_scb *p_avdt_scb;
+
+ /* Find the AVDT SCB with this handle */
+ p_avdt_scb = btusb_lite_avdt_scb_by_hdl(p_dev, avdt_handle);
+ if (p_avdt_scb == NULL)
+ {
+ BTUSB_ERR("No AVDT SCB stream found\n");
+ return AVDT_SYNC_FAILURE;
+ }
+
+ BTUSB_INFO("btusb_lite_avdt_cp_set_scms handle=0x%x enable=%d header=0x%x\n",
+ avdt_handle, enable, scms_hdr);
+
+ p_avdt_scb->scms.enable = enable;
+ p_avdt_scb->scms.header = scms_hdr;
+
+ return AVDT_SYNC_SUCCESS;
+
+}
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_hci.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_hci.c.svn-base
new file mode 100755
index 0000000..83835d9
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_hci.c.svn-base
@@ -0,0 +1,440 @@
+/*
+ *
+ * btusb_lite_hci.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include "btusb.h"
+
+/*
+ * Definitions
+ */
+#define BTUSB_LITE_HCI_NUM_CMD 0x01 /* HCI Num Command */
+
+/* HCI Definitions for the NumberOfCompletePacket Event */
+#define BTUSB_LITE_HCI_NOCP_HCI_LEN 7 /* HCI Length of the NumOfCpltPacket Event */
+#define BTUSB_A2DP_NOCP_LEN 5 /* Length of the NumOfCpltPacket Param */
+
+/*
+ * Local functions
+ */
+static UINT8 *btusb_lite_hci_write_acl_header(UINT8 *p_data, UINT16 con_hdl, UINT16 length);
+static UINT8 *btusb_lite_hci_write_evt_header(UINT8 *p_data, UINT8 event, UINT8 length);
+
+static int btusb_lite_hci_transport_pause_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static int btusb_lite_hci_transport_resume_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_hci_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len);
+static int btusb_lite_hci_nocp_event_hdlr(struct btusb_cb *p_dev, UINT8 *p_data, int length);
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_acl_send
+ **
+ ** Description Send an ACL packet to HCI
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+int btusb_lite_hci_acl_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 con_hdl)
+{
+ UINT8 *p_data;
+
+ /* Sanity */
+ if (p_msg->offset < BTUSB_LITE_HCI_ACL_HDR_SIZE)
+ {
+ BTUSB_ERR("offset too small=%d\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return -1;
+ }
+
+ /* Decrement offset to add headers */
+ p_msg->offset -= BTUSB_LITE_HCI_ACL_HDR_SIZE;
+
+ /* Get address of the HCI Header */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ /* Write L2CAP Header (length field is SBC Frames + RTP/A2DP/Media Header) */
+ p_data = btusb_lite_hci_write_acl_header(p_data, con_hdl, p_msg->len);
+
+ /* Increment length */
+ p_msg->len += BTUSB_LITE_HCI_ACL_HDR_SIZE;
+
+ /* Add this ACL data in the USB Tx queue and notify the btusb_tx_task to process */
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ /* Wake up tasklet (with High priority) */
+ tasklet_schedule(&p_dev->tx_task);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_cmd_filter
+ **
+ ** Description Check if the Sent HCI Command need to be handled/caught (not
+ ** sent to BT controller).
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+int btusb_lite_hci_cmd_filter(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p;
+ UINT8 hci_type;
+ UINT16 opcode;
+ int rv = 1; /* HCI command not handled by default */
+
+ p = (UINT8 *)(p_msg + 1);
+
+ STREAM_TO_UINT8(hci_type, p); /* Extract HCI Type */
+
+ if (hci_type != HCIT_TYPE_COMMAND)
+ {
+ /* This is not an HCI Command */
+ return rv; /* Send it to BT Controller */
+ }
+
+ STREAM_TO_UINT16(opcode, p); /* Extract HCI Command OpCode */
+
+ switch(opcode)
+ {
+ case HCI_BRCM_PAUSE_TRANSPORT:
+ rv = btusb_lite_hci_transport_pause_hndl(p_dev, p_msg);
+ break;
+
+ case HCI_BRCM_TRANSPORT_RESUME:
+ /* Call the function in charge of filtering UIPC Over HCI VSC */
+ rv = btusb_lite_hci_transport_resume_hndl(p_dev, p_msg);
+ break;
+
+ /* Add here other HCI Command OpCodes to filter */
+ default:
+ break;
+ /* Do not filter other HCI Command OpCodes */
+ }
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_transport_pause_hndl
+ **
+ ** Description Handles the HCI Transport Pause VSC.
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+static int btusb_lite_hci_transport_pause_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 param[sizeof(UINT8)];
+ UINT8 *p_param = param;
+
+ BTUSB_INFO("HCI_TransportPause VSC caught\n");
+
+ UINT8_TO_STREAM(p_param, HCI_SUCCESS);
+
+ btusb_lite_hci_cmd_cplt_evt_send(p_dev, HCI_BRCM_PAUSE_TRANSPORT, param,
+ p_param - param);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_transport_resume_hndl
+ **
+ ** Description Handles the HCI Transport Pause VSC.
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+static int btusb_lite_hci_transport_resume_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 param[sizeof(UINT8)];
+ UINT8 *p_param = param;
+
+ BTUSB_INFO("HCI_TransportResume VSC caught\n");
+
+ UINT8_TO_STREAM(p_param, HCI_SUCCESS);
+
+ btusb_lite_hci_cmd_cplt_evt_send(p_dev, HCI_BRCM_TRANSPORT_RESUME, param,
+ p_param - param);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_event_filter
+ **
+ ** Description Filter HCI Events received from BT Controller.
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+int btusb_lite_hci_event_filter(struct btusb_cb *p_dev, UINT8 *p_data, int length)
+{
+#if 0
+ BT_HDR *p_msg;
+ UINT8 *p;
+ UINT16 size;
+#endif
+
+ /* Check if HCI is over IPC */
+ if (btusb_lite_is_hci_over_ipc(p_dev) == 0)
+ {
+ /* If it is not, the event have to be sent through regular HCI */
+ return 1;
+ }
+
+ /* Check if the Event is a NumberOfCompletePacket Event */
+ if (btusb_lite_hci_nocp_event_hdlr(p_dev, p_data, length) == 0)
+ {
+ return 0; /* Do not Send this event to user space (we handled it) */
+ }
+
+ /* TODO: check if CSB VSE */
+
+ return 1;
+
+#if 0
+
+ /* Add size of both UIPC Length and Event header */
+ size = length + sizeof(UINT16) + sizeof(UINT16);
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return 0;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = 0;
+ p_msg->len = size;
+
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ UINT16_TO_STREAM(p, length + sizeof(UINT16)); /* UIPC Length */
+ UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_EVT); /* UIPC Event */
+ UINT8_TO_STREAM(p, hci_event); /* Write back the HCI Event (we already read it) */
+ ARRAY_TO_STREAM(p, p_data, length - 1); /* Copy Event data */
+
+ /* Send message to User Space */
+ btusb_lite_ipc_sent_to_user(p_dev, p_msg);
+
+ return 0; /* Event handled by the Stack Lite. No need to send it to HCI */
+#endif
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_nocp_event_hdlr
+ **
+ ** Description Check if the received HCI Event is A NumberOfdComplete Evt
+ ** sub opcode for a Started BAV stream.
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+static int btusb_lite_hci_nocp_event_hdlr(struct btusb_cb *p_dev, UINT8 *p_data, int length)
+{
+ UINT8 nb_handle;
+ UINT16 con_hdl;
+ UINT16 num_cplt_pck;
+ UINT8 byte;
+ UINT8 *p_save;
+ int send_to_user;
+ UINT16 num_cplt_pck_caugth;
+
+ /* We are waiting for an Event of, at least, 7 bytes */
+ if (length < BTUSB_LITE_HCI_NOCP_HCI_LEN)
+ {
+ return 1; /* This is not a NOCP. Send this event to user space */
+ }
+
+ /* Extract Event */
+ STREAM_TO_UINT8(byte, p_data);
+
+ /* Check if it's a NumberOfCompletePacket Event */
+ if (byte != HCI_NUM_COMPL_DATA_PKTS_EVT)
+ {
+ return 1; /* This is not a NOCP. Send this event to user space */
+ }
+
+ /* Extract Parameter Length */
+ STREAM_TO_UINT8(byte, p_data);
+
+ /* Extract Number Of Handle */
+ STREAM_TO_UINT8(nb_handle, p_data);
+
+ /* Sanity */
+ if (byte != (1 + (2 + 2) * nb_handle))
+ {
+ BTUSB_ERR("Unexpected Evt Size=%d vs.NumberOfHandle=%d\n", byte, nb_handle);
+ return 1; /* This is not a NOCP. Send this event to user space */
+ }
+
+ send_to_user = 0; /* For the moment, no Complete Packet sent to user */
+
+ /* For every Handle */
+ while(nb_handle--)
+ {
+ /* Extract the Connection Handle */
+ STREAM_TO_UINT16(con_hdl, p_data);
+
+ /* Save the current pointer position (to overwrite number of packet) */
+ p_save = p_data;
+
+ /* Extract the Number Of Complete Packet */
+ STREAM_TO_UINT16(num_cplt_pck, p_data);
+
+ /* Call the L2CAP NumberOfcompletePacket Handler */
+ num_cplt_pck_caugth = btusb_lite_l2c_nocp_hdlr(p_dev, con_hdl, num_cplt_pck);
+
+ /* If L2CAP "caught"at least one nocp packet */
+ if (num_cplt_pck_caugth)
+ {
+ /* Overwrite the Number Of Complete Packet */
+ UINT16_TO_STREAM(p_save, num_cplt_pck - num_cplt_pck_caugth);
+
+ /* If at least one Number Of Complete Packet remains */
+ if (num_cplt_pck - num_cplt_pck_caugth)
+ {
+ /* Send the event to user space */
+ send_to_user = 1;
+ }
+ }
+ else
+ {
+ /* Don't update the number but send the event to user space */
+ send_to_user = 1;
+ }
+ }
+
+ return send_to_user;
+}
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_cmd_cplt_evt_send
+ **
+ ** Description Send an HCI VSC Cmd Complete.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_hci_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len)
+{
+ BT_HDR *p_msg;
+ UINT16 size = param_len + 5;
+ UINT8 *p;
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = HCIT_TYPE_EVENT;
+ p_msg->len = size;
+ p_msg->layer_specific = BTUSB_LS_GKI_BUFFER;
+
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ p = btusb_lite_hci_write_evt_header(p, HCI_COMMAND_COMPLETE_EVT, size - 2);
+
+ UINT8_TO_STREAM(p, BTUSB_LITE_HCI_NUM_CMD); /* HCI Num Command */
+ UINT16_TO_STREAM(p, opcode); /* HCI OpCode */
+
+ if (p_param)
+ {
+ ARRAY_TO_STREAM(p, p_param, param_len)
+ }
+
+ /* InQ for user-space to read */
+ GKI_enqueue(&p_dev->rx_queue, p_msg);
+
+ /* if the process is polling, indicate RX event */
+ wake_up_interruptible(&p_dev->rx_wait_q);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_write_acl_header
+ **
+ ** Description Write HCI ACL Header (HCI_Type, Connection Handle, Length)
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_hci_write_acl_header(UINT8 *p_data, UINT16 con_hdl, UINT16 length)
+{
+ UINT8_TO_STREAM(p_data, HCIT_TYPE_ACL_DATA); /* HCI_Type */
+ UINT16_TO_STREAM(p_data, con_hdl); /* Connection Handle */
+ UINT16_TO_STREAM(p_data, length); /* Length */
+ return p_data;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_write_evt_header
+ **
+ ** Description Write HCI Event Header (HCI_Type, Connection Handle, Length)
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_hci_write_evt_header(UINT8 *p_data, UINT8 event, UINT8 length)
+{
+ UINT8_TO_STREAM(p_data, event);
+ UINT8_TO_STREAM(p_data, length); /* Param Length */
+ return p_data;
+}
+
diff --git a/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_l2c.c.svn-base b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_l2c.c.svn-base
new file mode 100755
index 0000000..5db7ecc
--- a/dev/null
+++ b/btusb_1_6_29_1/src/.svn/text-base/btusb_lite_l2c.c.svn-base
@@ -0,0 +1,278 @@
+/*
+ *
+ * btusb_lite_l2c.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include "btusb.h"
+
+/*
+ * Definitions
+ */
+
+/*
+ * Local functions
+ */
+static UINT8 *btusb_lite_l2c_write_header(UINT8 *p_data, UINT16 length, UINT16 cid);
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_add
+**
+** Description Synchronize (Add) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_add(struct btusb_cb *p_dev, tL2C_STREAM_INFO *p_l2c_stream)
+{
+ int idx;
+ struct btusb_lite_l2c_cb *p_l2c = &p_dev->lite_cb.l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+
+ /* Check if this L2CAP Stream exists */
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < ARRAY_SIZE(p_l2c->ccb) ; idx++, p_l2c_ccb++)
+ {
+ if ((p_l2c_ccb->in_use) &&
+ (p_l2c_ccb->handle == p_l2c_stream->handle))
+ {
+ BTUSB_INFO("CCB=%d was already allocated. Update it.\n", idx);
+ break;
+ }
+ }
+ /* If Not found */
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ /* Look for a free CCB */
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < ARRAY_SIZE(p_l2c->ccb) ; idx++, p_l2c_ccb++)
+ {
+ if (p_l2c_ccb->in_use == FALSE)
+ {
+ BTUSB_INFO("CCB=%d allocated\n", idx);
+ memset(p_l2c_ccb, 0, sizeof(*p_l2c_ccb));
+ p_l2c_ccb->in_use = TRUE;
+ p_l2c_ccb->local_cid = p_l2c_stream->local_cid;
+ p_l2c_ccb->remote_cid = p_l2c_stream->remote_cid;
+ p_l2c_ccb->out_mtu = p_l2c_stream->out_mtu;
+ p_l2c_ccb->handle = p_l2c_stream->handle;
+ p_l2c_ccb->is_flushable = p_l2c_stream->is_flushable;
+ break;
+ }
+ }
+ }
+
+ /* If Not found ot not allocated */
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ BTUSB_ERR("No Free L2C CCB found (handle=0x%x)\n", p_l2c_stream->handle);
+ return -1;
+ }
+
+ /* Update Transmit Quota */
+ p_l2c_ccb->link_xmit_quota = p_l2c_stream->link_xmit_quota;
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_remove
+**
+** Description Synchronize (Remove) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_remove(struct btusb_cb *p_dev, UINT16 local_cid)
+{
+ int idx;
+ struct btusb_lite_l2c_cb *p_l2c = &p_dev->lite_cb.l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+
+ /* Check if this L2CAP Stream exists */
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < ARRAY_SIZE(p_l2c->ccb) ; idx++, p_l2c_ccb++)
+ {
+ if ((p_l2c_ccb->in_use) &&
+ (p_l2c_ccb->local_cid == local_cid))
+ {
+ break;
+ }
+ }
+ /* If Not found */
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ BTUSB_ERR("L2C CCB found (lcid=0x%x)\n",local_cid);
+ return -1;
+ }
+
+ BTUSB_INFO("CCB=%d freed\n", idx);
+
+ /* Reset (Free) the L2CAP Stream */
+ memset(p_l2c_ccb, 0, sizeof(*p_l2c_ccb));
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_send
+**
+** Description Send L2CAP packet
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 local_cid)
+{
+ int idx;
+ struct btusb_lite_l2c_cb *p_l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+ UINT8 *p_data;
+
+ /* Look for the first AV stream Started */
+ p_l2c = &p_dev->lite_cb.l2c;
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < BTM_SYNC_INFO_NUM_STR ; idx++, p_l2c_ccb++)
+ {
+ if (p_l2c_ccb->local_cid == local_cid)
+ {
+ break;
+ }
+ }
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ BTUSB_ERR("No L2C CCB found (lcid=0x%x)\n", local_cid);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return -1;
+ }
+
+ /* Check if the Tx Quota has been reached for this channel */
+ if (p_l2c_ccb->tx_pending >= p_l2c_ccb->link_xmit_quota)
+ {
+ BTUSB_ERR("Tx Quota reached for L2CAP channel (lcid=0x%x). Drop buffer\n", local_cid);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return -1;
+ }
+
+ /* Sanity */
+ if (p_msg->offset < BTUSB_LITE_L2CAP_HDR_SIZE)
+ {
+ BTUSB_ERR("offset too small=%d\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return-1;
+ }
+
+ /* Decrement offset to add headers */
+ p_msg->offset -= BTUSB_LITE_L2CAP_HDR_SIZE;
+
+ /* Get address of the HCI Header */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ /* Write L2CAP Header (length field is SBC Frames + RTP/A2DP/Media Header) */
+ p_data = btusb_lite_l2c_write_header(p_data, p_msg->len, p_l2c_ccb->remote_cid);
+
+ /* Increment length */
+ p_msg->len += BTUSB_LITE_L2CAP_HDR_SIZE;
+
+
+ GKI_disable(); /* tx_pending field can be updated by another context */
+ p_l2c_ccb->tx_pending++; /* One more A2DP L2CAP packet pending */
+ BTUSB_DBG("L2C Tx Pending=%d\n", p_l2c_ccb->tx_pending);
+ GKI_enable();
+
+ if (btusb_lite_hci_acl_send(p_dev, p_msg, p_l2c_ccb->handle) < 0)
+ {
+ GKI_disable(); /* tx_pending field can be updated by another context */
+ p_l2c_ccb->tx_pending--; /* Remove A2DP L2CAP packet pending */
+ GKI_enable();
+ return -1;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_l2c_write_header
+ **
+ ** Description Write L2CAP ACL Header (Length, Channel Id)
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_l2c_write_header(UINT8 *p_data, UINT16 length, UINT16 cid)
+{
+ UINT16_TO_STREAM(p_data, length); /* Length */
+ UINT16_TO_STREAM(p_data, cid); /* Channel Id */
+ return p_data;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_l2c_nocp_hdlr
+ **
+ ** Description L2CAP NumberOfcompletePacket Handler function
+ **
+ ** Returns Number Of Complete Packet caught
+ **
+ *******************************************************************************/
+UINT16 btusb_lite_l2c_nocp_hdlr(struct btusb_cb *p_dev, UINT16 con_hdl, UINT16 num_cplt_pck)
+{
+ struct btusb_lite_l2c_cb *p_l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+ int i;
+ UINT16 num_cplt_pck_caugth;
+
+ /* Look for the L2CAP channel matching the Connection Handle */
+ p_l2c = &p_dev->lite_cb.l2c;
+ for (i = 0, p_l2c_ccb = p_l2c->ccb ; i < BTM_SYNC_INFO_NUM_STR ; i++, p_l2c_ccb++)
+ {
+ if (p_l2c_ccb->handle == con_hdl)
+ {
+ break;
+ }
+ }
+ /* If L2CAP channel not found/known */
+ if (i == BTM_SYNC_INFO_NUM_STR)
+ {
+ return 0;
+ }
+
+ /* If no Tx Pending */
+ if (p_l2c_ccb->tx_pending == 0)
+ {
+ return 0;
+ }
+
+ GKI_disable(); /* tx_pending field can be updated by another context */
+
+ /* Take the min between the number of pending packet and the number of acked packet */
+ num_cplt_pck_caugth = min(p_l2c_ccb->tx_pending, num_cplt_pck);
+
+ /* Update the number of pending packet */
+ p_l2c_ccb->tx_pending-= num_cplt_pck_caugth;
+
+ BTUSB_DBG("L2C NOCP Tx Pending=%d\n", p_l2c_ccb->tx_pending);
+
+ GKI_enable();
+
+ return num_cplt_pck_caugth;
+}
diff --git a/btusb_1_6_29_1/src/btusb.c b/btusb_1_6_29_1/src/btusb.c
new file mode 100755
index 0000000..0cda85b
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb.c
@@ -0,0 +1,1625 @@
+/*
+ *
+ * btusb.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include "btusb.h"
+#include "hcidefs.h"
+
+#define BTUSB_VID_BRCM 0x0A5C
+
+// forward reference
+struct usb_driver btusb_driver;
+
+// table of devices that work with this driver
+static struct usb_device_id btusb_table [] =
+{
+#if defined(BTUSB_VID) && defined(BTUSB_PID)
+ /* If a specific Vid/Pid is specified at compilation time */
+ { USB_DEVICE(BTUSB_VID, BTUSB_PID) },
+#else
+ // all BT devices
+ { .match_flags = USB_DEVICE_ID_MATCH_DEV_CLASS | USB_DEVICE_ID_MATCH_DEV_SUBCLASS |
+ USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ .bDeviceClass = USB_CLASS_WIRELESS_CONTROLLER,
+ // 0x01 / 0x01 = Bluetooth programming interface
+ .bDeviceSubClass = 0x01,
+ .bDeviceProtocol = 0x01
+ },
+ // all BRCM BT interfaces
+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_INT_CLASS | USB_DEVICE_ID_MATCH_INT_SUBCLASS |
+ USB_DEVICE_ID_MATCH_INT_PROTOCOL,
+ .idVendor = BTUSB_VID_BRCM,
+ .bInterfaceClass = USB_CLASS_WIRELESS_CONTROLLER,
+ // 0x01 / 0x01 = Bluetooth programming interface
+ .bInterfaceSubClass = 0x01,
+ .bInterfaceProtocol = 0x01
+ },
+ // all BRCM vendor specific with Bluetooth programming interface
+ { .match_flags = USB_DEVICE_ID_MATCH_VENDOR | USB_DEVICE_ID_MATCH_DEV_CLASS |
+ USB_DEVICE_ID_MATCH_DEV_SUBCLASS | USB_DEVICE_ID_MATCH_DEV_PROTOCOL,
+ .idVendor = BTUSB_VID_BRCM,
+ .bDeviceClass = USB_CLASS_VENDOR_SPEC,
+ // 0x01 / 0x01 = Bluetooth programming interface
+ .bDeviceSubClass = 0x01,
+ .bDeviceProtocol = 0x01
+ },
+#endif
+ { } /* Terminating entry */
+};
+
+MODULE_DEVICE_TABLE(usb, btusb_table);
+
+static const struct file_operations btusb_debug_fops =
+{
+ .open = btusb_debug_open,
+ .read = seq_read,
+ .write = btusb_debug_write,
+ .llseek = seq_lseek,
+ .release = single_release,
+};
+
+static const struct file_operations btusb_scosniff_fops =
+{
+ .open = btusb_scosniff_open,
+ .read = seq_read,
+ .llseek = seq_lseek,
+ .release = btusb_scosniff_release,
+};
+
+static struct file_operations btusb_fops =
+{
+ .owner = THIS_MODULE,
+ .read = btusb_read,
+ .write = btusb_write,
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+ .unlocked_ioctl = btusb_ioctl,
+#else
+ .ioctl = btusb_ioctl,
+#endif
+ .poll = btusb_poll,
+ .open = btusb_open,
+ .release = btusb_release,
+};
+
+/*
+ * usb class driver info in order to get a minor number from the usb core,
+ * and to have the device registered with devfs and the driver core
+ */
+static struct usb_class_driver btusb_class =
+{
+ .name = "usb/btusb%d",
+ .fops = &btusb_fops,
+ .minor_base = BTUSB_MINOR_BASE,
+};
+
+
+// static functions
+static int btusb_create(tBTUSB_CB *p_dev, struct usb_interface *p_interface, const struct usb_device_id *p_id);
+
+// module parameter to enable suspend/resume with remote wakeup
+bool autopm = 0;
+
+// module parameter to enable debug flags
+int dbgflags = BTUSB_DBGFLAGS;
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit
+ **
+ ** Description Submit a BTUSB transaction
+ **
+ ** Parameters p_dev: driver control block
+ ** p_anchor: anchor to hook URB to when submitting
+ ** p_trans: transaction to submit
+ ** mem_flags: memory flags to submit the URB with
+ **
+ ** Returns 0 upon success, error core else.
+ **
+ *******************************************************************************/
+int btusb_submit(tBTUSB_CB *p_dev, struct usb_anchor *p_anchor, tBTUSB_TRANSACTION *p_trans, int mem_flags)
+{
+ int status;
+ struct urb *p_urb = p_trans->p_urb;
+
+ BTUSB_DBG("urb %p b=%p\n", p_urb, p_urb->transfer_buffer);
+
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ return -ENODEV;
+ }
+
+ usb_anchor_urb(p_urb, p_anchor);
+ status = usb_submit_urb(p_urb, mem_flags);
+ if (unlikely(status))
+ {
+ BTUSB_ERR("usb_submit_urb failed(%d)\n", status);
+ usb_unanchor_urb(p_urb);
+ p_dev->stats.urb_submit_err++;
+ }
+ else
+ {
+ p_dev->stats.urb_submit_ok++;
+ }
+
+ return status;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_acl_read_complete
+ **
+ ** Description ACL Bulk pipe completion routine
+ **
+ ** Parameters p_urb: URB that completed
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_acl_read_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ int count = p_urb->actual_length;
+
+ BTUSB_DBG("urb %p status %d count %d flags x%x\n", p_urb,
+ p_urb->status, count, p_urb->transfer_flags);
+
+ // number of ACL URB completed
+ p_dev->stats.acl_rx_completed++;
+
+ // check if device is disconnecting, has been unplugged or is closing
+ if (unlikely((p_urb->status == -ESHUTDOWN) ||
+ (p_urb->status == -ENOENT) ||
+ (p_urb->status == -EILSEQ)))
+ {
+ BTUSB_DBG("not queuing URB\n");
+ goto exit;
+ }
+
+ // if there was an error or no data, do not forward to upper layers
+ if (unlikely(p_urb->status || !count))
+ {
+ p_dev->stats.acl_rx_resubmit++;
+ goto resubmit;
+ }
+
+ // increment the number of bytes transferred
+ p_dev->stats.acl_rx_bytes += count;
+
+ // forward up the data
+ btusb_dump_data(p_urb->transfer_buffer, count, "btusb_acl_read_complete");
+ btusb_enqueue(p_dev, p_trans, HCIT_TYPE_ACL_DATA);
+
+ // Do not resubmit since it was forwarded to the user
+ goto exit;
+
+resubmit:
+ if (unlikely(btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_ATOMIC)))
+ p_dev->stats.acl_rx_submit_err++;
+ else
+ p_dev->stats.acl_rx_submit_ok++;
+
+exit:
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_diag_read_complete
+ **
+ ** Description Diag Bulk pipe completion routine
+ **
+ ** Parameters p_urb: URB that completed
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_diag_read_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ int count = p_urb->actual_length;
+
+ BTUSB_DBG("urb %p status %d count %d flags %x\n", p_urb,
+ p_urb->status, count, p_urb->transfer_flags);
+
+ p_dev->stats.diag_rx_completed++;
+
+ // check if device is disconnecting, has been unplugged or is closing
+ if (unlikely((p_urb->status == -ESHUTDOWN) ||
+ (p_urb->status == -ENOENT) ||
+ (p_urb->status == -EILSEQ)))
+ {
+ BTUSB_DBG("not queuing URB\n");
+ goto exit;
+ }
+
+ // if there was an error or no data or no more submitted diags, do not forward to upper layers
+ if (unlikely(p_urb->status || !count || usb_anchor_empty(&p_dev->diag_rx_submitted)))
+ {
+ p_dev->stats.diag_rx_resubmit++;
+ goto resubmit;
+ }
+
+ // increment the number of bytes transferred
+ p_dev->stats.diag_rx_bytes += count;
+
+ // forward up the data
+ btusb_dump_data(p_urb->transfer_buffer, count, "btusb_diag_read_complete");
+ btusb_enqueue(p_dev, p_trans, HCIT_TYPE_LM_DIAG);
+
+ goto exit;
+
+resubmit:
+ if (unlikely(btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_ATOMIC)))
+ p_dev->stats.diag_rx_submit_err++;
+ else
+ p_dev->stats.diag_rx_submit_ok++;
+
+exit:
+ return;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_event_complete
+ **
+ ** Description Interrupt pipe completion routine
+ **
+ ** Parameters p_urb: URB that completed
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_event_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ int count = p_urb->actual_length;
+#if defined (BTUSB_LITE)
+ BT_HDR *p_buf;
+#endif
+
+ BTUSB_DBG("urb %p status %d count %d flags %x\n", p_urb,
+ p_urb->status, count, p_urb->transfer_flags);
+
+ p_dev->stats.event_completed++;
+
+ // check if device is disconnecting, has been unplugged or is closing
+ if (unlikely((p_urb->status == -ESHUTDOWN) ||
+ (p_urb->status == -ENOENT) ||
+ (p_urb->status == -EILSEQ)))
+ {
+ BTUSB_DBG("not queuing URB\n");
+ goto exit;
+ }
+
+ // if there was an error or no data, do not forward to upper layers
+ if (unlikely(p_urb->status || !count))
+ {
+ p_dev->stats.event_resubmit++;
+ goto resubmit;
+ }
+
+#ifdef BTUSB_LITE
+ /* Filter Events received from BT Controller*/
+ if (btusb_lite_hci_event_filter(p_dev, p_trans->dma_buffer, count) == 0)
+ {
+ p_buf = &p_trans->bt_hdr;
+ p_buf->offset = 0;
+ p_buf->event = HCIT_TYPE_EVENT;
+ p_buf->len = p_trans->p_urb->actual_length;
+ btusb_dequeued(p_dev, p_buf);
+ }
+ else
+#endif
+ {
+ /* increment the number of bytes transferred */
+ p_dev->stats.event_bytes += count;
+
+ /* forward up the event */
+ btusb_dump_data(p_urb->transfer_buffer, count, "btusb_event_complete");
+ btusb_enqueue(p_dev, p_trans, HCIT_TYPE_EVENT);
+ }
+
+ /* Do not resubmit since it was forwarded to the user */
+ goto exit;
+
+resubmit:
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_ATOMIC)))
+ p_dev->stats.event_submit_err++;
+ else
+ p_dev->stats.event_submit_ok++;
+
+exit:
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_probe
+ **
+ ** Description Device probe callback
+ ** assuming the following USB device configuration :
+ **
+ ** NumInterfaces = 4
+ ** Interface 0 Alt settings 0
+ ** 3 end point excluding end point 0
+ ** 1 interrupt end point -> event
+ ** 2 bulk for acl in and out
+ ** Interface 1 Alt settings 0
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 1
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 2
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 3
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 4
+ ** 2 Iso end point excluding end point 0
+ ** Interface 1 Alt settings 5
+ ** 2 Iso end point excluding end point 0
+ ** Interface 2 Alt settings 0
+ ** 2 bulk end point for diags
+ ** Interface 3 Alt settings 0
+ ** 0 end point point i.e. only the control endpoint is used
+ ** Parameters
+ **
+ ** Returns 0 upon success, error core else.
+ **
+ *******************************************************************************/
+static int btusb_probe(struct usb_interface *p_interface, const struct usb_device_id *p_id)
+{
+ tBTUSB_CB *p_dev;
+ struct usb_ctrlrequest *p_dr;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+ struct urb *p_urb;
+ int idx, jdx;
+ tBTUSB_TRANSACTION *p_trans;
+ int retval = -ENOMEM;
+ char procname[64];
+
+ BTUSB_INFO("p_interface=%p, p_id=%p\n", p_interface, p_id);
+ BTUSB_INFO("p_interface->cur_altsetting->desc.bInterfaceNumber=%d\n", p_interface->cur_altsetting->desc.bInterfaceNumber);
+ BTUSB_DBG("match=0x%x VID=0x%x PID=0x%x class=0x%x subclass=0x%x protocol=0x%x\n",
+ p_id->match_flags, p_id->idVendor, p_id->idProduct, p_id->bDeviceClass, p_id->bDeviceSubClass,
+ p_id->bDeviceProtocol);
+
+ // Bluetooth core Interface number must be 0 (hardcoded in the spec)
+ if (p_interface->cur_altsetting->desc.bInterfaceNumber != 0)
+ {
+ BTUSB_INFO("InterfaceNumber is not 0. This is not a Bluetooth Interface\n");
+ return -ENODEV;
+ }
+
+ // allocate memory for our device
+ p_dev = kzalloc(sizeof(tBTUSB_CB), GFP_KERNEL);
+ if (p_dev == NULL)
+ {
+ dev_err(&p_interface->dev, "Out of memory\n");
+ goto error;
+ }
+ BTUSB_DBG("allocated p_dev=%p\n", p_dev);
+
+ if (btusb_create(p_dev, p_interface, p_id))
+ {
+ goto error;
+ }
+
+ // set up the endpoint information
+ // use only the first bulk-in and bulk-out endpoints
+ p_host_intf = p_interface->cur_altsetting;
+ BTUSB_DBG("%u endpoints\n", p_host_intf->desc.bNumEndpoints);
+
+ for (idx = 0; idx < p_host_intf->desc.bNumEndpoints; ++idx)
+ {
+ p_ep_desc = &p_host_intf->endpoint[idx].desc;
+ BTUSB_DBG("endpoint addr 0x%x attr 0x%x\n",
+ p_ep_desc->bEndpointAddress, p_ep_desc->bmAttributes);
+ if ((!p_dev->p_acl_in) &&
+ BTUSB_EP_DIR_IN(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk in endpoint
+ p_dev->p_acl_in = &p_host_intf->endpoint[idx];
+ }
+
+ if ((!p_dev->p_event_in) &&
+ BTUSB_EP_DIR_IN(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_INT))
+ {
+ // we found an interrupt in end point
+ p_dev->p_event_in = &p_host_intf->endpoint[idx];
+ }
+
+ if ((!p_dev->p_acl_out) &&
+ BTUSB_EP_DIR_OUT(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk out end point
+ p_dev->p_acl_out = &p_host_intf->endpoint[idx];
+ }
+ }
+
+ // now start looking at the voice interface (check if it a BT interface)
+ p_dev->p_voice_intf = usb_ifnum_to_if(p_dev->p_udev, 1);
+ if (p_dev->p_voice_intf)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[0];
+ if (((p_host_intf->desc.bInterfaceClass == USB_CLASS_WIRELESS_CONTROLLER) ||
+ (p_host_intf->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC)) &&
+ (p_host_intf->desc.bInterfaceSubClass == 1) &&
+ (p_host_intf->desc.bInterfaceProtocol == 1))
+ {
+ // can claim here, but prefer to check there are ISO endpoints
+ }
+ else
+ {
+ BTUSB_INFO("Interface 1 is not VOICE\n");
+ goto no_voice;
+ }
+ for (idx = 0; idx < p_dev->p_voice_intf->num_altsetting; idx++)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[idx];
+ for (jdx = 0; jdx < p_host_intf->desc.bNumEndpoints; jdx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[jdx].desc;
+ if (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_ISOC)
+ {
+ // found an ISO endpoint, claim interface and stop here
+ if (usb_driver_claim_interface(&btusb_driver, p_dev->p_voice_intf, p_dev) != 0)
+ {
+ BTUSB_ERR("failed claiming iso interface\n");
+ // reset it to prevent releasing it
+ p_dev->p_voice_intf = NULL;
+ goto error_claim;
+ }
+ BTUSB_DBG("claimed iso interface\n");
+
+ // set it into a disabled state
+ if (usb_set_interface(p_dev->p_udev, 1, 0))
+ {
+ BTUSB_ERR("failed to set iso intf to 0\n");
+ }
+ goto found_voice;
+ }
+ }
+ }
+ }
+no_voice:
+ p_dev->p_voice_intf = NULL;
+found_voice:
+
+ // grab other interfaces if present
+ p_dev->p_diag_intf = usb_ifnum_to_if(p_dev->p_udev, 2);
+ if (p_dev->p_diag_intf)
+ {
+ p_host_intf = &p_dev->p_diag_intf->altsetting[0];
+ if ((p_host_intf->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
+ (p_host_intf->desc.bInterfaceSubClass == 255) &&
+ (p_host_intf->desc.bInterfaceProtocol == 255))
+ {
+ if (usb_driver_claim_interface(&btusb_driver, p_dev->p_diag_intf, p_dev) != 0)
+ {
+ BTUSB_ERR("failed claiming diag interface\n");
+ p_dev->p_diag_intf = NULL;
+ goto no_diag;
+ }
+ }
+ else
+ {
+ BTUSB_INFO("Interface 2 is not DIAG\n");
+ p_dev->p_diag_intf = NULL;
+ goto no_diag;
+ }
+
+ BTUSB_DBG("claimed diag interface bNumEndpoints %d\n", p_host_intf->desc.bNumEndpoints);
+ for (idx = 0; idx < p_host_intf->desc.bNumEndpoints; ++idx)
+ {
+ p_ep_desc = &p_host_intf->endpoint[idx].desc;
+ BTUSB_DBG("diag endpoint addr 0x%x attr 0x%x\n",
+ p_ep_desc->bEndpointAddress, p_ep_desc->bmAttributes);
+ if ((!p_dev->p_diag_in) &&
+ BTUSB_EP_DIR_IN(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk in end point
+ p_dev->p_diag_in = &p_host_intf->endpoint[idx];
+ }
+ if ((!p_dev->p_diag_out) &&
+ BTUSB_EP_DIR_OUT(p_ep_desc) &&
+ (BTUSB_EP_TYPE(p_ep_desc) == USB_ENDPOINT_XFER_BULK))
+ {
+ // we found a bulk out end point
+ p_dev->p_diag_out = &p_host_intf->endpoint[idx];
+ }
+ }
+ }
+no_diag:
+
+ // try to get the DFU interface
+ p_dev->p_dfu_intf = usb_ifnum_to_if(p_dev->p_udev, 3);
+ if (p_dev->p_dfu_intf)
+ {
+ p_host_intf = &p_dev->p_dfu_intf->altsetting[0];
+ if ((p_host_intf->desc.bInterfaceClass == USB_CLASS_APP_SPEC) &&
+ (p_host_intf->desc.bInterfaceSubClass == 1))
+ {
+ if (usb_driver_claim_interface(&btusb_driver, p_dev->p_dfu_intf, p_dev) != 0)
+ {
+ BTUSB_ERR("failed claiming dfu interface\n");
+ p_dev->p_dfu_intf = NULL;
+ goto no_dfu;
+ }
+ BTUSB_DBG("claimed DFU interface bNumEndpoints %d\n", p_dev->p_dfu_intf->cur_altsetting->desc.bNumEndpoints);
+ }
+ else
+ {
+ BTUSB_INFO("Interface 3 is not DFU\n");
+ p_dev->p_dfu_intf = NULL;
+ goto no_dfu;
+ }
+ }
+no_dfu:
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->cmd_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_CMD_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("cmd_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ p_dr = &p_dev->cmd_req_array[idx];
+ p_dr->bRequestType = USB_TYPE_CLASS;
+ p_dr->bRequest = 0;
+ p_dr->wIndex = 0;
+ p_dr->wValue = 0;
+ p_dr->wLength = 0;
+
+ usb_fill_control_urb(p_urb,
+ p_dev->p_udev,
+ usb_sndctrlpipe(p_dev->p_udev, 0),
+ (void *)p_dr,
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_CMD_SIZE,
+ btusb_cmd_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ // initialize the USB data paths
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_EVT_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("event_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_int_urb(p_urb,
+ p_dev->p_udev,
+ usb_rcvintpipe(p_dev->p_udev, p_dev->p_event_in->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_EVT_SIZE,
+ btusb_event_complete,
+ p_trans,
+ p_dev->p_event_in->desc.bInterval);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("acl_rx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_rcvbulkpipe(p_dev->p_udev, p_dev->p_acl_in->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_acl_read_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_tx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("acl_tx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_sndbulkpipe(p_dev->p_udev, p_dev->p_acl_out->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_write_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ // if it is a composite device, BULK out transfers must be ZERO packet terminated
+ if (p_dev->quirks & BTUSB_QUIRK_ZLP_TX_REQ)
+ {
+ BTUSB_DBG("acl_tx_array[%d]: add ZERO_PACKET\n", idx);
+ p_urb->transfer_flags |= URB_ZERO_PACKET;
+ }
+ }
+
+ if (p_dev->p_diag_in)
+ {
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("diag_rx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_rcvbulkpipe(p_dev->p_udev, p_dev->p_diag_in->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_diag_read_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+ }
+
+ if (p_dev->p_diag_out)
+ {
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_tx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_HCI_MAX_ACL_SIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(0, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("diag_tx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+ usb_fill_bulk_urb(p_urb,
+ p_dev->p_udev,
+ usb_sndbulkpipe(p_dev->p_udev, p_dev->p_diag_out->desc.bEndpointAddress),
+ p_trans->dma_buffer,
+ BTUSB_HCI_MAX_ACL_SIZE,
+ btusb_write_complete,
+ p_trans);
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP;
+ }
+ }
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->voice_rx_array)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ // write the magic number to allow checking corruption
+ p_trans->gki_hdr.q_id = GKI_NUM_TOTAL_BUF_POOLS;
+ p_trans->magic = MAGIC_NO;
+#endif
+ p_trans->context = p_dev;
+ p_trans->dma_buffer = BTUSB_BUFFER_ALLOC(p_dev->p_udev,
+ BTUSB_VOICE_BUFFER_MAXSIZE, GFP_KERNEL, &p_trans->dma);
+ p_urb = p_trans->p_urb = usb_alloc_urb(BTUSB_VOICE_FRAMES_PER_URB, GFP_KERNEL);
+ if (!p_trans->dma_buffer || !p_urb)
+ {
+ BTUSB_ERR("transaction allocation failed\n");
+ goto error_claim;
+ }
+ BTUSB_DBG("voice_rx_array[%d]: b=%p\n", idx, p_trans->dma_buffer);
+
+ p_urb->dev = p_dev->p_udev;
+ p_urb->transfer_buffer = p_trans->dma_buffer;
+ p_urb->transfer_buffer_length = BTUSB_VOICE_BUFFER_MAXSIZE;
+ p_urb->complete = btusb_voicerx_complete;
+ p_urb->context = p_trans;
+ p_urb->transfer_dma = p_trans->dma;
+ p_urb->transfer_flags |= URB_NO_TRANSFER_DMA_MAP | URB_ISO_ASAP;
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ usb_init_urb(&p_dev->p_voicetxIrpList[idx].urb);
+ }
+
+ // we can register the device now, as it is ready
+ usb_set_intfdata(p_interface, p_dev);
+ retval = usb_register_dev(p_interface, &btusb_class);
+ if (retval)
+ {
+ // something prevented us from registering this driver
+ BTUSB_ERR("Not able to get a minor for this device\n");
+ goto error_claim;
+ }
+
+ // start sending IN tokens
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ if (btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_KERNEL))
+ {
+ p_dev->stats.event_submit_err++;
+ BTUSB_ERR("btusb_submit(event) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.event_submit_ok++;
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ if (btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_KERNEL))
+ {
+ p_dev->stats.acl_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(acl_rx) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.acl_rx_submit_ok++;
+ }
+ if (p_dev->p_diag_in)
+ {
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ if (btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_KERNEL))
+ {
+ p_dev->stats.diag_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(diag) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.diag_rx_submit_ok++;
+ }
+ }
+
+ /* Create the proc filesystem entry. To make it easy to retrieve, the
+ * entry created is called /proc/driver/btusbN where btusbN matches the
+ * file entry in /dev.
+ * The name of the device in /dev comes from the device created when
+ * usb_register_dev was called (in the current fn). The name was built
+ * from the btusb_class structure. usb_register_dev calls device_create
+ * which creates the VFS entry. This can be found in online linux code.
+ */
+ scnprintf(procname, sizeof(procname), "driver/%s", p_interface->usb_dev->kobj.name);
+ p_dev->p_debug_pde = proc_create_data(procname, S_IRUGO | S_IWUGO, NULL, &btusb_debug_fops, p_dev);
+ if (p_dev->p_debug_pde == NULL)
+ {
+ BTUSB_ERR("Couldn't create proc entry\n");
+ }
+ else
+ {
+ BTUSB_DBG("created /proc/%s\n", procname);
+ }
+
+ scnprintf(procname, sizeof(procname), "driver/%s-scosniff", p_interface->usb_dev->kobj.name);
+ p_dev->p_scosniff_pde = proc_create_data(procname, S_IRUGO, NULL, &btusb_scosniff_fops, p_dev);
+ if (p_dev->p_scosniff_pde == NULL)
+ {
+ BTUSB_ERR("Couldn't create proc SCO sniff entry\n");
+ }
+ else
+ {
+ BTUSB_DBG("created /proc/%s\n", procname);
+ INIT_LIST_HEAD(&p_dev->scosniff_list);
+ init_completion(&p_dev->scosniff_completion);
+ }
+
+#ifdef BTUSB_LITE
+ btusb_lite_create(p_dev, p_interface);
+#endif
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+ if(autopm)
+ {
+ BTUSB_INFO("Enabling for remote wakeup\n");
+ p_interface->needs_remote_wakeup = 1;
+
+ BTUSB_INFO("Setting power/wakeup to enabled\n");
+ device_set_wakeup_enable(&p_dev->p_udev->dev, 1);
+
+ BTUSB_INFO("Enabling for autosuspend\n");
+ usb_enable_autosuspend(p_dev->p_udev);
+ }
+#else
+ autopm = 0;
+ BTUSB_INFO("USB suspend/resume not supported for this kernel version\n");
+#endif
+
+ // let the user know what node this device is now attached to
+ BTUSB_DBG("device now attached to minor %d\n", p_interface->minor);
+
+ return 0;
+
+error_bt_submit:
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->acl_tx_submitted);
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->diag_tx_submitted);
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+ usb_kill_anchored_urbs(&p_dev->cmd_submitted);
+ usb_kill_anchored_urbs(&p_dev->voice_rx_submitted);
+
+ usb_deregister_dev(p_interface, &btusb_class);
+
+error_claim:
+ usb_set_intfdata(p_interface, NULL);
+ if (p_dev->p_diag_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_diag_intf);
+ p_dev->p_diag_intf = NULL;
+ BTUSB_DBG("released diag interface\n");
+ }
+ if (p_dev->p_dfu_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_dfu_intf);
+ p_dev->p_dfu_intf = NULL;
+ BTUSB_DBG("released dfu interface\n");
+ }
+ if (p_dev->p_voice_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_voice_intf);
+ p_dev->p_voice_intf = NULL;
+ BTUSB_DBG("released iso interface\n");
+ }
+
+error:
+ if (p_dev)
+ {
+ kref_put(&p_dev->kref, btusb_delete);
+ }
+ return retval;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_cancel_voice
+ **
+ ** Description Cancel all pending voice requests and wait for their cancellations
+ **
+ ** Parameters p_dev: device instance control block
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_cancel_voice(tBTUSB_CB *p_dev)
+{
+ int idx;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ BTUSB_DBG("enter\n");
+
+ // cancel rx
+ BTUSB_DBG("Removing SCO RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->voice_rx_submitted);
+
+ // free any SCO HCI message being consolidated
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->p_msg != NULL)
+ {
+ GKI_freebuf(p_chan->p_msg);
+ p_chan->p_msg = NULL;
+ }
+ }
+ // clear active RX processing
+ p_dev->pending_bytes = 0;
+ p_dev->pp_pending_msg = NULL;
+ p_dev->pending_hdr_size = 0;
+
+
+ // cancel tx
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ if (p_dev->p_voicetxIrpList[idx].used)
+ {
+ BTUSB_DBG("canceling tx URB %d\n", idx);
+ usb_kill_urb(&p_dev->p_voicetxIrpList[idx].urb);
+ p_dev->p_voicetxIrpList[idx].used = 0;
+ BTUSB_DBG("tx URB %d canceled\n", idx);
+ }
+ }
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_cancel_urbs
+ **
+ ** Description Cancel all pending non-voice requests and wait for their cancellations
+ **
+ ** Parameters pointer on usb_bt struck that contains all the btusb info
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_cancel_urbs(tBTUSB_CB *p_dev)
+{
+ BTUSB_DBG("enter\n");
+
+ // stop reading data
+ BTUSB_DBG("Removing ACL RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+
+ // stop reading events
+ BTUSB_DBG("Removing EVENT anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+
+ // stop reading diags
+ BTUSB_DBG("Removing DIAG anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+
+ // cancel ACL writes
+ BTUSB_DBG("Removing ACL TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_tx_submitted);
+
+ // cancel commands
+ BTUSB_DBG("Removing CMD anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->cmd_submitted);
+
+ // cancel diags
+ BTUSB_DBG("Removing DIAG TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_tx_submitted);
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_disconnect
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being disconnected
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static void btusb_disconnect(struct usb_interface *p_interface)
+{
+ tBTUSB_CB *p_dev = usb_get_intfdata(p_interface);
+ int idx;
+ char procname[64];
+
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("p_dev == NULL\n");
+ return;
+ }
+
+ if (p_interface != p_dev->p_main_intf)
+ {
+ BTUSB_DBG("not the main interface\n");
+ return;
+ }
+
+ // clear the interface data information
+ usb_set_intfdata(p_interface, NULL);
+
+ scnprintf(procname, sizeof(procname), "driver/%s", p_interface->usb_dev->kobj.name);
+ remove_proc_entry(procname, NULL);
+
+ scnprintf(procname, sizeof(procname), "driver/%s-scosniff", p_interface->usb_dev->kobj.name);
+ remove_proc_entry(procname, NULL);
+
+#ifdef BTUSB_LITE
+ btusb_lite_stop_all(p_dev);
+ btusb_lite_delete(p_dev, p_interface);
+#endif
+
+ BTUSB_DBG("shutting down HCI intf\n");
+
+ /* prevent more I/O from starting */
+ spin_lock_bh(&p_dev->tasklet_lock);
+ p_dev->p_main_intf = NULL;
+ spin_unlock_bh(&p_dev->tasklet_lock);
+
+ // cancel pending requests
+ btusb_cancel_voice(p_dev);
+ btusb_cancel_urbs(p_dev);
+
+ // give back our minor
+ BTUSB_DBG("unregistering #%d\n", p_interface->minor);
+ usb_deregister_dev(p_interface, &btusb_class);
+
+ // release interfaces
+ if (p_dev->p_diag_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_diag_intf);
+ p_dev->p_diag_intf = NULL;
+ BTUSB_DBG("released diag interface\n");
+ }
+ if (p_dev->p_dfu_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_dfu_intf);
+ p_dev->p_dfu_intf = NULL;
+ BTUSB_DBG("released dfu interface\n");
+ }
+ if (p_dev->p_voice_intf)
+ {
+ usb_driver_release_interface(&btusb_driver, p_dev->p_voice_intf);
+ p_dev->p_voice_intf = NULL;
+ BTUSB_DBG("released iso interface\n");
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ p_dev->p_voicetxIrpList[idx].used = 0;
+ }
+
+ if(autopm)
+ {
+ BTUSB_INFO("Disabling for remote wakeup\n");
+ p_dev->p_main_intf->needs_remote_wakeup = 0;
+
+ BTUSB_INFO("Setting power/wakeup to disabled\n");
+ device_set_wakeup_enable(&p_dev->p_udev->dev, 0);
+
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2, 6, 34)
+ BTUSB_INFO("Disabling autosuspend\n");
+ usb_disable_autosuspend(p_dev->p_udev);
+#endif
+ }
+
+ // decrement the reference counter
+ BTUSB_DBG("kref_put -> &p_dev->kref 0x%p \n", &p_dev->kref);
+ kref_put(&p_dev->kref, btusb_delete);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_suspend
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being suspended
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static int btusb_suspend(struct usb_interface *p_interface, pm_message_t message)
+{
+ tBTUSB_CB *p_dev = usb_get_intfdata(p_interface);
+
+ if (unlikely(!p_dev))
+ return 0;
+
+ if (p_dev->p_main_intf == p_interface)
+ {
+ BTUSB_INFO("Suspending USB\n");
+ BTUSB_DBG("main interface (%p)\n",p_dev->p_main_intf);
+
+ // stop reading data
+ BTUSB_DBG("Removing ACL RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+
+ // stop reading events
+ BTUSB_DBG("Removing EVENT anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+
+ // cancel ACL writes
+ BTUSB_DBG("Removing ACL TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->acl_tx_submitted);
+
+ // cancel commands
+ BTUSB_DBG("Removing CMD anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->cmd_submitted);
+
+ }
+ if (p_dev->p_voice_intf == p_interface)
+ {
+ BTUSB_DBG("voice interface (%p)\n",p_dev->p_voice_intf);
+ }
+ if (p_dev->p_dfu_intf == p_interface)
+ {
+ BTUSB_DBG("dfu interface (%p)\n",p_dev->p_dfu_intf);
+ }
+ if (p_dev->p_diag_intf == p_interface)
+ {
+ BTUSB_DBG("diag interface (%p)\n",p_dev->p_diag_intf);
+
+ // stop reading diags
+ BTUSB_DBG("Removing DIAG RX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+
+ // cancel diags
+ BTUSB_DBG("Removing DIAG TX anchored URBs\n");
+ usb_kill_anchored_urbs(&p_dev->diag_tx_submitted);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_resume
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being resumed
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static int btusb_resume(struct usb_interface *p_interface)
+{
+ tBTUSB_CB *p_dev = usb_get_intfdata(p_interface);
+ int idx;
+ int retval = -ENOMEM;
+ tBTUSB_TRANSACTION *p_trans;
+
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("p_dev == NULL\n");
+ return retval;
+ }
+
+ if (p_dev->p_main_intf == p_interface)
+ {
+ BTUSB_DBG("main interface (%p)\n",p_dev->p_main_intf);
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ if (likely(p_trans->dma_buffer != NULL))
+ {
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_KERNEL)))
+ {
+ p_dev->stats.event_submit_err++;
+ BTUSB_ERR("btusb_submit(event) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.event_submit_ok++;
+ }
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ if (likely(p_trans->dma_buffer != NULL))
+ {
+ if (unlikely(btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_KERNEL)))
+ {
+ p_dev->stats.acl_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(acl_rx) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.acl_rx_submit_ok++;
+ }
+ }
+ }
+ if (p_dev->p_voice_intf == p_interface)
+ {
+ BTUSB_DBG("voice interface (%p)\n",p_dev->p_voice_intf);
+ }
+ if (p_dev->p_dfu_intf == p_interface)
+ {
+ BTUSB_DBG("dfu interface (%p)\n",p_dev->p_dfu_intf);
+ }
+ if (p_dev->p_diag_intf == p_interface)
+ {
+ BTUSB_DBG("diag interface (%p)\n",p_dev->p_diag_intf);
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ if (likely(p_trans->dma_buffer != NULL))
+ {
+ if (unlikely(btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_KERNEL)))
+ {
+ p_dev->stats.diag_rx_submit_err++;
+ BTUSB_ERR("btusb_submit(diag) failed\n");
+ goto error_bt_submit;
+ }
+ p_dev->stats.diag_rx_submit_ok++;
+ }
+ }
+ }
+
+ return 0;
+
+error_bt_submit:
+ usb_kill_anchored_urbs(&p_dev->acl_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->diag_rx_submitted);
+ usb_kill_anchored_urbs(&p_dev->event_submitted);
+
+ usb_deregister_dev(p_interface, &btusb_class);
+ return retval;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_reset_resume
+ **
+ ** Description
+ **
+ ** Parameters p_interface: first interface being resumed
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+static int btusb_reset_resume(struct usb_interface *p_interface)
+{
+ BTUSB_DBG("enter\n");
+
+ return btusb_resume(p_interface);
+}
+
+
+struct usb_driver btusb_driver =
+{
+ .name = "btusb",
+ .id_table = btusb_table,
+ .probe = btusb_probe,
+ .disconnect = btusb_disconnect,
+ .suspend = btusb_suspend,
+ .resume = btusb_resume,
+ .reset_resume = btusb_reset_resume,
+ .supports_autosuspend = 1
+};
+
+/*******************************************************************************
+ **
+ ** Function btusb_create
+ **
+ ** Description Initialize the control block
+ **
+ ** Returns 0 upon success, error core else.
+ **
+ *******************************************************************************/
+static int btusb_create(tBTUSB_CB *p_dev, struct usb_interface *p_interface, const struct usb_device_id *p_id)
+{
+ unsigned idx;
+ struct usb_host_config *p_config;
+ struct usb_host_interface *p_host_intf;
+
+ // initialize the elements of the device structure
+ mutex_init(&p_dev->open_mutex);
+ spin_lock_init(&p_dev->tasklet_lock);
+ kref_init(&p_dev->kref);
+ GKI_init_q(&p_dev->tx_queue);
+ GKI_init_q(&p_dev->rx_queue);
+ init_waitqueue_head(&p_dev->rx_wait_q);
+ init_usb_anchor(&p_dev->acl_rx_submitted);
+ init_usb_anchor(&p_dev->event_submitted);
+ init_usb_anchor(&p_dev->diag_rx_submitted);
+ init_usb_anchor(&p_dev->acl_tx_submitted);
+ init_usb_anchor(&p_dev->cmd_submitted);
+ init_usb_anchor(&p_dev->diag_tx_submitted);
+ init_usb_anchor(&p_dev->voice_rx_submitted);
+
+ // save the USB information
+ p_dev->p_udev = usb_get_dev(interface_to_usbdev(p_interface));
+ p_dev->p_id = p_id;
+ p_dev->p_main_intf = p_interface;
+
+ // register tx task so we can start sending data to transport
+ tasklet_init(&p_dev->tx_task, btusb_tx_task, (unsigned long)p_dev);
+ BTUSB_DBG("tasklet_init complete\n");
+
+ BTUSB_DBG("sizeof(tBTUSB_ISO_ELEMENT)*BTUSB_NUM_OF_VOICE_TX_BUFFERS=%zu\n",
+ sizeof(tBTUSB_ISO_ELEMENT)*BTUSB_NUM_OF_VOICE_TX_BUFFERS);
+ p_dev->p_voicetxIrpList = kzalloc(sizeof(tBTUSB_ISO_ELEMENT)*BTUSB_NUM_OF_VOICE_TX_BUFFERS, GFP_KERNEL);
+ if (p_dev->p_voicetxIrpList == NULL)
+ {
+ dev_err(&p_interface->dev, "Out of memory for voice TX\n");
+ return -ENOMEM;
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ p_dev->p_voicetxIrpList[idx].packet = kmalloc(BTUSB_MAXIMUM_TX_VOICE_SIZE, GFP_KERNEL);
+ if (p_dev->p_voicetxIrpList[idx].packet == NULL)
+ return -ENOMEM;
+ }
+
+ p_dev->kterm.c_line = N_HCI;
+ p_dev->kterm.c_iflag = IGNPAR | ICRNL;
+ p_dev->kterm.c_oflag = 0;
+ p_dev->kterm.c_cflag = B115200 | CRTSCTS | CS8 | CLOCAL | CREAD;
+ p_dev->kterm.c_lflag = ICANON;
+ p_dev->kterm.c_ispeed = p_dev->kterm.c_ospeed = 115200;
+ p_dev->kterm.c_cc[VEOF] = 4;
+ p_dev->kterm.c_cc[VMIN] = 1;
+
+ // check if there is a WiFi interface in the same device
+ p_config = p_dev->p_udev->actconfig;
+ for (idx = 1; idx < p_config->desc.bNumInterfaces; idx++)
+ {
+ p_host_intf = &p_config->interface[idx]->altsetting[0];
+ if ((p_host_intf->desc.bInterfaceClass == USB_CLASS_VENDOR_SPEC) &&
+ (p_host_intf->desc.bInterfaceSubClass == 2) &&
+ (p_host_intf->desc.bInterfaceProtocol == 255))
+ {
+ p_dev->issharedusb = true;
+ }
+ }
+
+ // set quirks
+ if (p_dev->issharedusb)
+ {
+ // all shared USB devices need a ZLP to be sent in TX
+ p_dev->quirks |= BTUSB_QUIRK_ZLP_TX_REQ;
+
+ if ((le16_to_cpu(p_dev->p_udev->descriptor.idVendor) == 0x0A5C) &&
+ (le16_to_cpu(p_dev->p_udev->descriptor.idProduct) == 0x0BDC))
+ {
+ // the 43242 has a specific bug that needs to append 1 byte because it
+ // can not send ZLP
+ p_dev->quirks |= BTUSB_QUIRK_ZLP_RX_WA;
+ }
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_delete
+ **
+ ** Description Fully remove the elements for a device
+ **
+ ** Parameters kref: reference counter
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+void btusb_delete(struct kref *kref)
+{
+ tBTUSB_CB *p_dev = container_of(kref, tBTUSB_CB, kref);
+ tBTUSB_TRANSACTION *p_trans;
+ BT_HDR *p_buf = NULL;
+ int idx;
+
+ BTUSB_DBG("enter\n");
+
+#ifdef BTUSB_LITE
+ btusb_lite_stop_all(p_dev);
+#endif
+
+ // stop tx_task and then remove any data packets from tx_q
+ tasklet_kill(&p_dev->tx_task);
+
+ BTUSB_DBG("tasklet_kill complete\n");
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->tx_queue)) != NULL)
+ {
+ GKI_freebuf(p_buf);
+ }
+
+ BTUSB_DBG("dequeued all remaining buffers from TX Q\n");
+
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->rx_queue)) != NULL)
+ {
+ btusb_dequeued(p_dev, p_buf);
+ }
+
+ if (p_dev->p_write_msg)
+ {
+ GKI_freebuf(p_dev->p_write_msg);
+ }
+
+ BTUSB_DBG("dequeued all remaining buffers from RX Q\n");
+
+ // ensure that the process is not hanging on select()/poll()
+ wake_up_interruptible(&p_dev->rx_wait_q);
+
+ // free allocated USB DMA space
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->cmd_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_CMD_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->event_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_EVT_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_rx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->acl_tx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_rx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->diag_tx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_HCI_MAX_ACL_SIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->voice_rx_array)
+ {
+ BTUSB_BUFFER_FREE(p_dev->p_udev, BTUSB_VOICE_BUFFER_MAXSIZE,
+ p_trans->dma_buffer,
+ p_trans->dma);
+ usb_free_urb(p_trans->p_urb);
+ }
+ usb_put_dev(p_dev->p_udev);
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ if (p_dev->p_voicetxIrpList[idx].packet)
+ {
+ kfree(p_dev->p_voicetxIrpList[idx].packet);
+ }
+ }
+
+ if (p_dev->p_voicetxIrpList)
+ {
+ kfree(p_dev->p_voicetxIrpList);
+ }
+ kfree(p_dev);
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_init
+ **
+ ** Description Module init routine
+ **
+ ** Parameters None
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static int __init btusb_init(void)
+{
+ int result;
+
+ //BTUSB_DBG("built %s,%s\n", __DATE__, __TIME__);
+
+ // initialize the GKI
+ GKI_init();
+
+ // register this driver with the USB subsystem
+ result = usb_register(&btusb_driver);
+ if (result)
+ {
+ BTUSB_ERR("usb_register failed (%d)\n", result);
+ }
+
+ return result;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_exit
+ **
+ ** Description Module exit routine
+ **
+ ** Parameters None
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static void __exit btusb_exit(void)
+{
+ BTUSB_DBG("enter\n");
+
+ // shutdown the GKI
+ GKI_shutdown();
+
+ // deregister this driver from the USB subsystem
+ usb_deregister(&btusb_driver);
+}
+
+module_init(btusb_init);
+module_exit(btusb_exit);
+
+module_param(autopm, bool, 0644);
+MODULE_PARM_DESC(autopm, "Enable suspend/resume with remote wakeup");
+module_param(dbgflags, int, 0644);
+MODULE_PARM_DESC(dbgflags, "Debug flags");
+
+MODULE_DESCRIPTION("Broadcom Bluetooth USB driver");
+MODULE_LICENSE("GPL");
+
diff --git a/btusb_1_6_29_1/src/btusb_dev.c b/btusb_1_6_29_1/src/btusb_dev.c
new file mode 100755
index 0000000..3638b1b
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb_dev.c
@@ -0,0 +1,2630 @@
+/*
+ *
+ * btusb_dev.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include <linux/module.h>
+#include <linux/poll.h>
+#include <linux/slab.h>
+#include <linux/serial.h>
+
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+
+#include <linux/jiffies.h>
+
+#include "btusb.h"
+
+#include "hcidefs.h"
+
+#include "gki_int.h"
+
+// delay between the voice samples: 3 ms
+#define BTUSB_VOICE_DELAY 3
+
+// local functions declaration
+static int btusb_add_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle, unsigned char burst);
+static int btusb_remove_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle);
+static int btusb_update_voice_channels(tBTUSB_CB *p_dev);
+static void btusb_update_voice_rx(tBTUSB_CB *p_dev);
+static void btusb_submit_voice_tx(tBTUSB_CB *p_dev, UINT8 *p_data, int len);
+static int btusb_submit_cmd(tBTUSB_CB *p_dev, char *packet, unsigned long length);
+static int btusb_submit_acl(tBTUSB_CB *p_dev, char *packet, unsigned long length);
+static int btusb_submit_diag(tBTUSB_CB *p_dev, char *packet, unsigned long length);
+static int btusb_submit_write_voice(tBTUSB_CB *p_dev, void *p_packet, unsigned long length);
+
+/*******************************************************************************
+ **
+ ** Function btusb_alloc_trans
+ **
+ ** Description Allocate a transaction in the array of transactions.
+ **
+ ** Parameters p_array: array of USB transactions
+ ** size: size of the array of transactions
+ **
+ ** Returns Pointer to the next free transaction, NULL if not found
+ **
+ *******************************************************************************/
+static tBTUSB_TRANSACTION *btusb_alloc_trans(tBTUSB_TRANSACTION *p_array, size_t size)
+{
+ int idx;
+ tBTUSB_TRANSACTION *p_trans;
+
+ for (idx = 0; idx < size; idx++)
+ {
+ p_trans = &p_array[idx];
+ if (p_trans->gki_hdr.status == BUF_STATUS_FREE)
+ {
+ p_trans->gki_hdr.status = BUF_STATUS_UNLINKED;
+ return p_trans;
+ }
+ }
+ return NULL;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_dump_data
+ **
+ ** Description Print the data into the kernel messages
+ **
+ ** Parameters p: pointer to the data to print
+ ** len: length of the data to print
+ ** p_title: title to print before the data
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_dump_data(const UINT8 *p, int len, const char *p_title)
+{
+ int idx;
+
+ if (likely((dbgflags & BTUSB_DBG_MSG) == 0))
+ {
+ return;
+ }
+
+ if (p_title)
+ {
+ printk("---------------------- %s ----------------------\n", p_title);
+ }
+
+ printk("%p: ", p);
+
+ for(idx = 0; idx < len; idx++)
+ {
+ printk("%02x ", p[idx]);
+ }
+ printk("\n--------------------------------------------------------------------\n");
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_voice_stats
+ **
+ ** Description
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_voice_stats(unsigned long *p_max, unsigned long *p_min,
+ struct timeval *p_result, struct timeval *p_last_time)
+{
+ struct timeval current_time;
+
+ do_gettimeofday(&current_time);
+ // perform the carry for the later subtraction by updating y
+ if (current_time.tv_usec < p_last_time->tv_usec) {
+ int nsec = (p_last_time->tv_usec - current_time.tv_usec) / 1000000 + 1;
+ p_last_time->tv_usec -= 1000000 * nsec;
+ p_last_time->tv_sec += nsec;
+ }
+ if (current_time.tv_usec - p_last_time->tv_usec > 1000000) {
+ int nsec = (current_time.tv_usec - p_last_time->tv_usec) / 1000000;
+ p_last_time->tv_usec += 1000000 * nsec;
+ p_last_time->tv_sec -= nsec;
+ }
+ // compute the time remaining to wait
+ p_result->tv_sec = current_time.tv_sec - p_last_time->tv_sec;
+ p_result->tv_usec = current_time.tv_usec - p_last_time->tv_usec;
+
+ // update the max except the first time where the calculation is wrong
+ // because of the initial value assuming p_last is zero initialized
+ if (p_max != NULL)
+ {
+ if (p_result->tv_usec > *p_max && (p_last_time->tv_sec) && (p_last_time->tv_usec))
+ {
+ *p_max = p_result->tv_usec;
+ }
+ }
+
+ // update the min except the first time where the calculation is wrong
+ // because of the initial value assuming *p_last and p_min are zero initialized
+ if (p_min != NULL)
+ {
+ if ((p_result->tv_usec < *p_min || (*p_min == 0))
+ && (p_last_time->tv_sec) && (p_last_time->tv_usec))
+ {
+ *p_min = p_result->tv_usec;
+ }
+ }
+
+ memcpy(p_last_time, &current_time, sizeof(struct timeval));
+ BTUSB_DBG("btusb_voice_stats len: %lu\n", p_result->tv_usec);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_tx_task
+ **
+ ** Description host to controller tasklet
+ **
+ ** Parameters arg:
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_tx_task(unsigned long arg)
+{
+ tBTUSB_CB *p_dev = (tBTUSB_CB *) arg;
+ BT_HDR *p_buf;
+ UINT8 *p_data;
+ UINT8 msg_type;
+
+ // dequeue data packet and submit to transport
+ if (unlikely((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->tx_queue)) == NULL))
+ {
+ BTUSB_DBG("dequeued data = NULL - just return\n");
+ goto reschedule_task;
+ }
+
+ // bypass the header and retrieve the type
+ p_data = (UINT8 *) (p_buf + 1) + p_buf->offset;
+
+ // extract message type
+ STREAM_TO_UINT8(msg_type, p_data);
+ switch (msg_type)
+ {
+ case HCIT_TYPE_SCO_DATA:
+ btusb_submit_voice_tx(p_dev, p_data, p_buf->len - 4);
+ break;
+ case HCIT_TYPE_COMMAND:
+#ifdef BTUSB_LITE
+ /* Filter User's Write operation to catch some commands(VSCs) */
+ if (btusb_lite_hci_cmd_filter(p_dev, p_buf))
+#endif
+ {
+ btusb_submit_cmd(p_dev, p_data, p_buf->len - 1);
+ }
+ break;
+ case HCIT_TYPE_ACL_DATA:
+ btusb_submit_acl(p_dev, p_data, p_buf->len - 1);
+ break;
+ case HCIT_TYPE_LM_DIAG:
+ btusb_submit_diag(p_dev, p_data, p_buf->len - 1);
+ break;
+ }
+ GKI_freebuf(p_buf);
+
+reschedule_task:
+ if (p_dev->tx_queue.count)
+ tasklet_schedule(&p_dev->tx_task);
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_enqueue
+ **
+ ** Description Add a received USB message into the user queue
+ **
+ ** Parameters p_dev: device instance control block
+ ** p_trans: transaction to forward
+ ** hcitype: type of HCI data in the USB transaction
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_enqueue(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, UINT8 hcitype)
+{
+ BT_HDR *p_buf = &p_trans->bt_hdr;
+ struct urb *p_urb = p_trans->p_urb;
+ UINT8 *p = (UINT8 *)p_urb->transfer_buffer;
+ UINT16 len;
+
+ BTUSB_DBG("len = %d\n", p_urb->actual_length);
+
+ switch (hcitype)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ // retrieve the length in the packet header
+ p += 2;
+ STREAM_TO_UINT16(len, p);
+ len += 4;
+ break;
+
+ case HCIT_TYPE_EVENT:
+ // retrieve the length in the packet header
+ p += 1;
+ STREAM_TO_UINT8(len, p);
+ len += 2;
+ break;
+
+ case HCIT_TYPE_LM_DIAG:
+ len = HCIT_LM_DIAG_LENGTH;
+ break;
+
+ default:
+ BTUSB_ERR("Unsupported HCI type: %d\n", hcitype);
+ len = p_urb->actual_length;
+ break;
+ }
+
+ // quirk for the ZLP HW issue
+ if (unlikely(((len % 16) == 0) && (p_dev->quirks & BTUSB_QUIRK_ZLP_RX_WA) &&
+ (p_urb->actual_length == (len + 1))))
+ {
+ BTUSB_DBG("missing ZLP workaround: %d != %d\n", p_urb->actual_length, len);
+ p_urb->actual_length = len;
+ }
+ // check if the length matches that of the ACL packet
+ if (unlikely(len != p_urb->actual_length))
+ {
+ BTUSB_ERR("URB data length does not match packet %d != %d\n", p_urb->actual_length, len);
+ }
+
+ // fill up the header of the message
+ p_buf->event = hcitype;
+ p_buf->len = p_urb->actual_length;
+ p_buf->offset = 0;
+ p_buf->layer_specific &= ~BTUSB_LS_H4_TYPE_SENT;
+
+ // InQ for user-space to read
+ GKI_enqueue(&p_dev->rx_queue, p_buf);
+
+ // if the process is polling, indicate RX event
+ wake_up_interruptible(&p_dev->rx_wait_q);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_dequeued
+ **
+ ** Description Figure out what to do with a dequeued message
+ **
+ ** Parameters p_dev: driver control block
+ ** p_msg: dequeued message
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_dequeued(tBTUSB_CB *p_dev, BT_HDR *p_msg)
+{
+ tBTUSB_TRANSACTION *p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+
+ switch (p_msg->event)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ if (unlikely(btusb_submit(p_dev, &p_dev->acl_rx_submitted, p_trans, GFP_KERNEL)))
+ p_dev->stats.acl_rx_submit_err++;
+ else
+ p_dev->stats.acl_rx_submit_ok++;
+ break;
+
+ case HCIT_TYPE_EVENT:
+#if defined(BTUSB_LITE)
+ // when BTUSB_LITE is defined, EVT may be resubmitted from IRQ context
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_ATOMIC)))
+#else
+ if (unlikely(btusb_submit(p_dev, &p_dev->event_submitted, p_trans, GFP_KERNEL)))
+#endif
+ p_dev->stats.event_submit_err++;
+ else
+ p_dev->stats.event_submit_ok++;
+ break;
+
+ case HCIT_TYPE_LM_DIAG:
+ if (unlikely(btusb_submit(p_dev, &p_dev->diag_rx_submitted, p_trans, GFP_KERNEL)))
+ p_dev->stats.diag_rx_submit_err++;
+ else
+ p_dev->stats.diag_rx_submit_ok++;
+ break;
+
+ default:
+ GKI_freebuf(p_msg);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_open
+ **
+ ** Description User mode open callback
+ **
+ *******************************************************************************/
+int btusb_open(struct inode *inode, struct file *file)
+{
+ tBTUSB_CB *p_dev;
+ struct usb_interface *interface;
+ int subminor;
+ int retval = 0;
+ BT_HDR *p_buf;
+
+ BTUSB_INFO("enter\n");
+
+ // retrieve the minor for this inode
+ subminor = iminor(inode);
+
+ // retrieve the USB interface attached to this minor
+ interface = usb_find_interface(&btusb_driver, subminor);
+ if (!interface)
+ {
+ BTUSB_ERR("can't find interface for minor %d\n", subminor);
+ retval = -ENODEV;
+ goto exit;
+ }
+ BTUSB_INFO("minor %u\n", subminor);
+
+ // retrieve the device driver structure pointer
+ p_dev = usb_get_intfdata(interface);
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (!p_dev)
+ {
+ BTUSB_ERR("can't find device\n");
+ retval = -ENODEV;
+ goto exit;
+ }
+
+ mutex_lock(&p_dev->open_mutex);
+ if (p_dev->opened)
+ {
+ mutex_unlock(&p_dev->open_mutex);
+ BTUSB_ERR("multiple open not allowed %d\n", p_dev->opened);
+ retval = -EBUSY;
+ goto exit;
+ }
+ // save our object in the file's private structure
+ file->private_data = p_dev;
+ p_dev->opened = true;
+ mutex_unlock(&p_dev->open_mutex);
+
+ // increment our usage count for the device
+ BTUSB_INFO("kref_get -> &p_dev->kref 0x%p\n", &p_dev->kref);
+ kref_get(&p_dev->kref);
+
+ // free all pending messages in Rx queue
+ BTUSB_DBG("Free Rx Queue count:%d\n", p_dev->rx_queue.count);
+ while ((p_buf = (BT_HDR *)GKI_dequeue(&p_dev->rx_queue)) != NULL)
+ {
+ btusb_dequeued(p_dev, p_buf);
+ }
+
+exit:
+ return retval;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_release
+ **
+ ** Description User mode close callback
+ **
+ *******************************************************************************/
+int btusb_release(struct inode *inode, struct file *file)
+{
+ tBTUSB_CB *p_dev;
+ BT_HDR *p_buf = NULL;
+ int idx;
+
+ BTUSB_INFO("enter\n");
+
+ p_dev = (tBTUSB_CB *) file->private_data;
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+#ifdef BTUSB_LITE
+ btusb_lite_stop_all(p_dev);
+#endif
+
+ // indicate driver is closed
+ mutex_lock(&p_dev->open_mutex);
+ p_dev->opened = false;
+ mutex_unlock(&p_dev->open_mutex);
+
+ // free all the pending elements
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->tx_queue)) != NULL)
+ {
+ GKI_freebuf(p_buf);
+ }
+
+ while ((p_buf = (BT_HDR *) GKI_dequeue(&p_dev->rx_queue)) != NULL)
+ {
+ btusb_dequeued(p_dev, p_buf);
+ }
+
+ // ensure there is no process hanging on poll / select
+ wake_up_interruptible(&p_dev->rx_wait_q);
+
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ if (p_dev->voice_channels[idx].used)
+ {
+ if (btusb_remove_voice_channel(p_dev, p_dev->voice_channels[idx].info.sco_handle))
+ {
+ BTUSB_ERR("btusb_remove_voice_channel failed\n");
+ }
+ }
+ }
+
+ for (idx = 0; idx < BTUSB_NUM_OF_VOICE_TX_BUFFERS; idx++)
+ {
+ p_dev->p_voicetxIrpList[idx].used = 0;
+ }
+
+ // decrement the usage count on our device
+ BTUSB_INFO("kref_put -> &p_dev->kref 0x%p\n", &p_dev->kref);
+ kref_put(&p_dev->kref, btusb_delete);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_get_rx_packet
+ **
+ ** Description Get (extract) next buffer to sent to User Space
+ **
+ *******************************************************************************/
+static BT_HDR *btusb_get_rx_packet(struct btusb_cb *p_dev)
+{
+ // if there is a pending Rx buffer
+ if (p_dev->p_rx_msg)
+ {
+ return p_dev->p_rx_msg;
+ }
+#ifdef BTUSB_LITE
+ /* If HCI is over IPC */
+ if (btusb_lite_is_hci_over_ipc(p_dev))
+ {
+ return NULL;
+ }
+#endif
+
+ // dequeue the next buffer and store its reference
+ p_dev->p_rx_msg = GKI_dequeue(&p_dev->rx_queue);
+
+ return p_dev->p_rx_msg;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_free_rx_packet
+ **
+ ** Description Free buffer sent to User Space
+ **
+ *******************************************************************************/
+static void btusb_free_rx_packet(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ if (unlikely(p_msg != p_dev->p_rx_msg))
+ {
+ BTUSB_ERR("Dequeued buffer (%p) does not matched working buffer (%p)\n",
+ p_msg, p_dev->p_rx_msg);
+ }
+
+ p_dev->p_rx_msg = NULL;
+
+ if (unlikely(p_msg->layer_specific & BTUSB_LS_GKI_BUFFER))
+ {
+ GKI_freebuf(p_msg);
+ }
+ else
+ {
+ // buffer received from USB -> resubmit
+ btusb_dequeued(p_dev, p_msg);
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_get_rx_packet_buffer
+ **
+ ** Description Get pointer address of data to send to User Space
+ **
+ *******************************************************************************/
+static UINT8 *btusb_get_rx_packet_buffer(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ tBTUSB_TRANSACTION *p_trans;
+
+ switch(p_msg->event)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ case HCIT_TYPE_EVENT:
+ case HCIT_TYPE_LM_DIAG:
+ if (unlikely(p_msg->layer_specific & BTUSB_LS_GKI_BUFFER))
+ {
+ return ((char *)(p_msg + 1) + p_msg->offset);
+ }
+ else
+ {
+ p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+ return (p_trans->dma_buffer + p_msg->offset);
+ }
+ default: // SCO etc...
+ return ((char *)(p_msg + 1) + p_msg->offset);
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_read
+ **
+ ** Description User mode read
+ **
+ ** Returns Number of bytes read, error number if negative
+ **
+ *******************************************************************************/
+ssize_t btusb_read(struct file *file, char __user *buffer, size_t count, loff_t *ppos)
+{
+ tBTUSB_CB *p_dev = (tBTUSB_CB *)file->private_data;
+ UINT16 len;
+ size_t remainder = count;
+ BT_HDR *p_buf = NULL;
+ char *p_data;
+ char type;
+ int retval;
+
+ BTUSB_DBG("p_dev=%p count=%zu\n", p_dev, count);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->opened))
+ {
+ BTUSB_ERR("driver is not open\n");
+ return -EINVAL;
+ }
+
+ // if read is non blocking and there is no data
+ if (unlikely((file->f_flags & O_NONBLOCK) && (btusb_get_rx_packet(p_dev) == NULL)))
+ {
+ BTUSB_INFO("Non blocking read without any data\n");
+ return -EAGAIN;
+ }
+
+ // wait for an event
+ retval = wait_event_interruptible(p_dev->rx_wait_q,
+ ((p_buf = btusb_get_rx_packet(p_dev)) != NULL));
+ if (unlikely(retval))
+ {
+ BTUSB_DBG("read wait interrupted\n");
+ return retval;
+ }
+ BTUSB_DBG("buffer=%p len=%u ls=%u\n", p_buf, p_buf->len, p_buf->layer_specific);
+
+ switch(p_buf->event)
+ {
+ case HCIT_TYPE_ACL_DATA:
+ case HCIT_TYPE_EVENT:
+ case HCIT_TYPE_LM_DIAG:
+ // if this is the first time buffer is picked, add HCI header in user space
+ if (likely(!(p_buf->layer_specific & BTUSB_LS_H4_TYPE_SENT)))
+ {
+ if (likely(remainder >= 1))
+ {
+ type = p_buf->event;
+ // add the H4 packet header
+ if (unlikely(copy_to_user(buffer, &type, 1)))
+ {
+ BTUSB_ERR("copy to user error\n");
+ return -EINVAL;
+ }
+ buffer += 1;
+ remainder -= 1;
+ }
+ else
+ {
+ BTUSB_ERR("Not enough space to copy H4 ACL header\n");
+ goto read_end;
+ }
+ }
+ break;
+
+ default:
+ break;
+ }
+
+ // retrieve address of the next data to send (depends on event)
+ p_data = btusb_get_rx_packet_buffer(p_dev, p_buf);
+
+ // take the min of remainder and p_buf length
+ if (likely(p_buf->len < remainder))
+ {
+ len = p_buf->len;
+ }
+ else
+ {
+ len = remainder;
+ }
+
+ // copy the message data to the available user space
+ if (unlikely(copy_to_user(buffer, p_data, len)))
+ {
+ BTUSB_ERR("copy to user error\n");
+ return -EINVAL;
+ }
+ remainder -= len;
+ p_buf->len -= len;
+ p_buf->offset += len;
+ p_buf->layer_specific |= BTUSB_LS_H4_TYPE_SENT;
+
+ // free the first buffer if it is empty
+ if (likely(p_buf->len == 0))
+ {
+ // free (fake event) or resubmit (real USB buffer) the buffer sent to app
+ btusb_free_rx_packet(p_dev, p_buf);
+ }
+
+read_end:
+ return (count - remainder);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_write
+ **
+ ** Description User mode write
+ **
+ ** Returns Number of bytes written, error number if negative
+ **
+ *******************************************************************************/
+ssize_t btusb_write(struct file *file, const char __user *user_buffer, size_t count, loff_t *ppos)
+{
+ tBTUSB_CB *p_dev;
+ BT_HDR *p_msg;
+ UINT8 *p_data;
+ size_t remainder = count;
+ int err;
+ UINT16 appended, len;
+
+ p_dev = (tBTUSB_CB *)file->private_data;
+
+ BTUSB_DBG("p_dev=%p count=%zu\n", p_dev, count);
+
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->opened))
+ {
+ return -EINVAL;
+ }
+
+ if (unlikely(count == 0))
+ {
+ return 0;
+ }
+
+ // check that the incoming data is good
+ if (unlikely(!access_ok(VERIFY_READ, (void *)user_buffer, count)))
+ {
+ BTUSB_ERR("buffer access verification failed\n");
+ return -EFAULT;
+ }
+
+ while (remainder)
+ {
+ BTUSB_DBG("remain=%zu p_write_msg=%p\n", remainder, p_dev->p_write_msg);
+ // check if there is already an active transmission buffer
+ p_msg = p_dev->p_write_msg;
+ if (likely(!p_msg))
+ {
+ // get a buffer from the pool
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + BTUSB_H4_MAX_SIZE);
+ if (unlikely(!p_msg))
+ {
+ BTUSB_ERR("unable to get GKI buffer - write failed\n");
+ return -EINVAL;
+ }
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return -EINVAL;
+ }
+ p_dev->p_write_msg = p_msg;
+
+ p_msg->event = 0;
+ p_msg->len = 0;
+ p_msg->offset = 0;
+ p_msg->layer_specific = 0;
+ }
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ // append the entire data to the buffer (not exceeding buffer length)
+ if (likely(remainder < (BTUSB_H4_MAX_SIZE - p_msg->len)))
+ appended = remainder;
+ else
+ appended = BTUSB_H4_MAX_SIZE - p_msg->len;
+ if (unlikely(copy_from_user(p_data + p_msg->len, (void *)user_buffer, appended)))
+ {
+ BTUSB_ERR("copy from user error\n");
+ return -EINVAL;
+ }
+ BTUSB_DBG("msg_len=%u appended=%u\n", p_msg->len, appended);
+
+ // update the size of the buffer
+ p_msg->len += appended;
+
+ // compute the real HCI packet length (by default 0xFFFF to mark incomplete)
+ len = 0xFFFF;
+ switch(p_data[0])
+ {
+ case HCIT_TYPE_SCO_DATA:
+ case HCIT_TYPE_COMMAND:
+ if (likely(p_msg->len >= 4))
+ {
+ // bypass HCI type + opcode/connection handle
+ p_data += 3;
+ STREAM_TO_UINT8(len, p_data);
+ len += 4;
+ BTUSB_DBG("SCO/CMD len=%u cur=%u\n", len, p_msg->len);
+ }
+ break;
+ case HCIT_TYPE_ACL_DATA:
+ if (likely(p_msg->len >= 5))
+ {
+ // bypass HCI type + connection handle
+ p_data += 3;
+ STREAM_TO_UINT16(len, p_data);
+ len += 5;
+ // sanity check : ACL buffer should not be larger than supported
+ if (unlikely(len > BTUSB_H4_MAX_SIZE))
+ {
+ BTUSB_ERR("ACL packet too long (%u)\n", len);
+ GKI_freebuf(p_dev->p_write_msg);
+ p_dev->p_write_msg = NULL;
+ return -EINVAL;
+ }
+ BTUSB_DBG("ACL len=%u cur=%u\n", len, p_msg->len);
+ }
+ break;
+ case HCIT_TYPE_LM_DIAG:
+ // this packet does not have a length, so just send everything
+ len = p_msg->len;
+ BTUSB_DBG("DIAG len=%u cur=%u\n", len, p_msg->len);
+ break;
+ default:
+ BTUSB_ERR("unsupported packet type\n");
+ return count;
+ break;
+ }
+ // check if the buffer length exceeds the packet length
+ if (likely(p_msg->len >= len))
+ {
+ // remove the extra data (belonging to next HCI packet)
+ if (unlikely(p_msg->len > len))
+ {
+ // remove exceeding data
+ appended -= p_msg->len - len;
+ // set len to computed HCI packet length
+ p_msg->len = len;
+ }
+ if (autopm)
+ {
+ err = usb_autopm_get_interface(p_dev->p_main_intf);
+ if (unlikely(err < 0))
+ {
+ BTUSB_ERR("autopm failed\n");
+ autopm = 0;
+ }
+ }
+
+ // add the incoming data and notify the btusb_tx_task to process
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ // wake up tasklet
+ tasklet_schedule(&p_dev->tx_task);
+
+ // new write message
+ p_dev->p_write_msg = NULL;
+ }
+ remainder -= appended;
+ user_buffer += appended;
+ }
+
+ return count;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_poll
+ **
+ ** Description Poll callback (to implement select)
+ **
+ ** Parameters file : file structure of the opened instance
+ ** p_pt : poll table to which the local queue must be added
+ **
+ ** Returns Mask of the type of polling supported, error number if negative
+ **
+ *******************************************************************************/
+unsigned int btusb_poll(struct file *file, struct poll_table_struct *p_pt)
+{
+ tBTUSB_CB *p_dev;
+ unsigned int mask;
+
+ BTUSB_DBG("enter\n");
+
+ // retrieve the device from the file pointer
+ p_dev = (tBTUSB_CB *) file->private_data;
+ BTUSB_DBG("p_dev=%p\n", p_dev);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ // check if the device was disconnected
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->opened))
+ {
+ return -EINVAL;
+ }
+
+ // indicate to the system on which queue it should poll (non blocking call)
+ poll_wait(file, &p_dev->rx_wait_q, p_pt);
+
+ // enable WRITE (select/poll is not write blocking)
+ mask = POLLOUT | POLLWRNORM;
+
+ // enable READ only if data is queued from HCI
+ if (btusb_get_rx_packet(p_dev))
+ {
+ mask |= POLLIN | POLLRDNORM;
+ }
+
+ return mask;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_print_voice_stat
+ **
+ ** Description SCO print voice stats
+ **
+ ** Parameters p_stat buffer holding the statistic to display.
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_print_voice_stat(tBTUSB_STATS * p_stat)
+{
+ printk("______________btusb_print_voice_stat______________\n");
+
+ printk("Number of voice reqs submitted USB stack %lu\n", p_stat->voicerx_submitted);
+ printk("Number of voice rx submitted in error %lu\n", p_stat->voicerx_submitted_error);
+ printk("Number of voice req completions from the USB software stack %lu\n", p_stat->voicerx_completed);
+ printk("Number of Voice req completions in error %lu\n", p_stat->voicerx_completed_error);
+ printk("Voice frames discarded due to bad status %lu\n", p_stat->voicerx_bad_packets);
+ printk("Voice frames discarded due to no headers in data %lu\n", p_stat->voicerx_disc_nohdr);
+
+ printk("Raw bytes received %lu\n",p_stat->voicerx_raw_bytes);
+ printk("Skipped bytes because no header matched %lu\n",p_stat->voicerx_skipped_bytes);
+ printk("Number of Voice Tx reqs submitted %lu\n",p_stat->voicetx_submitted);
+ printk("Number of voice tx submitted in error %lu\n",p_stat->voicetx_submitted_error);
+ printk("Number of Voice Tx reqs completed %lu\n",p_stat->voicetx_completed);
+ printk("Number of Voice Tx reqs completed in error %lu\n",p_stat->voicetx_completed_error);
+ printk("Number of Voice Tx not submitted due to no room on the tx queue %lu\n",
+ p_stat->voicetx_disc_nobuf);
+ printk("Number of Voice tx not submitted due to too long data %lu\n",
+ p_stat->voicetx_disc_toolong);
+
+ printk("voice pending counter %lu, max %lu\n", p_stat->voice_tx_cnt, p_stat->voice_max_tx_cnt);
+ p_stat->voice_tx_cnt=0;p_stat->voice_max_tx_cnt=0;
+
+ printk("Delta time between voice tx_done routine in us max: %lu, min: %lu\n", p_stat->voice_max_tx_done_delta_time, p_stat->voice_min_tx_done_delta_time);
+ memset(&(p_stat->voice_tx_done_delta_time) , 0, sizeof(struct timeval));
+ memset(&(p_stat->voice_last_tx_done_ts) , 0, sizeof(struct timeval));
+ p_stat->voice_max_tx_done_delta_time = 0;
+ p_stat->voice_min_tx_done_delta_time = 0;
+
+ printk("Delta time between voice tx feeding routine in us max: %lu, min: %lu\n", p_stat->voice_max_rx_feeding_interval, p_stat->voice_min_rx_feeding_interval);
+ memset(&(p_stat->voice_rx_feeding_interval) , 0, sizeof(struct timeval));
+ memset(&(p_stat->voice_last_rx_feeding_ts) , 0, sizeof(struct timeval));
+ p_stat->voice_max_rx_feeding_interval = 0;
+ p_stat->voice_min_rx_feeding_interval = 0;
+
+ printk("Delta time between voice rx_rdy routine max in us: %lu, min : %lu\n", p_stat->voice_max_rx_rdy_delta_time, p_stat->voice_min_rx_rdy_delta_time);
+ memset(&(p_stat->voice_rx_rdy_delta_time) , 0, sizeof(struct timeval));
+ memset(&(p_stat->voice_last_rx_rdy_ts) , 0, sizeof(struct timeval));
+ p_stat->voice_max_rx_rdy_delta_time = 0;
+ p_stat->voice_min_rx_rdy_delta_time = 0;
+
+ printk("_______________________________________________________\n");
+}
+
+#define BTUSB_RETURN_STR(__c) case __c: return #__c
+static const char *btusb_ioctl_string(unsigned int cmd)
+{
+ switch(cmd)
+ {
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_GET_STATS);
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_CLEAR_STATS);
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_ADD_VOICE_CHANNEL);
+ BTUSB_RETURN_STR(IOCTL_BTWUSB_REMOVE_VOICE_CHANNEL);
+ BTUSB_RETURN_STR(TCGETS);
+ BTUSB_RETURN_STR(TCSETS);
+ BTUSB_RETURN_STR(TCSETSW);
+ BTUSB_RETURN_STR(TCSETSF);
+ BTUSB_RETURN_STR(TCGETA);
+ BTUSB_RETURN_STR(TCSETA);
+ BTUSB_RETURN_STR(TCSETAW);
+ BTUSB_RETURN_STR(TCSETAF);
+ BTUSB_RETURN_STR(TCSBRK);
+ BTUSB_RETURN_STR(TCXONC);
+ BTUSB_RETURN_STR(TCFLSH);
+ BTUSB_RETURN_STR(TIOCGSOFTCAR);
+ BTUSB_RETURN_STR(TIOCSSOFTCAR);
+ BTUSB_RETURN_STR(TIOCGLCKTRMIOS);
+ BTUSB_RETURN_STR(TIOCSLCKTRMIOS);
+#ifdef TIOCGETP
+ BTUSB_RETURN_STR(TIOCGETP);
+ BTUSB_RETURN_STR(TIOCSETP);
+ BTUSB_RETURN_STR(TIOCSETN);
+#endif
+#ifdef TIOCGETC
+ BTUSB_RETURN_STR(TIOCGETC);
+ BTUSB_RETURN_STR(TIOCSETC);
+#endif
+#ifdef TIOCGLTC
+ BTUSB_RETURN_STR(TIOCGLTC);
+ BTUSB_RETURN_STR(TIOCSLTC);
+#endif
+#ifdef TCGETX
+ BTUSB_RETURN_STR(TCGETX);
+ BTUSB_RETURN_STR(TCSETX);
+ BTUSB_RETURN_STR(TCSETXW);
+ BTUSB_RETURN_STR(TCSETXF);
+#endif
+ BTUSB_RETURN_STR(TIOCMGET);
+ BTUSB_RETURN_STR(TIOCMSET);
+ BTUSB_RETURN_STR(TIOCGSERIAL);
+ BTUSB_RETURN_STR(TIOCMIWAIT);
+ BTUSB_RETURN_STR(TIOCMBIC);
+ BTUSB_RETURN_STR(TIOCMBIS);
+ default:
+ return "unknwown";
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_ioctl
+ **
+ ** Description User mode ioctl
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success or an error code.
+ **
+ *******************************************************************************/
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,36)
+long btusb_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
+#else
+int btusb_ioctl(struct inode *inode, struct file *file, unsigned int cmd, unsigned long arg)
+#endif
+{
+ const char *s_cmd;
+ tBTUSB_CB *p_dev;
+ tBTUSB_SCO_INFO sco_info;
+ int retval = 0;
+
+ s_cmd = btusb_ioctl_string(cmd);
+
+ BTUSB_INFO("cmd=%s\n", s_cmd);
+
+ p_dev = (tBTUSB_CB *) file->private_data;
+ BTUSB_INFO("p_dev=%p\n", p_dev);
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ // check if the device was disconnected
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ switch (cmd)
+ {
+ case IOCTL_BTWUSB_GET_STATS:
+ if (copy_to_user((void *) arg, &p_dev->stats, sizeof(tBTUSB_STATS)))
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case IOCTL_BTWUSB_CLEAR_STATS:
+ memset(&p_dev->stats, 0, sizeof(tBTUSB_STATS));
+ break;
+
+ case IOCTL_BTWUSB_ADD_VOICE_CHANNEL:
+ if (copy_from_user(&sco_info, (void *) arg, sizeof(sco_info)))
+ {
+ BTUSB_ERR("BTUSB_IOCTL_ADD_VOICE_CHANNEL failed getting 1st par\n");
+ retval = -EFAULT;
+ goto err_out;
+ }
+ return btusb_add_voice_channel(p_dev, sco_info.sco_handle, sco_info.burst);
+
+ case IOCTL_BTWUSB_REMOVE_VOICE_CHANNEL:
+ if (copy_from_user(&sco_info, (void *) arg, sizeof(sco_info)))
+ {
+ BTUSB_ERR("BTUSB_IOCTL_ADD_VOICE_CHANNEL failed getting 1st par\n");
+ retval = -EFAULT;
+ goto err_out;
+ }
+ return btusb_remove_voice_channel(p_dev, sco_info.sco_handle);
+
+ case TCGETS:
+ /* dummy support of TTY IOCTLs */
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+#ifndef TCGETS2
+ if (kernel_termios_to_user_termios((struct termios __user *)arg, &p_dev->kterm))
+#else
+ if (kernel_termios_to_user_termios_1((struct termios __user *)arg, &p_dev->kterm))
+#endif
+ {
+ BTUSB_ERR("failure copying termios\n");
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case TCSETSW:
+ case TCSETS:
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+#ifndef TCGETS2
+ if (user_termios_to_kernel_termios(&p_dev->kterm, (struct termios __user *)arg))
+#else
+ if (user_termios_to_kernel_termios_1(&p_dev->kterm, (struct termios __user *)arg))
+#endif
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ break;
+
+ case TCSETSF:
+ case TCGETA:
+ case TCSETA:
+ case TCSETAW:
+ case TCSETAF:
+ case TCSBRK:
+ case TCXONC:
+ case TCFLSH:
+ case TIOCGSOFTCAR:
+ case TIOCSSOFTCAR:
+ case TIOCGLCKTRMIOS:
+ case TIOCSLCKTRMIOS:
+#ifdef TIOCGETP
+ case TIOCGETP:
+ case TIOCSETP:
+ case TIOCSETN:
+#endif
+#ifdef TIOCGETC
+ case TIOCGETC:
+ case TIOCSETC:
+#endif
+#ifdef TIOCGLTC
+ case TIOCGLTC:
+ case TIOCSLTC:
+#endif
+#ifdef TCGETX
+ case TCGETX:
+ case TCSETX:
+ case TCSETXW:
+ case TCSETXF:
+#endif
+ case TIOCMSET:
+ case TIOCMBIC:
+ case TIOCMBIS:
+ /* dummy support of TTY IOCTLs */
+ BTUSB_DBG("TTY ioctl not implemented\n");
+ break;
+
+ case TIOCGSERIAL:
+ {
+ struct serial_struct tmp;
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ memset(&tmp, 0, sizeof(tmp));
+ tmp.type = 0;
+ tmp.line = 0;
+ tmp.port = 0;
+ tmp.irq = 0;
+ tmp.flags = ASYNC_SKIP_TEST | ASYNC_AUTO_IRQ;
+ tmp.xmit_fifo_size = 4096;
+ tmp.baud_base = 115200;
+ tmp.close_delay = 5*HZ;
+ tmp.closing_wait = 30*HZ;
+ tmp.custom_divisor = 0;
+ tmp.hub6 = 0;
+ tmp.io_type = 0;
+ if (copy_to_user((void __user *)arg, &tmp, sizeof(tmp)))
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = 0;
+ break;
+ }
+
+ case TIOCMGET:
+ {
+ int tiocm = TIOCM_RTS | TIOCM_CTS;
+ if (!arg)
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+
+ if (copy_to_user((void __user *)arg, &tiocm, sizeof(tiocm)))
+ {
+ retval = -EFAULT;
+ goto err_out;
+ }
+ retval = 0;
+ break;
+ }
+
+ case TIOCMIWAIT:
+ {
+ DECLARE_WAITQUEUE(wait, current);
+
+ BTUSB_DBG("arg = %lu\n", arg);
+ while (1)
+ {
+ BTUSB_DBG("adding task to wait list\n");
+ add_wait_queue(&p_dev->rx_wait_q, &wait);
+ set_current_state(TASK_INTERRUPTIBLE);
+ schedule();
+ BTUSB_DBG("removing task from wait list\n");
+ remove_wait_queue(&p_dev->rx_wait_q, &wait);
+ /* see if a signal woke us up */
+ if (signal_pending(current))
+ {
+ BTUSB_ERR("signal was pending\n");
+ retval = -ERESTARTSYS;
+ goto err_out;
+ }
+ // do not check the expected signals
+ retval = 0;
+ break;
+ }
+ break;
+ }
+ default:
+ BTUSB_ERR("unknown cmd %u\n", cmd);
+ retval = -ENOIOCTLCMD;
+ break;
+ }
+
+err_out:
+ BTUSB_DBG("returning %d\n", retval);
+ return retval;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_write_complete
+ **
+ ** Description Data write (bulk pipe) completion routine
+ **
+ ** Parameters urb pointer
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_write_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+
+ BTUSB_DBG("status %d length %u flags %x\n", p_urb->status,
+ p_urb->transfer_buffer_length, p_urb->transfer_flags);
+
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+
+ if (unlikely(p_urb->status))
+ {
+ p_dev->stats.writes_completed_error++;
+ printk(KERN_ERR "BTUSB btusb_write_complete failure %d\n", p_urb->status);
+ }
+ else
+ {
+ p_dev->stats.writes_completed++;
+ }
+
+ if(autopm)
+ {
+ usb_autopm_put_interface(p_dev->p_main_intf);
+ }
+
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_strip_off_acl_handle
+ **
+ ** Description Strip off the ACL handle if this is firmware download packet
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_strip_off_acl_handle(char* *packet, unsigned long *length)
+{
+ UINT8* p = (UINT8 *) (*packet);
+
+ BTUSB_DBG("first bytes are %02X %02X\n", *p, *(p+1));
+
+ // check special handle for firmware download packet
+ if ((*p == 0xEF) && (*(p+1) == 0xBE))
+ {
+ *packet = (char *) (p + 4);
+ *length -= 4;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_acl
+ **
+ ** Description ACL write submission to the controller
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success, negative value if error
+ **
+ *******************************************************************************/
+int btusb_submit_acl(tBTUSB_CB *p_dev, char *packet, unsigned long length)
+{
+ int retval;
+ tBTUSB_TRANSACTION *p_trans;
+
+ BTUSB_DBG("%p[%lu]\n", packet, length);
+
+ // strip off the ACL handle if this is a firmware download packet
+ btusb_strip_off_acl_handle (&packet, &length);
+ BTUSB_DBG("after adjusting %p[%lu]\n", packet, length);
+
+ btusb_dump_data(packet, length, "OUTGOING DATA");
+
+
+
+ p_trans = btusb_alloc_trans(p_dev->acl_tx_array, ARRAY_SIZE(p_dev->acl_tx_array));
+ if (unlikely(p_trans == NULL))
+ {
+ return -ENOMEM;
+ }
+
+ if (unlikely(length > BTUSB_HCI_MAX_ACL_SIZE))
+ {
+ retval = -E2BIG;
+ goto error;
+ }
+
+#if 0
+ // if this is called directly from write call
+ if (copy_from_user(p_trans->dma_buffer, user_buffer, length))
+ {
+ retval = -EFAULT;
+ goto error;
+ }
+#else
+ memcpy(p_trans->dma_buffer, packet, length);
+#endif
+ p_trans->p_urb->transfer_buffer_length = length;
+
+ retval = btusb_submit(p_dev, &p_dev->acl_tx_submitted, p_trans, GFP_ATOMIC);
+ if (unlikely(retval))
+ {
+ goto error;
+ }
+ return retval;
+
+error:
+ BTUSB_ERR("failed : %d\n", retval);
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+ return retval;
+#if 0
+ return btusb_submit_bulk(p_dev, packet, length, p_dev->p_acl_out, &p_dev->acl_tx_submitted);
+#endif
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_diag
+ **
+ ** Description Diag write submission to the controller
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success, negative value if error
+ **
+ *******************************************************************************/
+int btusb_submit_diag(tBTUSB_CB *p_dev, char *packet, unsigned long length)
+{
+ int retval;
+ tBTUSB_TRANSACTION *p_trans;
+
+ BTUSB_DBG("%p[%lu]\n", packet, length);
+
+ btusb_dump_data(packet, length, "OUTGOING DIAG");
+ if (unlikely(!p_dev->p_diag_out))
+ {
+ return -ENODEV;
+ }
+
+ p_trans = btusb_alloc_trans(p_dev->diag_tx_array, ARRAY_SIZE(p_dev->diag_tx_array));
+ if (unlikely(p_trans == NULL))
+ {
+ return -ENOMEM;
+ }
+
+ if (unlikely(length > BTUSB_HCI_MAX_ACL_SIZE))
+ {
+ retval = -E2BIG;
+ goto error;
+ }
+
+#if 0
+ // if this is called directly from write call
+ if (copy_from_user(p_trans->dma_buffer, user_buffer, length))
+ {
+ retval = -EFAULT;
+ goto error;
+ }
+#else
+ memcpy(p_trans->dma_buffer, packet, length);
+#endif
+ p_trans->p_urb->transfer_buffer_length = length;
+
+ retval = btusb_submit(p_dev, &p_dev->diag_tx_submitted, p_trans, GFP_ATOMIC);
+ if (unlikely(retval))
+ {
+ goto error;
+ }
+ return retval;
+
+error:
+ BTUSB_ERR("failed : %d\n", retval);
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+ return retval;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_cmd_complete
+ **
+ ** Description Command (control pipe) completion routine
+ **
+ ** Parameters
+ **
+ ** Returns void.
+ **
+ *******************************************************************************/
+void btusb_cmd_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+
+ BTUSB_DBG("status %d %u length flags %x\n", p_urb->status,
+ p_urb->transfer_buffer_length, p_urb->transfer_flags);
+
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+
+ if (unlikely(p_urb->status))
+ {
+ BTUSB_ERR("failure %d\n", p_urb->status);
+ p_dev->stats.commands_completed_error++;
+ }
+ else
+ {
+ p_dev->stats.commands_completed++;
+ }
+
+ if(autopm)
+ usb_autopm_put_interface(p_dev->p_main_intf);
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_cmd
+ **
+ ** Description
+ **
+ ** Parameters
+ **
+ ** Returns 0 upon success, negative value if error
+ **
+ *******************************************************************************/
+int btusb_submit_cmd(tBTUSB_CB *p_dev, char *packet, unsigned long length)
+{
+ int retval;
+ tBTUSB_TRANSACTION *p_trans;
+ struct usb_ctrlrequest *p_dr = NULL;
+
+ BTUSB_DBG("%p[%lu]\n", packet, length);
+
+ btusb_dump_data(packet, length, "OUTGOING CMD");
+
+ p_trans = btusb_alloc_trans(p_dev->cmd_array, ARRAY_SIZE(p_dev->cmd_array));
+ if (unlikely(p_trans == NULL))
+ {
+ return -ENOMEM;
+ }
+
+ if (unlikely(length > BTUSB_HCI_MAX_CMD_SIZE))
+ {
+ retval = -E2BIG;
+ goto error;
+ }
+
+#if 0
+ // if this is called directly from write call
+ if (copy_from_user(p_trans->dma_buffer, packet, length))
+ {
+ retval = -EFAULT;
+ goto error;
+ }
+#else
+ memcpy(p_trans->dma_buffer, packet, length);
+#endif
+ p_dr = (void *)p_trans->p_urb->setup_packet;
+ p_dr->wLength = __cpu_to_le16(length);
+ p_trans->p_urb->transfer_buffer_length = length;
+
+ retval = btusb_submit(p_dev, &p_dev->cmd_submitted, p_trans, GFP_ATOMIC);
+ if (unlikely(retval))
+ {
+ p_dev->stats.commands_submitted_error++;
+ goto error;
+ }
+ return retval;
+
+error:
+ p_trans->gki_hdr.status = BUF_STATUS_FREE;
+ return retval;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_voicetx_complete
+ **
+ ** Description Voice write (iso pipe) completion routine.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_voicetx_complete(struct urb *p_urb)
+{
+ tBTUSB_ISO_ELEMENT *pIsoXfer = p_urb->context;
+ tBTUSB_CB *p_dev = (void *) pIsoXfer->dev;
+
+ btusb_voice_stats(&(p_dev->stats.voice_max_tx_done_delta_time), &(p_dev->stats.voice_min_tx_done_delta_time),
+ &(p_dev->stats.voice_tx_done_delta_time), &(p_dev->stats.voice_last_tx_done_ts));
+
+ // keep track on the number of Tx buffer pending
+ p_dev->stats.voice_tx_cnt--;
+
+ if (unlikely(!p_dev->p_main_intf))
+ goto exit;
+
+ pIsoXfer->used = 0;
+
+ if (unlikely(p_urb->status))
+ {
+ BTUSB_ERR("btusb_voicetx_complete failure %d\n", p_urb->status);
+ p_dev->stats.voicetx_completed_error++;
+ }
+ else
+ {
+ p_dev->stats.voicetx_completed++;
+ }
+
+exit:
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_fill_iso_pkts
+ **
+ ** Description Useful voice utility.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_fill_iso_pkts(struct urb *p_urb, int len, int pkt_size)
+{
+ int off = 0, i;
+
+ for (i = 0; len >= pkt_size; i++, off += pkt_size, len -= pkt_size)
+ {
+ p_urb->iso_frame_desc[i].offset = off;
+ p_urb->iso_frame_desc[i].length = pkt_size;
+ }
+
+ // remainder?
+ if (len)
+ {
+ p_urb->iso_frame_desc[i].offset = off;
+ p_urb->iso_frame_desc[i].length = len;
+ i++;
+ }
+
+ p_urb->number_of_packets = i;
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_fill_iso_rx_pkts
+ **
+ ** Description Useful voice utility.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_fill_iso_rx_pkts(struct urb *p_urb, int len, int pkt_size)
+{
+ int off = 0, i;
+
+ for (i = 0; len >= pkt_size; i++, off += ALIGN(pkt_size, 4), len -= ALIGN(pkt_size, 4))
+ {
+ p_urb->iso_frame_desc[i].offset = off;
+ p_urb->iso_frame_desc[i].length = pkt_size;
+ BTUSB_DBG("off=%d pkt_size=%d\n", off, pkt_size);
+ }
+ p_urb->number_of_packets = i;
+ return;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_voice_rx
+ **
+ ** Description Resubmit an already filled URB request
+ **
+ ** Parameters
+ **
+ ** Returns
+ **
+ *******************************************************************************/
+void btusb_submit_voice_rx(tBTUSB_CB *p_dev, tBTUSB_TRANSACTION *p_trans, int mem_flags)
+{
+ if (unlikely(btusb_submit(p_dev, &p_dev->voice_rx_submitted, p_trans, mem_flags)))
+ {
+ p_dev->stats.voicerx_submitted_error++;
+ }
+ else
+ {
+ p_dev->stats.voicerx_submitted++;
+ }
+
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_update_voice_rx
+ **
+ ** Description Finish filling the voice URB and submit them. At this point
+ ** the URBs should NOT be submitted.
+ **
+ ** Parameters
+ **
+ ** Returns
+ **
+ *******************************************************************************/
+static void btusb_update_voice_rx(tBTUSB_CB *p_dev)
+{
+ unsigned int idx;
+ tBTUSB_TRANSACTION *p_trans;
+ struct urb *p_urb;
+ int packet_size;
+
+ BTUSB_DBG("enter\n");
+
+ if (!p_dev->p_main_intf || !p_dev->p_voice_intf || !p_dev->p_voice_in)
+ {
+ BTUSB_ERR("failing (p_dev removed or no voice intf)\n");
+ return;
+ }
+
+ packet_size = le16_to_cpu(p_dev->p_voice_in->desc.wMaxPacketSize);
+ if (!packet_size)
+ {
+ BTUSB_ERR("failing, 0 packet size)\n");
+ return;
+ }
+ BTUSB_DBG("packet_size=%d\n", packet_size);
+
+ BTUSB_ARRAY_FOR_EACH_TRANS(p_dev->voice_rx_array)
+ {
+ p_urb = p_trans->p_urb;
+ p_urb->pipe = usb_rcvisocpipe(p_dev->p_udev, p_dev->p_voice_in->desc.bEndpointAddress);
+ BTUSB_DBG("ep=%d\n", p_dev->p_voice_in->desc.bEndpointAddress);
+ p_urb->interval = p_dev->p_voice_in->desc.bInterval;
+ BTUSB_DBG("interval=%d\n", p_urb->interval);
+ p_urb->transfer_buffer_length = ALIGN(packet_size, 4) * BTUSB_VOICE_FRAMES_PER_URB;
+ BTUSB_DBG("transfer_buffer_length=%d\n", p_urb->transfer_buffer_length);
+ if (p_urb->transfer_buffer_length > BTUSB_VOICE_BUFFER_MAXSIZE)
+ {
+ BTUSB_ERR("Required buffer size larger than allocated size\n");
+ p_urb->transfer_buffer_length = BTUSB_VOICE_BUFFER_MAXSIZE;
+ }
+ btusb_fill_iso_rx_pkts(p_urb, p_urb->transfer_buffer_length, packet_size);
+
+ btusb_submit_voice_rx(p_dev, p_trans, GFP_KERNEL);
+ }
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_voice_tx
+ **
+ ** Description Voice write submission
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_submit_voice_tx(tBTUSB_CB *p_dev, UINT8 *p_data, int len)
+{
+ int to_send = 0;
+
+ btusb_voice_stats(&(p_dev->stats.voice_max_rx_feeding_interval), &(p_dev->stats.voice_min_rx_feeding_interval),
+ &(p_dev->stats.voice_rx_feeding_interval), &(p_dev->stats.voice_last_rx_feeding_ts));
+
+ while (len > 0)
+ {
+ if (len >= BTUSB_VOICE_BURST_SIZE)
+ {
+ to_send = BTUSB_VOICE_BURST_SIZE;
+ }
+ else
+ {
+ BTUSB_DBG("Sending partial sco data len: %d\n", len);
+ }
+ p_data[2] = to_send;
+ len -= to_send;
+ btusb_submit_write_voice(p_dev, p_data, to_send + 3);
+
+ if (len)
+ {
+ // copy the header for the next chunk
+ memcpy(p_data + BTUSB_VOICE_BURST_SIZE, p_data , 3);
+ p_data += BTUSB_VOICE_BURST_SIZE;
+ }
+ }
+
+ // we should always have at least 30 ms of audio ready to send
+ // if not fill up with silence
+ if (p_dev->stats.voice_tx_cnt<10)
+ {
+ BTUSB_DBG("less than 10 buffer in the Tx Q %lu insert silence \n", p_dev->stats.voice_tx_cnt);
+ while(p_dev->stats.voice_tx_cnt < 30)
+ {
+ memset(p_data + 3, 0, BTUSB_VOICE_BURST_SIZE );
+ btusb_submit_write_voice(p_dev, p_data, BTUSB_VOICE_BURST_SIZE + 3);
+ }
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_submit_write_voice
+ **
+ ** Description Voice write submission, length should be
+ ** smaller than or equal to VOICE_SAMPLE_SIZE
+ **
+ ** Parameters
+ **
+ ** Returns A zero value upon success.
+ **
+ *******************************************************************************/
+int btusb_submit_write_voice(tBTUSB_CB *p_dev, void *p_packet, unsigned long length)
+{
+ tBTUSB_ISO_ELEMENT *pIsoXfer;
+ struct urb *p_urb;
+ int status, pipe;
+ int packet_size, cur_frame_number;
+
+ if (!p_dev->p_main_intf || !p_dev->p_voice_intf || !p_dev->p_voice_out)
+ {
+ BTUSB_DBG(" failing (p_dev removed or no voice intf)\n");
+ return -1;
+ }
+
+ packet_size = le16_to_cpu(p_dev->p_voice_out->desc.wMaxPacketSize);
+ if ((length > BTUSB_MAXIMUM_TX_VOICE_SIZE) || !packet_size)
+ {
+ BTUSB_ERR("failing (%lu bytes - too many for %d packet size)\n", length, packet_size);
+ p_dev->stats.voicetx_disc_toolong++;
+ return -11;
+ }
+
+ // advance to the next voice tx IRP
+ if (++p_dev->voicetxIrpIndex == BTUSB_NUM_OF_VOICE_TX_BUFFERS)
+ p_dev->voicetxIrpIndex = 0;
+
+ // keep track on the number of tx buffer for stats debug and optimization
+ p_dev->stats.voice_tx_cnt++;
+ if (p_dev->stats.voice_tx_cnt>p_dev->stats.voice_max_tx_cnt)
+ {
+ p_dev->stats.voice_max_tx_cnt = p_dev->stats.voice_tx_cnt;
+ }
+
+ pIsoXfer = &p_dev->p_voicetxIrpList[p_dev->voicetxIrpIndex];
+
+ // buffer available?
+ if (pIsoXfer->used)
+ {
+ BTUSB_ERR("failed, no buf!\n");
+ p_dev->stats.voicetx_disc_nobuf++;
+ return -111;
+ }
+
+ p_urb = &pIsoXfer->urb;
+ pIsoXfer->index = p_dev->voicetxIrpIndex;
+ pIsoXfer->dev = p_dev;
+ memcpy(pIsoXfer->packet, p_packet, length);
+ pipe = usb_sndisocpipe(p_dev->p_udev, p_dev->p_voice_out->desc.bEndpointAddress);
+ p_urb->complete = btusb_voicetx_complete;
+ p_urb->context = pIsoXfer;
+ p_urb->dev = p_dev->p_udev;
+ p_urb->pipe = pipe;
+ p_urb->interval = p_dev->p_voice_out->desc.bInterval;
+ p_urb->transfer_buffer = pIsoXfer->packet;
+ p_urb->transfer_buffer_length = length;
+ btusb_fill_iso_pkts(p_urb, length, packet_size);
+ // p_urb->transfer_flags = 0;
+ p_urb->transfer_flags = URB_ISO_ASAP;
+ cur_frame_number = usb_get_current_frame_number(p_dev->p_udev);
+
+ BTUSB_INFO("len %lu idx %lu frm %u\n", length, pIsoXfer->index, cur_frame_number);
+ pIsoXfer->used = 1;
+ status = usb_submit_urb(p_urb, GFP_ATOMIC);
+ if (status)
+ {
+ BTUSB_ERR("usb_submit_urb failed %d\n", status);
+ p_dev->stats.voicetx_submitted_error++;
+ pIsoXfer->used = 0;
+ }
+ else
+ {
+ p_dev->stats.voicetx_submitted++;
+ BTUSB_DBG("success\n");
+ }
+
+ return(status);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_set_voice
+ **
+ ** Description Change voice interface setting processor
+ ** NOTE: Must be called at low execution level
+ **
+ ** Parameters p_dev: pointer to the device control block
+ ** setting_number: new voice interface setting number
+ ** submit_urb: true if the URBs must be submitted
+ **
+ ** Returns 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_set_voice(tBTUSB_CB *p_dev, unsigned char setting_number,
+ bool submit_urb)
+{
+ int idx;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+
+ BTUSB_DBG("setting_number=%d submit_urb=%u\n", setting_number, submit_urb);
+
+ // cancel all voice requests before switching buffers
+ p_dev->p_voice_in = NULL;
+ p_dev->p_voice_out = NULL;
+ btusb_cancel_voice(p_dev);
+
+ // configure the voice interface to the proper setting
+ if (usb_set_interface(p_dev->p_udev, 1, setting_number))
+ {
+ BTUSB_ERR("failed to set iso intf to %u\n", setting_number);
+ return -EFAULT;
+ }
+
+ // find the endpoints
+ p_host_intf = p_dev->p_voice_intf->cur_altsetting;
+
+ for (idx = 0; idx < p_host_intf->desc.bNumEndpoints; idx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[idx].desc;
+ if (usb_endpoint_type(p_ep_desc) == USB_ENDPOINT_XFER_ISOC)
+ {
+ if (usb_endpoint_dir_in(p_ep_desc))
+ {
+ p_dev->p_voice_in = &p_host_intf->endpoint[idx];
+ }
+ else
+ {
+ p_dev->p_voice_out = &p_host_intf->endpoint[idx];
+ }
+ }
+ }
+
+ if (!p_dev->p_voice_in || !p_dev->p_voice_out)
+ {
+ BTUSB_ERR("no iso pipes found!\n");
+ return -EFAULT;
+ }
+
+ if (submit_urb)
+ {
+ btusb_update_voice_rx(p_dev);
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_add_voice_channel
+ **
+ ** Description Add a voice channel in the list of current channels
+ **
+ ** Parameters p_dev: pointer to the device control structure
+ ** sco_handle: handle of the synchronous connection carrying voice
+ ** burst: size of the voice bursts
+ **
+ ** Returns Return 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_add_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle, unsigned char burst)
+{
+ int idx;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ if (!p_dev->p_voice_intf)
+ {
+ BTUSB_ERR("No voice interface detected\n");
+ return -EOPNOTSUPP;
+ }
+
+ // kludge to support the backward compatibility with older BTKRNLs
+ // not supplying the packet size...
+ if (burst == 0)
+ {
+ BTUSB_INFO("fixing legacy req to 48\n");
+ burst = BTUSB_VOICE_BURST_SIZE;
+ }
+
+ // look for an available voice channel entry
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (!p_chan->used)
+ {
+ p_chan->info.sco_handle = sco_handle;
+ p_chan->info.burst = burst;
+ p_chan->used = 1;
+ goto found;
+ }
+ }
+ BTUSB_ERR("Could not find empty slot in internal tables\n");
+ return -EMLINK;
+
+found:
+ if (btusb_update_voice_channels(p_dev))
+ {
+ BTUSB_ERR("Failed adding voice channel\n");
+ // failure, remove the channel just added
+ btusb_remove_voice_channel(p_dev, sco_handle);
+ return -ENOMEM;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_remove_voice_channel
+ **
+ ** Description Remove a voice channel from the list of current channels
+ **
+ ** Parameters p_dev: pointer to the device control structure
+ ** sco_handle: handle of the synchronous connection carrying voice
+ **
+ ** Returns Return 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_remove_voice_channel(tBTUSB_CB *p_dev, unsigned short sco_handle)
+{
+ int idx;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ if (!p_dev->p_voice_intf)
+ {
+ BTUSB_ERR("No voice interface detected\n");
+ return -EOPNOTSUPP;
+ }
+
+ // find the channel to be removed
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->used && (p_chan->info.sco_handle == sco_handle))
+ {
+ p_chan->used = 0;
+ goto found;
+ }
+ }
+ BTUSB_ERR("Could not find SCO handle in internal tables\n");
+ return -ENOENT;
+
+found:
+ return btusb_update_voice_channels(p_dev);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_update_voice_channels
+ **
+ ** Description Voice channels just updated, reconfigure
+ **
+ ** Parameters p_dev: pointer to the device control structure
+ **
+ ** Returns Return 0 upon success, error code otherwise
+ **
+ *******************************************************************************/
+static int btusb_update_voice_channels(tBTUSB_CB *p_dev)
+{
+ int idx, jdx;
+ unsigned char min_burst, max_burst, num_voice_chan, voice_setting;
+ unsigned short desired_packet_size, packet_size;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+
+ BTUSB_DBG("\n");
+
+ // get the number of voice channels and the size information
+ num_voice_chan = 0;
+ min_burst = 0xFF;
+ max_burst = 0;
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->used)
+ {
+ num_voice_chan++;
+ min_burst = min(min_burst, p_chan->info.burst);
+ max_burst = max(max_burst, p_chan->info.burst);
+ }
+ }
+
+ BTUSB_DBG("num_voice_chan=%d\n", num_voice_chan);
+ // now calculate a desired_packet_size
+ switch (num_voice_chan)
+ {
+ case 0:
+ desired_packet_size = 0;
+ break;
+
+ case 1:
+ // single channel: we just need a third of the length (rounded up so we add 2 before dividing)
+ desired_packet_size = ((max_burst + BTUSB_VOICE_HEADER_SIZE) + 2) / 3;
+ break;
+
+ case 2:
+ // two channels: we need the smaller one to fit in completely
+ // and the larger one to fit in into two...
+ packet_size = (max_burst + BTUSB_VOICE_HEADER_SIZE + 1) / 2;
+
+ desired_packet_size = min_burst + BTUSB_VOICE_HEADER_SIZE;
+ if (packet_size > desired_packet_size)
+ desired_packet_size = packet_size;
+ break;
+
+ case 3:
+ // three channels - we need all of them to fit into a single packet
+ desired_packet_size = max_burst + BTUSB_VOICE_HEADER_SIZE;
+ break;
+
+ default:
+ // this can not happen
+ BTUSB_ERR("invalid # (%d) of channels, failing...\n", num_voice_chan);
+ return 0;
+ }
+
+ BTUSB_DBG("desired packet size is %u\n", desired_packet_size);
+
+ // now convert the desired_packet_size into the interface setting number
+ packet_size = BTUSB_USHRT_MAX;
+ voice_setting = 0;
+ for (idx = 0; idx < p_dev->p_voice_intf->num_altsetting; idx++)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[idx];
+ for (jdx = 0; jdx < p_host_intf->desc.bNumEndpoints; jdx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[jdx].desc;
+ if ((usb_endpoint_type(p_ep_desc) == USB_ENDPOINT_XFER_ISOC) &&
+ usb_endpoint_dir_in(p_ep_desc))
+ {
+ // if the MaxPacketSize is large enough and if it is smaller
+ // than the current setting
+ if ((desired_packet_size <= le16_to_cpu(p_ep_desc->wMaxPacketSize)) &&
+ (le16_to_cpu(p_ep_desc->wMaxPacketSize) < packet_size))
+ {
+ packet_size = le16_to_cpu(p_ep_desc->wMaxPacketSize);
+ voice_setting = p_host_intf->desc.bAlternateSetting;
+ }
+ }
+ }
+ }
+ if (packet_size == BTUSB_USHRT_MAX)
+ {
+ BTUSB_ERR("no appropriate ISO interface setting found, failing...\n");
+ return -ERANGE;
+ }
+
+ BTUSB_DBG("desired_packet_size=%d voice_setting=%d\n", desired_packet_size, voice_setting);
+ // store the desired packet size
+ p_dev->desired_packet_size = desired_packet_size;
+
+ // set the voice setting and only submit the URBs if there is a channel
+ return btusb_set_voice(p_dev, voice_setting, num_voice_chan != 0);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_debug_show
+ **
+ ** Description Function called when reading the /proc file created by our driver
+ **
+ *******************************************************************************/
+#define BTUSB_STATS(__n) \
+ seq_printf(s, " - " #__n " = %lu\n", p_dev->stats.__n)
+
+static int btusb_debug_show(struct seq_file *s, void *unused)
+{
+ tBTUSB_CB *p_dev = s->private;
+ struct usb_device *udev = p_dev->p_udev;
+ struct usb_host_interface *p_host_intf;
+ struct usb_endpoint_descriptor *p_ep_desc;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+ int idx, jdx;
+
+ seq_printf(s, "USB device :\n");
+ seq_printf(s, " - Match info:\n");
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_VENDOR)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_VENDOR (0x%02X)\n", p_dev->p_id->idVendor);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_PRODUCT)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_PRODUCT 0x%02X)\n", p_dev->p_id->idProduct);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_LO)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_LO (%u)\n", p_dev->p_id->bcdDevice_lo);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_HI)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_HI (%u)\n", p_dev->p_id->bcdDevice_hi);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_CLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_CLASS (0x%02X)\n", p_dev->p_id->bDeviceClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_SUBCLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_SUBCLASS (0x%02X)\n", p_dev->p_id->bDeviceSubClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_DEV_PROTOCOL)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_DEV_PROTOCOL (0x%02X)\n", p_dev->p_id->bDeviceProtocol);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_CLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_CLASS (0x%02X)\n", p_dev->p_id->bInterfaceClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_SUBCLASS)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_SUBCLASS (0x%02X)\n", p_dev->p_id->bInterfaceSubClass);
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_PROTOCOL)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_PROTOCOL (0x%02X)\n", p_dev->p_id->bInterfaceProtocol);
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(3, 6, 0)
+ if (p_dev->p_id->match_flags & USB_DEVICE_ID_MATCH_INT_NUMBER)
+ seq_printf(s, " * USB_DEVICE_ID_MATCH_INT_NUMBER (%u)\n", p_dev->p_id->bInterfaceNumber);
+#endif
+
+ seq_printf(s, " - Address = %d\n", udev->devnum);
+ seq_printf(s, " - VendorId = %04x\n", le16_to_cpu(udev->descriptor.idVendor));
+ seq_printf(s, " - ProductId = %04x\n", le16_to_cpu(udev->descriptor.idProduct));
+ seq_printf(s, " - Manufacturer String = %s\n", udev->manufacturer);
+ seq_printf(s, " - Product String = %s\n", udev->product);
+ seq_printf(s, " - USB bus number = %d\n", udev->bus->busnum);
+ seq_printf(s, " - USB devpath = %s\n", udev->devpath);
+ seq_printf(s, " - USB devnum = %d\n", udev->devnum);
+ seq_printf(s, " - USB ttport = %d\n", udev->ttport);
+ seq_printf(s, " - Interfaces :\n");
+ seq_printf(s, " * MAIN : ");
+ if (p_dev->p_main_intf)
+ {
+ seq_printf(s, "intf = %d (nb alt settings = %d, ",
+ p_dev->p_main_intf->cur_altsetting->desc.bInterfaceNumber,
+ p_dev->p_main_intf->num_altsetting);
+ seq_printf(s, "cur alt setting = %d)\n", p_dev->p_main_intf->cur_altsetting->desc.bAlternateSetting);
+ seq_printf(s, " * HCI EVENT : ");
+ if (p_dev->p_event_in)
+ {
+ seq_printf(s, "ep = 0x%02x\n", p_dev->p_event_in->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "ERROR (endpoint not found)\n");
+ }
+ seq_printf(s, " * ACL RX : ");
+ if (p_dev->p_acl_in)
+ {
+ seq_printf(s, "ep = 0x%02x\n", p_dev->p_event_in->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "ERROR (endpoint not found)\n");
+ }
+ seq_printf(s, " * ACL TX : ");
+ if (p_dev->p_acl_out)
+ {
+ seq_printf(s, "ep = 0x%02x\n", p_dev->p_acl_out->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "ERROR (endpoint not found)\n");
+ }
+ }
+ else
+ {
+
+ }
+ seq_printf(s, " * VOICE :");
+ if (p_dev->p_voice_intf)
+ {
+ seq_printf(s, " intf = %d (nb alt setting = %d, ", p_dev->p_voice_intf->cur_altsetting->desc.bInterfaceNumber, p_dev->p_voice_intf->num_altsetting);
+ seq_printf(s, "cur alt setting = %d)\n", p_dev->p_voice_intf->cur_altsetting->desc.bAlternateSetting);
+ for (idx = 0; idx < p_dev->p_voice_intf->num_altsetting; idx++)
+ {
+ p_host_intf = &p_dev->p_voice_intf->altsetting[idx];
+ seq_printf(s, " * alt setting %d (idx %d) : %d enpoints\n",
+ p_host_intf->desc.bAlternateSetting, idx, p_host_intf->desc.bNumEndpoints);
+ for (jdx = 0; jdx < p_host_intf->desc.bNumEndpoints; jdx++)
+ {
+ p_ep_desc = &p_host_intf->endpoint[jdx].desc;
+ seq_printf(s, " * ep = 0x%02x : ", p_ep_desc->bEndpointAddress);
+ if (usb_endpoint_type(p_ep_desc) == USB_ENDPOINT_XFER_ISOC)
+ {
+ seq_printf(s, "Isoch ");
+ if (usb_endpoint_dir_out(p_ep_desc))
+ {
+ seq_printf(s, "(OUT) ");
+ }
+ else
+ {
+ seq_printf(s, "(IN) ");
+ }
+ seq_printf(s, "wMaxPacketSize = %d\n", le16_to_cpu(p_ep_desc->wMaxPacketSize));
+ }
+ else
+ {
+ seq_printf(s, "not isochronous endpoint\n");
+ }
+ }
+ }
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+ seq_printf(s, " * DIAG RX : ");
+ if (p_dev->p_diag_in)
+ {
+ seq_printf(s, "intf = %d ep = 0x%02x\n", p_dev->p_diag_intf->cur_altsetting->desc.bInterfaceNumber, p_dev->p_diag_in->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+ seq_printf(s, " * DIAG TX : ");
+ if (p_dev->p_diag_out)
+ {
+ seq_printf(s, "intf = %d ep = 0x%02x\n", p_dev->p_diag_intf->cur_altsetting->desc.bInterfaceNumber, p_dev->p_diag_out->desc.bEndpointAddress);
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+ seq_printf(s, " * DFU : ");
+ if (p_dev->p_dfu_intf)
+ {
+ seq_printf(s, "intf = %d\n", p_dev->p_dfu_intf->cur_altsetting->desc.bInterfaceNumber);
+ }
+ else
+ {
+ seq_printf(s, "Not present\n");
+ }
+
+ seq_printf(s, "Memory usage :\n");
+ seq_printf(s, " - p_dev = %p\n", p_dev);
+ seq_printf(s, " - size = %zd\n", sizeof(*p_dev));
+ seq_printf(s, " * CMD = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, cmd_array), sizeof(p_dev->cmd_array));
+ seq_printf(s, " * EVENT = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, event_array), sizeof(p_dev->event_array));
+ seq_printf(s, " * ACL RX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, acl_rx_array), sizeof(p_dev->acl_rx_array));
+ seq_printf(s, " * ACL TX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, acl_tx_array), sizeof(p_dev->acl_tx_array));
+ seq_printf(s, " * DIAG RX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, diag_rx_array), sizeof(p_dev->diag_rx_array));
+ seq_printf(s, " * DIAG TX = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, diag_tx_array), sizeof(p_dev->diag_tx_array));
+ seq_printf(s, " * VOICE = off:%zd/size=%zd\n", offsetof(tBTUSB_CB, voice_channels), offsetof(tBTUSB_CB, rx_queue)-offsetof(tBTUSB_CB, voice_channels));
+
+ seq_printf(s, "Status :\n");
+ seq_printf(s, " - issharedusb = %u\n", p_dev->issharedusb);
+ seq_printf(s, " - quirks = %u\n", p_dev->quirks);
+ seq_printf(s, " - opened = %d\n", p_dev->opened);
+ seq_printf(s, "Voice :\n");
+ // calculate number of voice sample per timer expiration
+ // HZ could be 100, 250 or 1000
+ if ((1000 / HZ) <= BTUSB_VOICE_DELAY)
+ {
+ seq_printf(s, " - number of voice samples per timer expiration = 1\n");
+ }
+ else
+ {
+ seq_printf(s, " - number of voice samples per timer expiration = %d\n",
+ (1000 / (HZ * BTUSB_VOICE_DELAY)));
+ }
+ jdx = 0;
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if (p_chan->used)
+ {
+ seq_printf(s, " - channel %d : SCO handle = %d(0x%02x) burst = %d\n", idx,
+ p_chan->info.sco_handle, p_chan->info.sco_handle, p_chan->info.burst);
+ jdx = 1;
+ }
+ }
+ if (jdx)
+ {
+ seq_printf(s, " - desired_packet_size = %d\n", p_dev->desired_packet_size);
+ }
+ else
+ {
+ seq_printf(s, " - No active channels\n");
+ }
+ seq_printf(s, "Statistics :\n");
+ BTUSB_STATS(urb_submit_ok);
+ BTUSB_STATS(urb_submit_err);
+ BTUSB_STATS(acl_rx_submit_ok);
+ BTUSB_STATS(acl_rx_submit_err);
+ BTUSB_STATS(acl_rx_completed);
+ BTUSB_STATS(acl_rx_resubmit);
+ BTUSB_STATS(acl_rx_bytes);
+ BTUSB_STATS(event_submit_ok);
+ BTUSB_STATS(event_submit_err);
+ BTUSB_STATS(event_completed);
+ BTUSB_STATS(event_resubmit);
+ BTUSB_STATS(event_bytes);
+ BTUSB_STATS(diag_rx_submit_ok);
+ BTUSB_STATS(diag_rx_submit_err);
+ BTUSB_STATS(diag_rx_completed);
+ BTUSB_STATS(diag_rx_resubmit);
+ BTUSB_STATS(diag_rx_bytes);
+ BTUSB_STATS(diag_rx_bytes);
+ BTUSB_STATS(writes_submitted);
+ BTUSB_STATS(writes_submitted_error);
+ BTUSB_STATS(writes_completed);
+ BTUSB_STATS(writes_completed_error);
+ BTUSB_STATS(commands_submitted);
+ BTUSB_STATS(commands_submitted_error);
+ BTUSB_STATS(commands_completed);
+ BTUSB_STATS(commands_completed_error);
+ BTUSB_STATS(voicerx_submitted);
+ BTUSB_STATS(voicerx_submitted_error);
+ BTUSB_STATS(voicerx_completed);
+ BTUSB_STATS(voicerx_completed_error);
+ BTUSB_STATS(voicerx_bad_packets);
+ BTUSB_STATS(voicerx_disc_nohdr);
+ BTUSB_STATS(voicerx_split_hdr);
+ BTUSB_STATS(voicerx_raw_bytes);
+ BTUSB_STATS(voicerx_skipped_bytes);
+ BTUSB_STATS(voicetx_submitted);
+ BTUSB_STATS(voicetx_submitted_error);
+ BTUSB_STATS(voicetx_completed);
+ BTUSB_STATS(voicetx_completed_error);
+ BTUSB_STATS(voicetx_disc_nobuf);
+ BTUSB_STATS(voicetx_disc_toolong);
+ BTUSB_STATS(voice_tx_cnt);
+ BTUSB_STATS(voice_max_tx_cnt);
+
+ {
+ struct btusb_scosniff *p, *n;
+ seq_printf(s, "SCO sniffing:\n");
+ seq_printf(s, " - list: %p\n", &p_dev->scosniff_list);
+ seq_printf(s, " - list.next: %p\n", p_dev->scosniff_list.next);
+ seq_printf(s, " - list.prev: %p\n", p_dev->scosniff_list.prev);
+ seq_printf(s, " - whole list:\n");
+ list_for_each_entry_safe(p, n, &p_dev->scosniff_list, lh)
+ {
+ seq_printf(s, " > %p\n", p);
+ }
+ }
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_debug_write
+ **
+ ** Description Write handler of the debug /proc interface
+ **
+ *******************************************************************************/
+ssize_t btusb_debug_write(struct file *file, const char *buf,
+ size_t count, loff_t *pos)
+{
+ struct seq_file *s = file->private_data;
+ tBTUSB_CB *p_dev = s->private;
+ unsigned char cmd;
+
+ // copy the first byte from the data written
+ if (copy_from_user(&cmd, buf, 1))
+ {
+ return -EFAULT;
+ }
+
+ // unconditional print on purpose
+ BTUSB_INFO("'%c'\n", cmd);
+
+ switch (cmd)
+ {
+ case '0':
+ // reset the stats
+ memset(&p_dev->stats, 0, sizeof(p_dev->stats));
+ break;
+ case '1':
+ btusb_add_voice_channel(p_dev, 6, BTUSB_VOICE_BURST_SIZE);
+ break;
+
+ case '2':
+ btusb_remove_voice_channel(p_dev, 6);
+ break;
+
+ case '3':
+ if (p_dev->scosniff_active)
+ {
+ struct btusb_scosniff *bs;
+ bs = kmalloc(sizeof(*bs), GFP_ATOMIC);
+ if (bs)
+ {
+
+ BTUSB_INFO("SCOSNIFF: adding %p\n", bs);
+ bs->n = 0;
+ list_add_tail(&bs->lh, &p_dev->scosniff_list);
+ complete(&p_dev->scosniff_completion);
+ }
+ }
+ break;
+
+#ifdef BTUSB_LITE
+ case '4':
+ BTUSB_INFO("Mute PCM0\n");
+ pcm0_mute = 1;
+ break;
+
+ case '5':
+ BTUSB_INFO("Unmute PCM0\n");
+ pcm0_mute = 0;
+ break;
+#endif
+
+ default:
+ break;
+ }
+
+ return count;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_debug_open
+ **
+ ** Description Open handler of the debug /proc interface
+ **
+ *******************************************************************************/
+int btusb_debug_open(struct inode *inode, struct file *file)
+{
+ return single_open(file, btusb_debug_show, BTUSB_PDE_DATA(inode));
+}
+
+static void * btusb_scosniff_start(struct seq_file *s, loff_t *pos)
+{
+ tBTUSB_CB *p_dev = s->private;
+ struct btusb_scosniff *bs;
+ int rv;
+
+ BTUSB_INFO("waiting %p\n", p_dev);
+ rv = wait_for_completion_interruptible(&p_dev->scosniff_completion);
+ if (rv < 0)
+ return NULL;
+
+ BTUSB_INFO("triggered\n");
+
+ if (!list_empty(&p_dev->scosniff_list))
+ {
+ bs = list_first_entry(&p_dev->scosniff_list, struct btusb_scosniff, lh);
+
+ // remove the element from the list
+ list_del(&bs->lh);
+ BTUSB_INFO("receiving %p\n", bs);
+
+ return bs;
+ }
+ return NULL;
+}
+
+static void btusb_scosniff_stop(struct seq_file *s, void *v)
+{
+ BTUSB_INFO("stop\n");
+}
+
+static void * btusb_scosniff_next(struct seq_file *s, void *v, loff_t *pos)
+{
+ struct btusb_scosniff *bs = v;
+ BTUSB_INFO("next\n");
+
+ kfree(bs);
+
+ (*pos)++;
+
+ /* if you do not want to buffer the data, just return NULL, otherwise, call start
+ * again in order to use as much of the allocated PAGE in seq_read
+ *
+ * optional:
+ * return btusb_scosniff_start(s, pos);
+ */
+ return NULL;
+}
+
+ static int btusb_scosniff_show(struct seq_file *s, void *v)
+{
+ struct btusb_scosniff *bs = v;
+ unsigned int i, j;
+ unsigned char *p_buf, *p_c;
+ unsigned char c;
+ struct usb_iso_packet_descriptor *p_uipd;
+ const char hexdigit[16] = {'0','1','2','3','4','5','6','7','8','9','a','b','c','d','e','f'};
+
+ seq_printf(s, "%u %u %d \n", bs->n, bs->l, bs->s);
+ p_buf = (unsigned char *)&bs->d[bs->n];
+ for (i = 0; i < bs->n; i++)
+ {
+ p_uipd = &bs->d[i];
+ seq_printf(s, " %d %u %u %u\n", p_uipd->status, p_uipd->actual_length, p_uipd->length, p_uipd->offset);
+ for (j = 0, p_c = &p_buf[p_uipd->offset]; j < p_uipd->actual_length; j++, p_c++)
+ {
+ c = *p_c;
+ seq_putc(s, hexdigit[c >> 4]);
+ seq_putc(s, hexdigit[c & 0xF]);
+ seq_putc(s, ' ');
+ }
+ seq_putc(s, '\n');
+ }
+
+ return 0;
+}
+
+static const struct seq_operations btusb_scosniff_seq_ops = {
+ .start = btusb_scosniff_start,
+ .next = btusb_scosniff_next,
+ .stop = btusb_scosniff_stop,
+ .show = btusb_scosniff_show,
+};
+
+int btusb_scosniff_open(struct inode *inode, struct file *file)
+{
+ int rv;
+ tBTUSB_CB *p_dev = BTUSB_PDE_DATA(inode);
+
+ rv = seq_open(file, &btusb_scosniff_seq_ops);
+ if (!rv)
+ {
+ p_dev->scosniff_active = true;
+ ((struct seq_file *)file->private_data)->private = p_dev;
+ }
+ return rv;
+}
+
+int btusb_scosniff_release(struct inode *inode, struct file *file)
+{
+ struct btusb_scosniff *p, *n;
+ tBTUSB_CB *p_dev = BTUSB_PDE_DATA(inode);
+
+ p_dev->scosniff_active = false;
+
+ list_for_each_entry_safe(p, n, &p_dev->scosniff_list, lh)
+ {
+ list_del(&p->lh);
+ kfree(p);
+ }
+
+ return seq_release(inode, file);
+}
diff --git a/btusb_1_6_29_1/src/btusb_isoc.c b/btusb_1_6_29_1/src/btusb_isoc.c
new file mode 100755
index 0000000..bc3acff
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb_isoc.c
@@ -0,0 +1,311 @@
+/*
+ *
+ * btusb_isoc.c
+ *
+ *
+ *
+ * Copyright (C) 2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+// for kmalloc
+#include <linux/slab.h>
+#include "btusb.h"
+#include "hcidefs.h"
+
+/*******************************************************************************
+ **
+ ** Function btusb_isoc_reset_msg
+ **
+ ** Description Reset the currently receiving voice message
+ **
+ ** Parameters p_dev: device instance control block
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_isoc_reset_msg(tBTUSB_CB *p_dev)
+{
+ p_dev->pending_bytes = 0;
+ if (p_dev->pp_pending_msg && *p_dev->pp_pending_msg)
+ {
+ GKI_freebuf(*p_dev->pp_pending_msg);
+ }
+ p_dev->pp_pending_msg = NULL;
+ p_dev->pending_hdr_size = 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_isoc_check_hdr
+ **
+ ** Description Check the packet header
+ **
+ ** Parameters p_dev: device instance control block
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static bool btusb_isoc_check_hdr(tBTUSB_CB *p_dev)
+{
+ unsigned char *p_data = p_dev->pending_hdr;
+ int idx;
+ unsigned short sco_handle;
+ unsigned char size;
+ BT_HDR *p_hdr;
+ tBTUSB_VOICE_CHANNEL *p_chan;
+
+ STREAM_TO_UINT16(sco_handle, p_data);
+ sco_handle &= 0x0fff;
+ STREAM_TO_UINT8(size, p_data);
+
+ for (idx = 0; idx < ARRAY_SIZE(p_dev->voice_channels); idx++)
+ {
+ p_chan = &p_dev->voice_channels[idx];
+ if ((p_chan->used) &&
+ (sco_handle == p_chan->info.sco_handle) &&
+ (size <= (2 * p_chan->info.burst)))
+ {
+ // check if there is already a message being consolidated
+ if (unlikely(p_chan->p_msg == NULL))
+ {
+ p_hdr = (BT_HDR *) GKI_getpoolbuf(HCI_SCO_POOL_ID);
+ if (unlikely(p_hdr == NULL))
+ {
+ return false;
+ }
+ p_hdr->event = BT_EVT_TO_BTU_HCI_SCO;
+ p_hdr->len = 1 + BTUSB_VOICE_HEADER_SIZE; // sizeof(data_type) + SCO header
+ p_hdr->offset = 0;
+ p_hdr->layer_specific = 0;
+
+ p_data = (void *) (p_hdr + 1);
+
+ // add data type
+ UINT8_TO_STREAM(p_data, HCIT_TYPE_SCO_DATA);
+ UINT16_TO_STREAM(p_data, sco_handle);
+
+ p_chan->p_msg = p_hdr;
+ }
+ p_dev->pending_bytes = size;
+ p_dev->pp_pending_msg = &p_chan->p_msg;
+
+ return true;
+ }
+ }
+ return false;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_isoc_check_msg
+ **
+ ** Description Check the currently receiving message
+ **
+ ** Parameters p_dev: device instance control block
+ ** pp_hdr: pointer to the receiving message
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+static void btusb_isoc_check_msg(tBTUSB_CB *p_dev, BT_HDR **pp_hdr)
+{
+ BT_HDR *p_hdr = *pp_hdr;
+ unsigned char *p_data;
+
+ // if enough data was received
+ if (unlikely(p_hdr->len >= (1 + BTUSB_VOICE_HEADER_SIZE + SCO_RX_MAX_LEN)))
+ {
+ p_data = (void *)(p_hdr + 1);
+ p_data[BTUSB_VOICE_HEADER_SIZE] = p_hdr->len - BTUSB_VOICE_HEADER_SIZE - 1;
+ GKI_enqueue(&p_dev->rx_queue, p_hdr);
+
+ // notify RX event(in case of select/poll
+ wake_up_interruptible(&p_dev->rx_wait_q);
+
+ *pp_hdr = NULL;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_voicerx_complete
+ **
+ ** Description Voice read (iso pipe) completion routine.
+ **
+ ** Parameters
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_voicerx_complete(struct urb *p_urb)
+{
+ tBTUSB_TRANSACTION *p_trans = p_urb->context;
+ tBTUSB_CB *p_dev = p_trans->context;
+ BT_HDR **pp_hdr, *p_hdr;
+ unsigned int length, packet_length;
+ unsigned char *p_packet, *p_frame, *p_data;
+ struct usb_iso_packet_descriptor *p_uipd, *p_end;
+
+ BTUSB_INFO("enter");
+
+ btusb_voice_stats(&(p_dev->stats.voice_max_rx_rdy_delta_time), &(p_dev->stats.voice_min_rx_rdy_delta_time),
+ &(p_dev->stats.voice_rx_rdy_delta_time), &(p_dev->stats.voice_last_rx_rdy_ts));
+
+ p_dev->stats.voicerx_completed++;
+
+ if (unlikely(!p_dev->p_main_intf || !p_dev->p_voice_in))
+ {
+ BTUSB_DBG("intf is down\n");
+ return;
+ }
+
+ // entire URB error?
+ if (unlikely(p_urb->status))
+ {
+ BTUSB_ERR("failure %d\n", p_urb->status);
+ p_dev->stats.voicerx_completed_error++;
+ return;
+ }
+
+ if (unlikely(p_dev->scosniff_active))
+ {
+ struct btusb_scosniff *bs;
+
+ bs = kmalloc(sizeof(struct btusb_scosniff) +
+ (p_urb->number_of_packets * sizeof(p_urb->iso_frame_desc[0])) +
+ p_urb->transfer_buffer_length, GFP_ATOMIC);
+ if (bs)
+ {
+ bs->s = p_urb->start_frame;
+ bs->n = p_urb->number_of_packets;
+ bs->l = p_urb->transfer_buffer_length;
+ // copy the descriptors
+ memcpy(bs->d, p_urb->iso_frame_desc, bs->n * sizeof(p_urb->iso_frame_desc[0]));
+ // then copy the content of the buffer
+ memcpy(&bs->d[bs->n], p_urb->transfer_buffer, bs->l);
+ list_add_tail(&bs->lh, &p_dev->scosniff_list);
+ complete(&p_dev->scosniff_completion);
+ }
+ else
+ {
+ BTUSB_ERR("Failed allocating scosniff buffer");
+ }
+ }
+
+ p_frame = p_urb->transfer_buffer;
+ p_end = &p_urb->iso_frame_desc[p_urb->number_of_packets];
+ for (p_uipd = p_urb->iso_frame_desc; p_uipd < p_end; p_uipd++)
+ {
+ if (unlikely(p_uipd->status))
+ {
+ p_dev->stats.voicerx_bad_packets++;
+ // should we do something if there is expected data?
+ continue;
+ }
+
+ p_packet = p_frame + p_uipd->offset;
+ packet_length = p_uipd->actual_length;
+ p_dev->stats.voicerx_raw_bytes += packet_length;
+
+ // waiting for data?
+ if (likely(p_dev->pending_bytes))
+ {
+ fill_data:
+ if (likely(p_dev->pending_bytes >= packet_length))
+ {
+ length = packet_length;
+ }
+ else
+ {
+ length = p_dev->pending_bytes;
+ }
+ pp_hdr = p_dev->pp_pending_msg;
+ p_hdr = *pp_hdr;
+ p_data = (void *)(p_hdr + 1) + p_hdr->len;
+ // add data at the tail of the current message
+ memcpy(p_data, p_packet, length);
+ p_hdr->len += length;
+
+ // decrement the number of bytes remaining
+ p_dev->pending_bytes -= length;
+ if (likely(p_dev->pending_bytes))
+ {
+ // data still needed -> next descriptor
+ continue;
+ }
+ // no more pending bytes, check if it is full
+ btusb_isoc_check_msg(p_dev, pp_hdr);
+ packet_length -= length;
+ if (likely(!packet_length))
+ continue;
+ // more bytes -> increment pointer
+ p_packet += length;
+ }
+
+ // if there is still data in the packet
+ if (likely(packet_length))
+ {
+ // at this point, there is NO SCO packet pending
+ if (likely(packet_length >= (BTUSB_VOICE_HEADER_SIZE - p_dev->pending_hdr_size)))
+ {
+ length = BTUSB_VOICE_HEADER_SIZE - p_dev->pending_hdr_size;
+ }
+ else
+ {
+ length = packet_length;
+ }
+
+ // fill the hdr (in case header is split across descriptors)
+ memcpy(&p_dev->pending_hdr[p_dev->pending_hdr_size], p_packet, length);
+ p_dev->pending_hdr_size += length;
+
+ if (likely(p_dev->pending_hdr_size == BTUSB_VOICE_HEADER_SIZE))
+ {
+ p_dev->pending_hdr_size = 0;
+
+ if (likely(btusb_isoc_check_hdr(p_dev)))
+ {
+ p_packet += length;
+ packet_length -= length;
+ // a correct header was found, get the data
+ goto fill_data;
+ }
+ p_dev->stats.voicerx_disc_nohdr++;
+ p_dev->stats.voicerx_skipped_bytes += packet_length;
+ // this is not a correct header -> next descriptor
+ continue;
+ }
+ else if (likely(p_dev->pending_hdr_size < BTUSB_VOICE_HEADER_SIZE))
+ {
+ p_dev->stats.voicerx_split_hdr++;
+ // header not complete -> next descriptor
+ continue;
+ }
+ else
+ {
+ BTUSB_ERR("ISOC Header larger than possible. This is a major failure.\n");
+ btusb_isoc_reset_msg(p_dev);
+ }
+ }
+ }
+
+ btusb_submit_voice_rx(p_dev, p_trans, GFP_ATOMIC);
+}
+
diff --git a/btusb_1_6_29_1/src/btusb_lite.c b/btusb_1_6_29_1/src/btusb_lite.c
new file mode 100755
index 0000000..f6d1374
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb_lite.c
@@ -0,0 +1,1794 @@
+/*
+ *
+ * btusb_lite.c
+ *
+ *
+ *
+ * Copyright (C) 2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#include <linux/proc_fs.h>
+#include <linux/poll.h>
+
+#include "btusb.h"
+#include "bd.h"
+
+
+/*
+ * Defines
+ */
+
+#define BTUSB_LITE_IPC_AVDT_SYNC_INFO_RSP_LEN (1 + BTM_SYNC_INFO_NUM_STR * (1+6+2+2+1+2))
+
+/*
+ * Local functions
+ */
+static void btusb_lite_init(struct btusb_cb *p_dev);
+static int btusb_lite_open(struct inode *inode, struct file *file);
+static int btusb_lite_close(struct inode *inode, struct file *file);
+static ssize_t btusb_lite_write(struct file *file, const char *buf, size_t count,
+ loff_t *p_off);
+static ssize_t btusb_lite_read(struct file *file, char __user *buffer, size_t count,
+ loff_t *p_off);
+static unsigned int btusb_lite_poll(struct file *file, struct poll_table_struct *p_pt);
+
+static BT_HDR *btusb_lite_msg_to_app_get(struct btusb_cb *p_dev);
+static void btusb_lite_msg_to_app_free(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static UINT8 *btusb_lite_msg_to_app_get_data_addr(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+static char *btusb_lite_ipc_event_desc(UINT16 event);
+
+static void btusb_lite_ipc_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_hci_cmd_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_hci_acl_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_mgt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_btu_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_btm_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_l2c_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_ipc_avdt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+static void btusb_lite_ipc_rsp_send(struct btusb_cb *p_dev, UINT16 event, UINT8 op_code,
+ UINT8 *p_param, UINT8 param_len);
+static void btusb_lite_ipc_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len);
+static void btusb_lite_ipc_avdt_sync_info_send(struct btusb_cb *p_dev,
+ tAVDT_SYNC_INFO *p_sync_rsp);
+
+static void btusb_lite_ipc_sent_to_user(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+/*
+ * Globals
+ */
+static const struct file_operations btusb_lite_fops =
+{
+ .open = btusb_lite_open,
+ .read = btusb_lite_read,
+ .poll = btusb_lite_poll,
+ .write = btusb_lite_write,
+ .release = btusb_lite_close,
+};
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_open
+ **
+ ** Description Open BTUSB Lite interface
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static void btusb_lite_init(struct btusb_cb *p_dev)
+{
+ struct proc_dir_entry *p_lite_pde;
+
+ /* Save p_lite_pde */
+ p_lite_pde = p_dev->lite_cb.p_lite_pde;
+
+ /* Clear Control Block */
+ memset(&p_dev->lite_cb, 0x00, sizeof(p_dev->lite_cb));
+
+ /* Restore p_lite_pde */
+ p_dev->lite_cb.p_lite_pde = p_lite_pde;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_open
+ **
+ ** Description Open BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+static int btusb_lite_open(struct inode *inode, struct file *file)
+{
+ int rv;
+ struct btusb_cb *p_dev = BTUSB_PDE_DATA(inode);
+
+ BTUSB_INFO("btusb_lite_open\n");
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ rv = -ENODEV;
+ goto out;
+ }
+
+ if (p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface already opened\n");
+ rv = -EBUSY;;
+ goto out;
+ }
+
+ file->private_data = p_dev; /* Save our private p_dev */
+
+ p_dev->lite_cb.opened = 1; /* Lite Interface opened */
+
+ /* Clear Every Lite Stack Control Block */
+ memset(&p_dev->lite_cb.stat, 0, sizeof(p_dev->lite_cb.stat));
+ memset(&p_dev->lite_cb.from_app, 0, sizeof(p_dev->lite_cb.from_app));
+ memset(&p_dev->lite_cb.to_app, 0, sizeof(p_dev->lite_cb.to_app));
+ memset(&p_dev->lite_cb.mgt, 0, sizeof(p_dev->lite_cb.mgt));
+ memset(&p_dev->lite_cb.btu, 0, sizeof(p_dev->lite_cb.btu));
+ memset(&p_dev->lite_cb.l2c, 0, sizeof(p_dev->lite_cb.l2c));
+ memset(&p_dev->lite_cb.av, 0, sizeof(p_dev->lite_cb.av));
+ memset(&p_dev->lite_cb.avdt, 0, sizeof(p_dev->lite_cb.avdt));
+
+ rv = 0;
+
+out:
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_close
+ **
+ ** Description Close BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+static int btusb_lite_close(struct inode *inode, struct file *file)
+{
+ int rv;
+ struct btusb_cb *p_dev = BTUSB_PDE_DATA(inode);
+
+ BTUSB_INFO("btusb_lite_close\n");
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ rv = -ENODEV;
+ goto out;
+ }
+
+ if (!p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ rv = -EBUSY;;
+ goto out;
+ }
+
+ BTUSB_ERR("To do, flush/free pending data\n");
+ btusb_lite_init(p_dev);
+
+ rv = 0;
+
+out:
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_write
+ **
+ ** Description Write handler of the BTUSB Lite interface
+ **
+ ** Returns Nb bytes written
+ **
+ *******************************************************************************/
+static ssize_t btusb_lite_write(struct file *file, const char *p_user_buffer,
+ size_t count, loff_t *p_off)
+{
+ struct btusb_cb *p_dev = file->private_data;
+ size_t remainder;
+ struct btusb_lite_cb *p_lite_cb;
+ unsigned long copy_len;
+ ssize_t copied_len;
+ UINT8 *p;
+ UINT16 rx_event;
+ BT_HDR *p_msg;
+
+ BTUSB_DBG("btusb_lite_write count=%zu\n", count);
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ return -ENODEV;
+ }
+
+ if (!p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ return -EBUSY;
+ }
+
+ if (unlikely(count == 0))
+ {
+ return 0;
+ }
+
+ /* check that the incoming data is good */
+ if (unlikely(!access_ok(VERIFY_READ, (void *)p_user_buffer, count)))
+ {
+ BTUSB_ERR("buffer access verification failed\n");
+ return -EFAULT;
+ }
+
+ p_lite_cb = &p_dev->lite_cb;
+
+ copied_len = 0;
+ remainder = count;
+
+ while(remainder)
+ {
+ /* If a full Header has not yet been received */
+ if (p_lite_cb->from_app.rx_header_len < BTUSB_LITE_IPC_HDR_SIZE)
+ {
+ /* How many bytes are needed (1 to 4) */
+ copy_len = BTUSB_LITE_IPC_HDR_SIZE - p_lite_cb->from_app.rx_header_len;
+
+ /* If less bytes are available */
+ if (remainder < copy_len)
+ {
+ copy_len = remainder;
+ }
+
+ /* Copy the header (or a part of it) */
+ if (copy_from_user(&p_lite_cb->from_app.rx_header[p_lite_cb->from_app.rx_header_len],
+ (void *)p_user_buffer, copy_len))
+ {
+ BTUSB_ERR("Copy header from user error\n");
+ return -EINVAL;
+ }
+ remainder -= copy_len;
+ p_lite_cb->from_app.rx_header_len += copy_len;
+ p_user_buffer += copy_len;
+ copied_len += copy_len;
+
+ /* If the buffer has been read */
+ if (p_lite_cb->from_app.rx_header_len == BTUSB_LITE_IPC_HDR_SIZE)
+ {
+ p = p_lite_cb->from_app.rx_header;
+ STREAM_TO_UINT16(p_lite_cb->from_app.rx_len, p);
+ STREAM_TO_UINT16(rx_event, p);
+
+ BTUSB_DBG("Rx Len=%d RxEvent=0x%X\n", p_lite_cb->from_app.rx_len, rx_event);
+
+ p_lite_cb->from_app.rx_len -= sizeof(UINT16); /* Do not count Event Field */
+
+ /* get a buffer from the pool (add one byte for HCI_Type) */
+ if (unlikely((p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + p_lite_cb->from_app.rx_len + 1)) == NULL))
+ {
+ BTUSB_ERR("unable to get GKI buffer - write failed\n");
+ return -EINVAL;
+ }
+ p_msg->event = rx_event;
+ p_msg->layer_specific = 0;
+ p_msg->offset = 1;
+ p_msg->len = 0;
+
+ p_lite_cb->from_app.p_rx_msg = p_msg;
+ }
+ }
+ /* If Header already received */
+ else
+ {
+ p_msg = p_lite_cb->from_app.p_rx_msg;
+
+ if (!p_msg)
+ {
+ BTUSB_ERR("no Rx buffer\n");
+ return EINVAL;
+ }
+ p = (UINT8 *)(p_msg + 1) + p_msg->len + p_msg->offset;
+
+ /* How many payload bytes are expected */
+ copy_len = p_lite_cb->from_app.rx_len;
+
+ /* If less bytes are available */
+ if (remainder < copy_len)
+ {
+ copy_len = remainder;
+ }
+
+ /* Copy the Payload (or a part of it) */
+ if (copy_from_user(p, (void *)p_user_buffer, copy_len))
+ {
+ BTUSB_ERR("Copy payload from user error\n");
+ return -EINVAL;
+ }
+ remainder -= copy_len;
+ p_user_buffer += copy_len;
+ copied_len += copy_len;
+ p_lite_cb->from_app.rx_len -= copy_len;
+ p_msg->len += copy_len;
+
+ if (p_lite_cb->from_app.rx_len == 0)
+ {
+ /* Handle the received message */
+ btusb_lite_ipc_hndl(p_dev, p_msg);
+
+ p_lite_cb->from_app.p_rx_msg = NULL;
+ p_lite_cb->from_app.rx_header_len = 0; /* Ready to receive a new header */
+ }
+ }
+ }
+
+ return copied_len;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_msg_to_app_get
+ **
+ ** Description Get next message to send to IPC
+ **
+ ** Returns GKI buffer to send (or Null)
+ **
+ *******************************************************************************/
+static BT_HDR *btusb_lite_msg_to_app_get(struct btusb_cb *p_dev)
+{
+ BT_HDR *p_msg;
+ BT_HDR *p_hdr_msg;
+ UINT8 *p_data;
+
+ /* First, check if a locally generated Event (IPC) message is pending */
+ p_msg = p_dev->lite_cb.to_app.p_ipc_msg;
+ if (p_msg)
+ {
+ return p_msg;
+ }
+
+ /* Secondly, check if a locally generated IPC Header message is pending */
+ p_msg = p_dev->lite_cb.to_app.p_hdr_msg;
+ if (p_msg)
+ {
+ return p_msg;
+ }
+
+ /* Thirdly, check if an HCI message is pending */
+ p_msg = p_dev->lite_cb.to_app.p_hci_msg;
+ if (p_msg)
+ {
+ return p_msg;
+ }
+
+ /*
+ * No pending message. Check queues now
+ */
+
+ /* First, check if a locally generated Event (UIPC) message is enqueued */
+ p_msg = GKI_dequeue(&p_dev->lite_cb.to_app.ipc_queue);
+ if (p_msg)
+ {
+ p_dev->lite_cb.to_app.p_ipc_msg = p_msg;
+ return p_msg;
+ }
+
+ /* If HCI is not over IPC */
+ if (!btusb_lite_is_hci_over_ipc(p_dev))
+ {
+ return NULL; /* Nothing more to send on IPC */
+ }
+
+ /* Check if an HCI message (from BT controller) is ready */
+ p_msg = GKI_getfirst(&p_dev->rx_queue);
+ if (p_msg)
+ {
+ /* We need to Build an IPC Header to send the HCI packet */
+ p_hdr_msg = GKI_getbuf(sizeof(BT_HDR) + BTUSB_LITE_IPC_HDR_SIZE);
+ if (p_hdr_msg == NULL)
+ {
+ /* Leave the Received HCI packet in the queue (for next time) */
+ BTUSB_ERR("No more buffer\n");
+ p_dev->lite_cb.to_app.p_hci_msg = NULL;
+ return NULL;
+ }
+ p_hdr_msg->len = BTUSB_LITE_IPC_HDR_SIZE;
+ p_hdr_msg->offset = 0;
+ p_hdr_msg->layer_specific = 0;
+ p_hdr_msg->event = 0;
+ p_data = (UINT8 *)(p_hdr_msg + 1) + p_hdr_msg->offset;
+
+ /* Write Length */
+ UINT16_TO_STREAM(p_data, p_msg->len + BTUSB_LITE_IPC_HDR_EVT_SIZE);
+
+ /* Write Event code */
+ switch(p_msg->event)
+ {
+ case HCIT_TYPE_EVENT:
+ {
+ tBTUSB_TRANSACTION *p_trans;
+ p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+ BTUSB_INFO("Event=0x%02X Received from BT Controller\n",
+ *(p_trans->dma_buffer + p_msg->offset));
+ BTUSB_INFO("IPC Buffer TxEvent=BT_EVT_TO_BTU_HCI_EVT(%X) Length=%d\n",
+ BT_EVT_TO_BTU_HCI_EVT, p_msg->len);
+ }
+ UINT16_TO_STREAM(p_data, BT_EVT_TO_BTU_HCI_EVT);
+ break;
+
+ case HCIT_TYPE_ACL_DATA:
+ BTUSB_INFO("IPC Buffer TxEvent=BT_EVT_BTU_IPC_ACL_EVT(%X) Length=%d\n", BT_EVT_BTU_IPC_ACL_EVT, p_msg->len);
+ UINT16_TO_STREAM(p_data, BT_EVT_BTU_IPC_ACL_EVT);
+ break;
+
+ case HCIT_TYPE_LM_DIAG:
+ BTUSB_INFO("IPC Buffer TxEvent=BT_EVT_TO_LM_DIAG(%X) Length=%d\n", BT_EVT_TO_LM_DIAG, p_msg->len);
+ UINT16_TO_STREAM(p_data, BT_EVT_TO_LM_DIAG);
+ break;
+
+ default:
+ /* Should not append. Set Event to 0xFFFF for debug */
+ BTUSB_ERR("Unknown event=0x%x\n", p_msg->event);
+ UINT16_TO_STREAM(p_data, 0xFFFF);
+ break;
+ }
+
+ /* Store Header */
+ p_dev->lite_cb.to_app.p_hdr_msg = p_hdr_msg;
+
+ /* Dequeue HCI message */
+ p_msg = GKI_dequeue(&p_dev->rx_queue);
+ p_dev->lite_cb.to_app.p_hci_msg = p_msg;
+
+ return p_hdr_msg; /* Return pointer on Header */
+ }
+
+ return p_msg;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_msg_to_app_get_data_addr
+ **
+ ** Description Retrieve the data from a GKI Buffer pointer
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_msg_to_app_get_data_addr(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ tBTUSB_TRANSACTION *p_trans;
+
+ /* If the message is a "real" GKI buffer */
+ if ((p_dev->lite_cb.to_app.p_ipc_msg == p_msg) ||
+ (p_dev->lite_cb.to_app.p_hdr_msg == p_msg))
+ {
+ return (UINT8 *)(p_msg + 1) + p_msg->offset;
+ }
+
+ /* If the message is an HCI message, the data is located in the USB transaction */
+
+ /* Check if the message is an HCI message */
+ if (p_dev->lite_cb.to_app.p_hci_msg == p_msg)
+ {
+ p_trans = container_of(p_msg, tBTUSB_TRANSACTION, bt_hdr);
+ return (p_trans->dma_buffer + p_msg->offset);
+ }
+
+ BTUSB_ERR("Unknown buffer=%p\n", p_msg);
+
+ return NULL;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_msg_to_app_free
+ **
+ ** Description Free a message which has been sent to IPC
+ **
+ ** Returns None
+ **
+ *******************************************************************************/
+static void btusb_lite_msg_to_app_free(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ /* Check if the message is a locally generated Event (IPC) message */
+ if (p_dev->lite_cb.to_app.p_ipc_msg == p_msg)
+ {
+ GKI_freebuf(p_msg);
+ p_dev->lite_cb.to_app.p_ipc_msg = NULL;
+ return;
+ }
+
+ /* Check if the message is a locally generated Header (IPC) message */
+ if (p_dev->lite_cb.to_app.p_hdr_msg == p_msg)
+ {
+ GKI_freebuf(p_msg);
+ p_dev->lite_cb.to_app.p_hdr_msg = NULL;
+ return;
+ }
+
+ /* Check if the message is an HCI message */
+ if (p_dev->lite_cb.to_app.p_hci_msg == p_msg)
+ {
+ p_dev->lite_cb.to_app.p_hci_msg = NULL;
+ /* The buffer must not be freed. It has to be re-enqueue in USB core */
+ btusb_dequeued(p_dev, p_msg);
+ return;
+ }
+
+ BTUSB_ERR("Unknown buffer=%p\n", p_msg);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_read
+ **
+ ** Description Read handler of the BTUSB Lite interface
+ **
+ ** Returns Nb bytes written
+ **
+ *******************************************************************************/
+static ssize_t btusb_lite_read(struct file *file, char __user *p_user_buffer, size_t count, loff_t *p_off)
+{
+ struct btusb_cb *p_dev = file->private_data;
+ ssize_t size;
+ UINT8 *p_data;
+ unsigned long copy_len;
+ BT_HDR *p_msg;
+ int rv;
+
+ BTUSB_DBG("btusb_lite_read\n");
+
+ if (!p_dev)
+ {
+ BTUSB_ERR("Unable to find p_dev reference\n");
+ size = -ENODEV;
+ goto out;
+ }
+
+ if (!p_dev->lite_cb.opened)
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ size = -EBUSY;;
+ goto out;
+ }
+
+ if (count == 0)
+ {
+ size = 0;
+ goto out;
+ }
+
+ /* Check that the user buffer is good */
+ if (unlikely(!access_ok(VERIFY_WRITE, (void *)p_user_buffer, count)))
+ {
+ BTUSB_ERR("buffer access verification failed\n");
+ size = -EFAULT;
+ goto out;
+ }
+
+ /* Sleep while nothing for the application */
+ rv = wait_event_interruptible(p_dev->rx_wait_q,
+ ((p_msg = btusb_lite_msg_to_app_get(p_dev)) != NULL));
+
+ if (unlikely(rv))
+ {
+ BTUSB_DBG("read wait interrupted");
+ return rv;
+ }
+
+ if (p_msg)
+ {
+ if (p_msg->len < count)
+ {
+ copy_len = p_msg->len;
+ }
+ else
+ {
+ copy_len = count; /* User asks for count bytes */
+ }
+
+ BTUSB_DBG("p_msg=%p msg->len=%d count=%zu copy_len=%lu\n", p_msg, p_msg->len, count, copy_len);
+
+ p_data = btusb_lite_msg_to_app_get_data_addr(p_dev, p_msg);
+ if (p_data == NULL)
+ {
+ size = -EFAULT;
+ goto out;
+ }
+
+ /* copy the message data to the available user space */
+ if (unlikely(copy_to_user(p_user_buffer, p_data, copy_len)))
+ {
+ BTUSB_ERR("copy to user error\n");
+ size = -EINVAL;
+ goto out;
+ }
+
+ BTUSB_DBG("copied %ld bytes\n", copy_len);
+
+ p_msg->offset += copy_len;
+ p_msg->len -= copy_len;
+ size = copy_len;
+
+ if (p_msg->len == 0)
+ {
+ BTUSB_DBG("free gki buffer\n");
+ btusb_lite_msg_to_app_free(p_dev, p_msg);
+ }
+ goto out;
+ }
+ else
+ {
+ BTUSB_ERR("No Buffer\n");
+ }
+
+ size = 0; /* should not happen */
+
+out:
+ return size;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_poll
+ **
+ ** Description Poll callback (to implement select)
+ **
+ ** Parameters file : file structure of the opened instance
+ ** p_pt : poll table to which the local queue must be added
+ **
+ ** Returns Mask of the type of polling supported, error number if negative
+ **
+ *******************************************************************************/
+static unsigned int btusb_lite_poll(struct file *file, struct poll_table_struct *p_pt)
+{
+ struct btusb_cb *p_dev = file->private_data;
+ unsigned int mask;
+
+ BTUSB_DBG("enter\n");
+
+ /* retrieve the device from the file pointer*/
+ BTUSB_DBG("p_dev=%p\n", p_dev);
+ if (unlikely(p_dev == NULL))
+ {
+ BTUSB_ERR("can't find device\n");
+ return -ENODEV;
+ }
+
+ // check if the device was disconnected
+ if (unlikely(!p_dev->p_main_intf))
+ {
+ BTUSB_ERR("device unplugged\n");
+ return -ENODEV;
+ }
+
+ if (unlikely(!p_dev->lite_cb.opened))
+ {
+ BTUSB_ERR("Lite interface was not opened\n");
+ return -EINVAL;
+ }
+
+ /* indicate to the system on which queue it should poll (non blocking call) */
+ poll_wait(file, &p_dev->rx_wait_q, p_pt);
+
+ /* enable WRITE (select/poll is not write blocking) */
+ mask = POLLOUT | POLLWRNORM;
+
+ /* enable READ only if data is queued from HCI */
+ if (btusb_lite_msg_to_app_get(p_dev))
+ {
+ mask |= POLLIN | POLLRDNORM;
+ }
+
+ return mask;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_create
+ **
+ ** Description Create BTUSB Lite interface
+ **
+ ** Returns status (< 0 if error)
+ **
+ *******************************************************************************/
+int btusb_lite_create(struct btusb_cb *p_dev, struct usb_interface *p_interface)
+{
+ int rv;
+ char procname[64];
+
+ btusb_lite_init(p_dev);
+
+ scnprintf(procname, sizeof(procname), "driver/%s-lite", p_interface->usb_dev->kobj.name);
+ p_dev->lite_cb.p_lite_pde = proc_create_data(procname, S_IRUGO | S_IWUGO, NULL, &btusb_lite_fops, p_dev);
+ if (p_dev->lite_cb.p_lite_pde == NULL)
+ {
+ BTUSB_ERR("Couldn't create %s entry\n", procname);
+ rv = -1;
+ }
+ else
+ {
+ BTUSB_INFO("Created /proc/%s\n", procname);
+ rv = 0;
+ }
+
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_delete
+ **
+ ** Description Delete BTUSB Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+void btusb_lite_delete(struct btusb_cb *p_dev, struct usb_interface *p_interface)
+{
+ char procname[64];
+
+ scnprintf(procname, sizeof(procname), "driver/%s-lite", p_interface->usb_dev->kobj.name);
+ remove_proc_entry(procname, NULL);
+ BTUSB_INFO("/proc/%s deleted\n", procname);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_is_hci_over_ipc
+ **
+ ** Description Check if HCI is over IPC (Lite Interface).
+ **
+ ** Returns int (1 if HCI is over IPC otherwise 0)
+ **
+ *******************************************************************************/
+int btusb_lite_is_hci_over_ipc(struct btusb_cb *p_dev)
+{
+ if ((p_dev->lite_cb.opened) && /* User Space opened the Lite interface */
+ (p_dev->lite_cb.mgt.opened) && /* IPC MGT Opened */
+ /* Lite Transport is opened */
+ ((p_dev->lite_cb.btu.transport_state == BTU_LITE_STACK_ACTIVE) ||
+ (p_dev->lite_cb.btu.transport_state == BTU_LITE_TRANSPORT_ACTIVE)))
+ {
+ return 1;
+ }
+ return 0;
+}
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_stop_all
+ **
+ ** Description Stop all sound streams
+ **
+ ** Returns void
+ **
+ *******************************************************************************/
+void btusb_lite_stop_all(struct btusb_cb *p_dev)
+{
+ int i;
+
+ BTUSB_INFO("");
+
+ for (i = 0 ; i < BTA_AV_NUM_STRS ; i++)
+ {
+ btusb_lite_av_stop(p_dev, i, 0);
+ btusb_lite_av_remove(p_dev, i, 0, 0);
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_hndl
+ **
+ ** Description Handle received message from BTUSB Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ BTUSB_INFO("IPC Buffer RxEvent=%s(0x%X) Length=%d\n",
+ btusb_lite_ipc_event_desc(p_msg->event), p_msg->event, p_msg->len);
+
+ if (unlikely(dbgflags & BTUSB_DBG_MSG) && p_msg->len)
+ {
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ int len = p_msg->len>20?20:p_msg->len;
+ int i;
+
+ for (i = 0 ; i < len ; i++, p++)
+ {
+ printk("%02X ", *p);
+ }
+ if (p_msg->len>20)
+ printk("...\n");
+ else
+ printk("\n");
+ }
+
+ switch(p_msg->event)
+ {
+ case BT_EVT_TO_LM_HCI_CMD:
+ btusb_lite_ipc_hci_cmd_hndl(p_dev, p_msg);
+ /* NO GKI_freebuf here */
+ break;
+
+ case BT_EVT_TO_LM_HCI_ACL:
+ btusb_lite_ipc_hci_acl_hndl(p_dev, p_msg);
+ /* NO GKI_freebuf here */
+ break;
+
+ case BT_EVT_BTU_IPC_MGMT_EVT:
+ btusb_lite_ipc_mgt_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_BTU_EVT:
+ btusb_lite_ipc_btu_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_L2C_EVT:
+ btusb_lite_ipc_l2c_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_BTM_EVT:
+ btusb_lite_ipc_btm_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_AVDT_EVT:
+ btusb_lite_ipc_avdt_hndl(p_dev, p_msg);
+ GKI_freebuf(p_msg);
+ break;
+
+ case BT_EVT_BTU_IPC_SLIP_EVT:
+ case BT_EVT_BTU_IPC_BTTRC_EVT:
+ case BT_EVT_BTU_IPC_BURST_EVT:
+ case BT_EVT_BTU_IPC_ACL_EVT:
+ case BT_EVT_BTU_IPC_L2C_MSG_EVT:
+ BTUSB_INFO("Event=0x%X Not expected\n", p_msg->event);
+ GKI_freebuf(p_msg);
+ break;
+
+ default:
+ BTUSB_INFO("Event=0x%X Unknown\n", p_msg->event);
+ GKI_freebuf(p_msg);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_hci_cmd_hndl
+ **
+ ** Description Handle HCI CMD packet received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_hci_cmd_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p;
+ UINT16 hci_opcode;
+ UINT8 hci_status;
+
+ /* First check if this HCI command must be caught by BTUSB */
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ STREAM_TO_UINT16(hci_opcode, p); /* Extract HCI Opcode */
+
+ /* If the HCI Opcode must be caught */
+ switch(hci_opcode)
+ {
+ case HCI_BRCM_PAUSE_TRANSPORT:
+ BTUSB_INFO("HCI TransportPause VSC (%X) caught\n", hci_opcode);
+ hci_status = HCI_SUCCESS;
+ btusb_lite_ipc_cmd_cplt_evt_send(p_dev, hci_opcode,
+ &hci_status, sizeof(hci_status));
+ GKI_freebuf(p_msg);
+ return;
+
+ case HCI_BRCM_TRANSPORT_RESUME:
+ BTUSB_INFO("HCI TransportResume VSC (%X) caught\n", hci_opcode);
+
+ hci_status = HCI_SUCCESS;
+ btusb_lite_ipc_cmd_cplt_evt_send(p_dev, hci_opcode,
+ &hci_status, sizeof(hci_status));
+ GKI_freebuf(p_msg);
+ return;
+
+ default:
+ break;
+ }
+
+ BTUSB_INFO("HCI OpCode=0x%04X Sent to BT Controller\n", hci_opcode);
+
+ if (p_msg->offset < 1)
+ {
+ BTUSB_ERR("Offset=%d too small\n", p_msg->offset);
+ GKI_freebuf(p_msg);
+ return;
+ }
+
+ p_msg->offset--; /* Reduce Offset to add H4 HCI Type (Command) */
+ p_msg->len++;
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ UINT8_TO_STREAM(p, HCIT_TYPE_COMMAND);
+
+ /* add the incoming data and notify the btusb_tx_task to process */
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ // wake up tasklet
+ tasklet_schedule(&p_dev->tx_task);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_hci_acl_hndl
+ **
+ ** Description Handle HCI ACL packet received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_hci_acl_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p;
+
+ if (p_msg->offset < 1)
+ {
+ BTUSB_ERR("Offset=%d too small\n", p_msg->offset);
+ GKI_freebuf(p_msg);
+ return;
+ }
+
+ p_msg->offset--; /* Reduce Offset to add H4 HCI Type (Command) */
+ p_msg->len++;
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ UINT8_TO_STREAM(p, HCIT_TYPE_ACL_DATA);
+
+ /* add the incoming data and notify the btusb_tx_task to process */
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ // wake up tasklet
+ tasklet_schedule(&p_dev->tx_task);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_mgt_hndl
+ **
+ ** Description Handle Mgt messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_mgt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ UINT8 response[6];
+ UINT8 *p_response = response;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_MGMT Request */
+
+ switch(cmd)
+ {
+ case UIPC_OPEN_REQ:
+ BTUSB_INFO("IPC_MGT:OpenReq received\n");
+ /* If Mgt already opened */
+ if (p_dev->lite_cb.mgt.opened)
+ {
+ BTUSB_ERR("IPC_MGT Was already opened\n");
+ UINT8_TO_STREAM(p_response, UIPC_STATUS_FAIL); /* Status */
+ }
+ else
+ {
+ p_dev->lite_cb.mgt.opened = 1;
+ UINT8_TO_STREAM(p_response, UIPC_STATUS_SUCCESS); /* Status */
+ }
+ UINT16_TO_STREAM(p_response, UIPC_VERSION_MAJOR); /* version_major */
+ UINT16_TO_STREAM(p_response, UIPC_VERSION_MINOR); /* version_minor */
+ UINT8_TO_STREAM(p_response, BTM_SYNC_INFO_NUM_STR); /* Number of simultaneous streams supported by the light stack */
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_MGMT_EVT, UIPC_OPEN_RSP,
+ response, p_response - response);
+ break;
+
+ case UIPC_CLOSE_REQ:
+ BTUSB_INFO("IPC_MGT:CloseReq received\n");
+ p_dev->lite_cb.mgt.opened = 0;
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_MGMT_EVT, UIPC_CLOSE_RSP, NULL, 0);
+ break;
+
+ default:
+ BTUSB_INFO("Unknown IPC_MGT command=%d\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_btu_hndl
+ **
+ ** Description Handle BTU messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_btu_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 byte;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_BTU Request */
+
+ switch(cmd)
+ {
+ case BTU_IPC_CMD_SET_TRANSPORT_STATE:
+ STREAM_TO_UINT8(byte, p); /* Extract Param */
+ BTUSB_INFO("IPC_BTU:SetTransportState (%d) received\n", byte);
+ p_dev->lite_cb.btu.transport_state = byte;
+ break;
+
+ case BTU_IPC_CMD_DISABLE_TRANSPORT:
+ STREAM_TO_UINT8(byte, p); /* Extract Param */
+ BTUSB_INFO("IPC_BTU:DisableTransport (%d) received\n", byte);
+ p_dev->lite_cb.btu.transport_disabled = byte;
+ break;
+
+ default:
+ BTUSB_INFO("Unknown IPC_BTU command=%d\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_btm_hndl
+ **
+ ** Description Handle BTM messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_btm_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ tBTA_AV_SYNC_INFO sync_info;
+ UINT8 scb_idx;
+ tBTA_AV_AUDIO_CODEC_INFO codec_cfg;
+ UINT8 start_stop_flag;
+ UINT8 multi_av_supported;
+ UINT16 curr_mtu;
+ UINT8 audio_open_cnt;
+ UINT8 response[1];
+ UINT8 *p_response = response;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_BTU Request */
+
+ switch(cmd)
+ {
+ case BTA_AV_SYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvSyncToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(sync_info.avdt_handle, p);
+ STREAM_TO_UINT8(sync_info.chnl, p);
+ STREAM_TO_UINT8(sync_info.codec_type, p);
+ STREAM_TO_UINT8(sync_info.cong, p);
+ STREAM_TO_UINT8(sync_info.hdi, p);
+ STREAM_TO_UINT8(sync_info.hndl, p);
+ STREAM_TO_UINT8(sync_info.l2c_bufs, p);
+ STREAM_TO_UINT16(sync_info.l2c_cid, p);
+ STREAM_TO_ARRAY (sync_info.peer_addr, p, BD_ADDR_LEN);
+ STREAM_TO_UINT8(multi_av_supported, p);
+ STREAM_TO_UINT16(curr_mtu, p);
+ BTUSB_INFO("avdt_hdl=0x%x chnl=0x%x codec_type=0x%x cong=%d hdi=%d hndl=0x%x\n",
+ sync_info.avdt_handle, sync_info.chnl, sync_info.codec_type,
+ sync_info.cong, sync_info.hdi, sync_info.hndl);
+ BTUSB_INFO("l2c_bufs=%d l2c_cid=0x%x multi_av_sup=%d curr_mtu=%d\n",
+ sync_info.l2c_bufs, sync_info.l2c_cid, multi_av_supported, curr_mtu);
+ BTUSB_INFO("BdAddr=%02X-%02X-%02X-%02X-%02X-%02X\n",
+ sync_info.peer_addr[0], sync_info.peer_addr[1],sync_info.peer_addr[2],
+ sync_info.peer_addr[3], sync_info.peer_addr[4],sync_info.peer_addr[5]);
+
+ /* Add AV channel */
+ btusb_lite_av_add(p_dev, &sync_info, multi_av_supported, curr_mtu);
+
+ UINT8_TO_STREAM(p_response, sync_info.hdi);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_SYNC_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_START_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrStartToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ STREAM_TO_UINT16 (codec_cfg.bit_rate, p);
+ STREAM_TO_UINT16 (codec_cfg.bit_rate_busy, p);
+ STREAM_TO_UINT16 (codec_cfg.bit_rate_swampd, p);
+ STREAM_TO_UINT8 (codec_cfg.busy_level, p);
+ STREAM_TO_ARRAY (codec_cfg.codec_info, p, AVDT_CODEC_SIZE);
+ STREAM_TO_UINT8 (codec_cfg.codec_type, p);
+ STREAM_TO_UINT8 (start_stop_flag, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d busy_level=%d start_stop_flag=%d\n",
+ scb_idx, audio_open_cnt,
+ codec_cfg.busy_level, start_stop_flag);
+ BTUSB_INFO(" codec_type=0x%x bit_rate=%d busy_level=%d bit_rate_busy=%d bit_rate_swampd=%d\n",
+ codec_cfg.codec_type, codec_cfg.bit_rate, codec_cfg.busy_level,
+ codec_cfg.bit_rate_busy, codec_cfg.bit_rate_swampd);
+ BTUSB_INFO(" CodecInfo:%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X-%02X",
+ codec_cfg.codec_info[0], codec_cfg.codec_info[1], codec_cfg.codec_info[2],
+ codec_cfg.codec_info[3], codec_cfg.codec_info[4], codec_cfg.codec_info[5],
+ codec_cfg.codec_info[6], codec_cfg.codec_info[7], codec_cfg.codec_info[8],
+ codec_cfg.codec_info[9]);
+
+ /* Start AV */
+ btusb_lite_av_start(p_dev, scb_idx, start_stop_flag, audio_open_cnt, &codec_cfg);
+
+ /* Send the response */
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_START_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_STOP_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrStopToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+
+ btusb_lite_av_stop(p_dev, scb_idx, audio_open_cnt);
+
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_STOP_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_SUSPEND_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrSuspendToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+ btusb_lite_av_suspend(p_dev, scb_idx, audio_open_cnt);
+
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_SUSPEND_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case BTA_AV_STR_CLEANUP_TO_LITE_REQ:
+ BTUSB_INFO("IPC_BTM:BtaAvStrCleanupToLiteReq (%d)\n", cmd);
+ STREAM_TO_UINT8(scb_idx, p);
+ STREAM_TO_UINT8(audio_open_cnt, p);
+ STREAM_TO_UINT16(curr_mtu, p);
+ BTUSB_INFO(" scb_idx=%d audio_open_cnt=%d curr_mtu=%d\n", scb_idx, audio_open_cnt,
+ curr_mtu);
+
+ btusb_lite_av_remove(p_dev, scb_idx, audio_open_cnt, curr_mtu);
+
+ UINT8_TO_STREAM(p_response, scb_idx);
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_BTM_EVT, BTA_AV_STR_CLEANUP_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ /* BTC commands (unexpected) */
+ case A2DP_START_REQ:
+ case A2DP_START_RESP:
+ case A2DP_STOP_REQ:
+ case A2DP_STOP_RESP:
+ case A2DP_CLEANUP_REQ:
+ case A2DP_CLEANUP_RESP:
+ case A2DP_SUSPEND_REQ:
+ case A2DP_SUSPEND_RESP:
+ case A2DP_JITTER_DONE_IND:
+
+ /* BTA AV Response commands (unexpected) */
+ case BTA_AV_SYNC_TO_LITE_RESP:
+ case BTA_AV_STR_START_TO_LITE_RESP:
+ case BTA_AV_STR_STOP_TO_LITE_RESP:
+ case BTA_AV_STR_CLEANUP_TO_LITE_RESP:
+ case BTA_AV_STR_SUSPEND_TO_LITE_RESP:
+ case BTA_AV_SYNC_ERROR_RESP:
+ BTUSB_INFO("IPC_BTM: Unexpected Cmd=%d received\n", cmd);
+ break;
+
+ default:
+ BTUSB_INFO("IPC_BTM: Unknown Cmd=%d received\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_avdt_hndl
+ **
+ ** Description Handle AVDT messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_avdt_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ tAVDT_SYNC_INFO sync_req;
+ tAVDT_SYNC_INFO sync_rsp;
+ int stream;
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 avdt_status;
+
+ STREAM_TO_UINT8(sync_req.op_code, p); /* Extract UIPC_AVDT Request */
+
+ switch(sync_req.op_code)
+ {
+ case AVDT_SYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtSyncToLiteReq (%d) received\n", sync_req.op_code);
+ break;
+
+ case AVDT_RESYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtReSyncToLiteReq (%d) received\n", sync_req.op_code);
+ break;
+
+ case AVDT_SYNC_TO_FULL_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtSyncToFullReq (%d) received\n", sync_req.op_code);
+ break;
+
+ case AVDT_REMOVE_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtRemoveToLiteReq (%d)\n", sync_req.op_code);
+ break;
+
+ case AVDT_SYNC_CP_TO_LITE_REQ:
+ BTUSB_INFO("IPC_AVDT:AvdtSyncCpToLiteReq (%d)\n", sync_req.op_code);
+ break;
+
+ case AVDT_SYNC_TO_LITE_RESP:
+ case AVDT_RESYNC_TO_LITE_RESP:
+ case AVDT_SYNC_TO_FULL_RESP:
+ case AVDT_REMOVE_TO_LITE_RESP:
+ case AVDT_SYNC_CP_TO_LITE_RESP:
+ BTUSB_INFO("IPC_AVDT: Unexpected Cmd=%d received\n", sync_req.op_code);
+ sync_rsp.op_code = 0xFF;
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+
+ default:
+ BTUSB_INFO("IPC_AVDT: Unknown Cmd=%d received\n", sync_req.op_code);
+ sync_rsp.op_code = 0xFE;
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+
+ /* Extract parameters */
+ STREAM_TO_UINT8(sync_req.status, p);
+
+ /* Decode Sync CP parameters */
+ if (sync_req.op_code == AVDT_SYNC_CP_TO_LITE_REQ)
+ {
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++ )
+ {
+ STREAM_TO_UINT8(sync_req.scb_info[stream].handle, p);
+ STREAM_TO_UINT16(sync_req.scb_info[stream].cp.id, p);
+ STREAM_TO_UINT8(sync_req.scb_info[stream].cp.scms_hdr, p);
+ if (sync_req.scb_info[stream].handle)
+ {
+ BTUSB_INFO(" stream[%d]: handle=0x%x cp_id=0x%04X scms_hdr=0x%x\n",
+ stream, sync_req.scb_info[stream].handle,
+ sync_req.scb_info[stream].cp.id,
+ sync_req.scb_info[stream].cp.scms_hdr);
+ }
+ else
+ {
+ BTUSB_INFO(" stream[%d]: No Data\n", stream);
+ }
+ }
+ }
+ /* Decode other Sync message parameters */
+ else
+ {
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++ )
+ {
+ STREAM_TO_UINT8(sync_req.scb_info[stream].handle, p);
+ STREAM_TO_BDADDR(sync_req.scb_info[stream].peer_addr, p)
+ STREAM_TO_UINT16(sync_req.scb_info[stream].local_cid, p);
+ STREAM_TO_UINT16(sync_req.scb_info[stream].peer_mtu, p);
+ STREAM_TO_UINT8(sync_req.scb_info[stream].mux_tsid_media, p);
+ STREAM_TO_UINT16(sync_req.scb_info[stream].media_seq, p);
+ if (sync_req.scb_info[stream].handle)
+ {
+ BTUSB_INFO(" stream[%d]:\n", stream);
+ BTUSB_INFO(" BdAddr=%02X-%02X-%02X-%02X-%02X-%02X\n",
+ sync_req.scb_info[stream].peer_addr[0],
+ sync_req.scb_info[stream].peer_addr[1],
+ sync_req.scb_info[stream].peer_addr[2],
+ sync_req.scb_info[stream].peer_addr[3],
+ sync_req.scb_info[stream].peer_addr[4],
+ sync_req.scb_info[stream].peer_addr[5]);
+ BTUSB_INFO(" handle=0x%x local_cid=0x%x peer_mtu=%d mux_tsid_media=%d media_seq=%d\n",
+ sync_req.scb_info[stream].handle,
+ sync_req.scb_info[stream].local_cid,
+ sync_req.scb_info[stream].peer_mtu,
+ sync_req.scb_info[stream].mux_tsid_media,
+ sync_req.scb_info[stream].media_seq);
+ }
+ else
+ {
+ BTUSB_INFO(" stream[%d]: No data\n", stream);
+ }
+ }
+ }
+ memset(&sync_rsp, 0, sizeof(sync_rsp));
+
+ switch(sync_req.op_code)
+ {
+ case AVDT_SYNC_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_SYNC_TO_LITE_RESP;
+
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ if(btusb_lite_avdt_init_scb(p_dev, &(sync_req.scb_info[stream])) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_RESYNC_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_RESYNC_TO_LITE_RESP;
+
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ if((p_scb = btusb_lite_avdt_scb_by_hdl(p_dev, sync_req.scb_info[stream].handle)) != NULL)
+ {
+ memcpy(p_scb->p_ccb->peer_addr, sync_req.scb_info[stream].peer_addr, BD_ADDR_LEN);
+ p_scb->p_ccb->lcid = sync_req.scb_info[stream].local_cid;
+ p_scb->p_ccb->peer_mtu = sync_req.scb_info[stream].peer_mtu;
+ p_scb->mux_tsid_media = sync_req.scb_info[stream].mux_tsid_media;
+ p_scb->media_seq = sync_req.scb_info[stream].media_seq;
+ }
+ else if(btusb_lite_avdt_init_scb(p_dev, &(sync_req.scb_info[stream])) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_SYNC_TO_FULL_REQ:
+ sync_rsp.op_code = AVDT_SYNC_TO_FULL_RESP;
+
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ {
+ sync_rsp.scb_info[stream].handle = 0;
+ continue;
+ }
+
+ if(btusb_lite_avdt_remove_scb(p_dev, sync_req.scb_info[stream].handle,
+ &sync_rsp.scb_info[stream]) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_REMOVE_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_REMOVE_TO_LITE_RESP;
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ if(btusb_lite_avdt_remove_scb(p_dev, sync_req.scb_info[stream].handle,
+ &sync_rsp.scb_info[stream]) != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+
+ case AVDT_SYNC_CP_TO_LITE_REQ:
+ sync_rsp.op_code = AVDT_SYNC_CP_TO_LITE_RESP;
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ if(sync_req.scb_info[stream].handle == 0)
+ continue;
+
+ switch(sync_req.scb_info[stream].cp.id)
+ {
+ case AVDT_SYNC_CP_ID_NONE:
+ avdt_status = btusb_lite_avdt_cp_set_scms(p_dev,
+ sync_req.scb_info[stream].handle, FALSE, 0x00);
+ break;
+
+ case AVDT_SYNC_CP_ID_SCMS:
+ avdt_status = btusb_lite_avdt_cp_set_scms(p_dev,
+ sync_req.scb_info[stream].handle, TRUE,
+ sync_req.scb_info[stream].cp.scms_hdr);
+ break;
+
+ default:
+ avdt_status = AVDT_SYNC_FAILURE;
+ break;
+ }
+ if (avdt_status != AVDT_SYNC_SUCCESS)
+ {
+ sync_rsp.status = AVDT_SYNC_FAILURE;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ return;
+ }
+ }
+ sync_rsp.status = AVDT_SYNC_SUCCESS;
+ btusb_lite_ipc_avdt_sync_info_send(p_dev, &sync_rsp);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_avdt_sync_info_send
+ **
+ ** Description Build and send an IPC AVDT Sync Info Response
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_avdt_sync_info_send(struct btusb_cb *p_dev, tAVDT_SYNC_INFO *p_sync_rsp)
+{
+ int stream;
+ UINT8 response[BTUSB_LITE_IPC_AVDT_SYNC_INFO_RSP_LEN];
+ UINT8 *p_response = response;
+
+ UINT8_TO_STREAM(p_response, p_sync_rsp->status);
+
+ if (p_sync_rsp->op_code != AVDT_SYNC_CP_TO_LITE_RESP)
+ {
+ for(stream = 0; stream < BTM_SYNC_INFO_NUM_STR; stream++)
+ {
+ UINT8_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].handle);
+ BDADDR_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].peer_addr)
+ UINT16_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].local_cid);
+ UINT16_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].peer_mtu);
+ UINT8_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].mux_tsid_media);
+ UINT16_TO_STREAM(p_response, p_sync_rsp->scb_info[stream].media_seq);
+ }
+ }
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_AVDT_EVT, p_sync_rsp->op_code,
+ response, p_response - response);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_l2c_hndl
+ **
+ ** Description Handle L2C messages received from Lite interface
+ **
+ ** Returns none
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_l2c_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 cmd;
+ UINT8 *p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ UINT8 response[3];
+ UINT8 *p_response = response;
+ struct btusb_lite_l2c_cb *p_l2c = &p_dev->lite_cb.l2c;
+ int stream;
+ tL2C_STREAM_INFO l2c_stream;
+ UINT16 local_cid;
+ UINT8 num_stream;
+
+ STREAM_TO_UINT8(cmd, p); /* Extract UIPC_MGMT Request */
+
+ switch(cmd)
+ {
+ case L2C_SYNC_TO_LITE_REQ:
+ BTUSB_INFO("IPC_L2C:L2cSyncToLiteReq (%d) received\n", L2C_SYNC_TO_LITE_REQ);
+ STREAM_TO_UINT16(p_l2c->light_xmit_quota, p);
+ STREAM_TO_UINT16(p_l2c->acl_data_size, p);
+ STREAM_TO_UINT16(p_l2c->non_flushable_pbf, p);
+ STREAM_TO_UINT8(p_l2c->multi_av_data_cong_start, p);
+ STREAM_TO_UINT8(p_l2c->multi_av_data_cong_end, p);
+ STREAM_TO_UINT8(p_l2c->multi_av_data_cong_discard, p);
+ STREAM_TO_UINT8(num_stream, p);
+ BTUSB_INFO("Xquota=%d AclSize=%d NFpbf=%d congStart=%d congEnd=%d congDisc=%d NbStr=%d\n",
+ p_l2c->light_xmit_quota, p_l2c->acl_data_size, p_l2c->non_flushable_pbf,
+ p_l2c->multi_av_data_cong_start, p_l2c->multi_av_data_cong_end,
+ p_l2c->multi_av_data_cong_discard, num_stream);
+
+ /* Start building the response */
+ UINT16_TO_STREAM(p_response, p_l2c->light_xmit_unacked);
+ UINT8_TO_STREAM(p_response, num_stream);
+
+ for(stream = 0; stream < num_stream; stream++)
+ {
+ STREAM_TO_UINT16(l2c_stream.local_cid, p);
+ STREAM_TO_UINT16(l2c_stream.remote_cid, p);
+ STREAM_TO_UINT16(l2c_stream.out_mtu, p);
+ STREAM_TO_UINT16(l2c_stream.handle, p);
+ STREAM_TO_UINT16(l2c_stream.link_xmit_quota, p);
+ STREAM_TO_UINT8(l2c_stream.is_flushable, p);
+ BTUSB_INFO(" Stream[%d]:lcid=0x%X rcid=0x%X mtu=%d handle=0x%X xmit_quota=%d flushable=%d\n",
+ stream, l2c_stream.local_cid, l2c_stream.remote_cid,
+ l2c_stream.out_mtu, l2c_stream.handle,
+ l2c_stream.link_xmit_quota, l2c_stream.is_flushable);
+
+ /* Resume building the response */
+ UINT16_TO_STREAM(p_response, l2c_stream.local_cid);
+
+ /* Synchronize (add) this L2CAP Stream */
+ if (btusb_lite_l2c_add(p_dev, &l2c_stream) < 0)
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_FAILURE);
+ }
+ else
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_SUCCESS);
+ }
+ }
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_L2C_EVT, L2C_SYNC_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ case L2C_REMOVE_TO_LITE_REQ:
+ BTUSB_INFO("IPC_L2C:L2cRemoveToLiteReq (%d) received\n", L2C_REMOVE_TO_LITE_REQ);
+ STREAM_TO_UINT16(p_l2c->light_xmit_quota, p);
+ STREAM_TO_UINT8(num_stream, p);
+ BTUSB_INFO("Xquota=%d NbStr=%d\n", p_l2c->light_xmit_quota, num_stream);
+
+ /* Start building the response */
+ UINT16_TO_STREAM(p_response, p_l2c->light_xmit_unacked);
+ UINT8_TO_STREAM(p_response, num_stream);
+
+ for(stream = 0; stream < num_stream; stream++)
+ {
+ STREAM_TO_UINT16(local_cid, p);
+ BTUSB_INFO(" Stream[%d]:lcid=0x%X\n", stream, p_l2c->ccb[stream].local_cid);
+
+ /* Resume building the response */
+ UINT16_TO_STREAM(p_response, local_cid);
+
+ /* Synchronize (remove) this L2CAP Stream */
+ if (btusb_lite_l2c_remove(p_dev, local_cid) < 0)
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_FAILURE);
+ }
+ else
+ {
+ UINT8_TO_STREAM(p_response, L2C_SYNC_SUCCESS);
+ }
+ }
+
+ /* Send the response to the full stack */
+ btusb_lite_ipc_rsp_send(p_dev, BT_EVT_BTU_IPC_L2C_EVT, L2C_REMOVE_TO_LITE_RESP,
+ response, p_response - response);
+ break;
+
+ default:
+ BTUSB_INFO("Unknown IPC_MGT command=%d\n", cmd);
+ break;
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_rsp_send
+ **
+ ** Description Send an Response over Lite interface.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_rsp_send(struct btusb_cb *p_dev,
+ UINT16 event, UINT8 op_code, UINT8 *p_param, UINT8 param_len)
+{
+ BT_HDR *p_msg;
+ UINT16 size = param_len + BTUSB_LITE_IPC_HDR_SIZE + sizeof(UINT8);
+ UINT8 *p;
+
+ BTUSB_INFO("Event=%s(0x%X), opcode=%d len=%d\n", btusb_lite_ipc_event_desc(event),
+ event, op_code, param_len);
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = 0;
+ p_msg->len = size;
+
+ p = (UINT8 *)(p_msg + 1);
+
+ UINT16_TO_STREAM(p, param_len + BTUSB_LITE_IPC_HDR_EVT_SIZE + sizeof(UINT8)); /* Length */
+ UINT16_TO_STREAM(p, event); /* Event */
+ UINT8_TO_STREAM(p, op_code); /* Opcode */
+ if (p_param)
+ {
+ ARRAY_TO_STREAM(p, p_param, param_len)
+ }
+
+ /* Send message to User Space */
+ btusb_lite_ipc_sent_to_user(p_dev, p_msg);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_cmd_cplt_evt_send
+ **
+ ** Description Send an UIPC_Over_HCI VSC Cmd Complete.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len)
+{
+ BT_HDR *p_msg;
+ UINT16 size = param_len + BTUSB_LITE_IPC_HDR_SIZE + 5;
+ UINT8 *p;
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = 0;
+ p_msg->len = size;
+
+ p = (UINT8 *)(p_msg + 1);
+
+ UINT16_TO_STREAM(p, param_len + BTUSB_LITE_IPC_HDR_EVT_SIZE + 5); /* length */
+ UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_EVT); /* IPC OpCode */
+ UINT8_TO_STREAM(p, HCI_COMMAND_COMPLETE_EVT); /* Command Complete Evt */
+ UINT8_TO_STREAM(p, param_len + 3); /* Param Length (param + NumCmd + OpCode) */
+ UINT8_TO_STREAM(p, 0x01); /* HCI Num Command */
+ UINT16_TO_STREAM(p, opcode); /* HCI OpCode */
+
+ if (p_param)
+ {
+ ARRAY_TO_STREAM(p, p_param, param_len)
+ }
+
+ /* Send message to User Space */
+ btusb_lite_ipc_sent_to_user(p_dev, p_msg);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_sent_to_user
+ **
+ ** Description Send message to User Space (via IPC Interface).
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+static void btusb_lite_ipc_sent_to_user(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ /* Update Lite Statistics */
+ p_dev->lite_cb.stat.event_bytes += p_msg->len;
+ p_dev->lite_cb.stat.event_completed++;
+
+ /* Enqueue message in IPC queue */
+ GKI_enqueue(&p_dev->lite_cb.to_app.ipc_queue, p_msg);
+
+ /* WakeUp IPC read */
+ wake_up_interruptible(&p_dev->rx_wait_q);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_ipc_event_desc
+ **
+ ** Description Get IPC Event description
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+static char *btusb_lite_ipc_event_desc(UINT16 event)
+{
+ switch(event)
+ {
+ case BT_EVT_TO_LM_HCI_CMD:
+ return "BT_EVT_TO_LM_HCI_CMD";
+ case BT_EVT_TO_LM_HCI_ACL:
+ return "BT_EVT_TO_LM_HCI_ACL";
+ case BT_EVT_BTU_IPC_MGMT_EVT:
+ return "BT_EVT_BTU_IPC_MGMT_EVT";
+ case BT_EVT_BTU_IPC_BTU_EVT:
+ return "BT_EVT_BTU_IPC_BTU_EVT";
+ case BT_EVT_BTU_IPC_L2C_EVT:
+ return "BT_EVT_BTU_IPC_L2C_EVT";
+ case BT_EVT_BTU_IPC_ACL_EVT:
+ return "BT_EVT_BTU_IPC_ACL_EVT";
+ case BT_EVT_BTU_IPC_BTM_EVT:
+ return "BT_EVT_BTU_IPC_BTM_EVT";
+ case BT_EVT_BTU_IPC_L2C_MSG_EVT:
+ return "BT_EVT_BTU_IPC_L2C_MSG_EVT";
+ case BT_EVT_BTU_IPC_AVDT_EVT:
+ return "BT_EVT_BTU_IPC_AVDT_EVT";
+ case BT_EVT_BTU_IPC_SLIP_EVT:
+ return "BT_EVT_BTU_IPC_SLIP_EVT";
+ case BT_EVT_BTU_IPC_BTTRC_EVT:
+ return "BT_EVT_BTU_IPC_BTTRC_EVT";
+ case BT_EVT_BTU_IPC_BURST_EVT:
+ return "BT_EVT_BTU_IPC_BURST_EVT";
+ default:
+ return "Unknown Event";
+ }
+}
+
diff --git a/btusb_1_6_29_1/src/btusb_lite_av.c b/btusb_1_6_29_1/src/btusb_lite_av.c
new file mode 100755
index 0000000..b2a1400
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb_lite_av.c
@@ -0,0 +1,1322 @@
+/*
+ *
+ * btusb_lite_av.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include <linux/moduleparam.h>
+#include "btusb.h"
+#include "bd.h"
+#include "btpcm_api.h"
+#include "btsbc_api.h"
+#ifdef BTUSB_LITE_SEC
+#include "btsec_api.h"
+#endif
+
+/*
+ * Definitions
+ */
+#define BTUSB_LITE_AV_PCM_CHANNEL 0
+
+struct btusb_lite_av_sbc_param
+{
+ int frequency;
+ unsigned char nb_blocks;
+ unsigned char nb_subbands;
+ unsigned char mode;
+ unsigned char allocation;
+ unsigned char bitpool_min;
+ unsigned char bitpool_max;
+};
+
+
+/* Codec (From BT Spec) */
+#define A2D_MEDIA_TYPE_AUDIO 0x00
+
+#define A2D_MEDIA_CT_SBC 0x00 /* SBC Codec */
+#define A2D_MEDIA_CT_VEND 0xFF /* Vendor specific */
+
+/* SBC Codec (From BT Spec) */
+#define CODEC_SBC_LOSC 6
+
+#define CODEC_SBC_FREQ_MASK 0xF0
+#define CODEC_SBC_FREQ_48 0x10
+#define CODEC_SBC_FREQ_44 0x20
+#define CODEC_SBC_FREQ_32 0x40
+#define CODEC_SBC_FREQ_16 0x80
+
+#define CODEC_MODE_MASK 0x0F
+#define CODEC_MODE_JOIN_STEREO 0x01
+#define CODEC_MODE_STEREO 0x02
+#define CODEC_MODE_DUAL 0x04
+#define CODEC_MODE_MONO 0x08
+
+#define CODEC_SBC_BLOCK_MASK 0xF0
+#define CODEC_SBC_BLOCK_16 0x10
+#define CODEC_SBC_BLOCK_12 0x20
+#define CODEC_SBC_BLOCK_8 0x40
+#define CODEC_SBC_BLOCK_4 0x80
+
+#define CODEC_SBC_NBBAND_MASK 0x0C
+#define CODEC_SBC_NBBAND_8 0x04
+#define CODEC_SBC_NBBAND_4 0x08
+
+#define CODEC_SBC_ALLOC_MASK 0x03
+#define CODEC_SBC_ALLOC_LOUDNESS 0x01
+#define CODEC_SBC_ALLOC_SNR 0x02
+
+/* SEC codec */
+#ifdef BTUSB_LITE_SEC
+#define A2D_MEDIA_CT_SEC 0x07 /* Internal SEC Codec type */
+
+struct btusb_lite_av_sec_param
+{
+ int frequency;
+ unsigned char mode;
+};
+#endif
+
+
+/*
+ * Globals
+ */
+int pcm0_mute = 0;
+module_param(pcm0_mute, int, S_IRUSR | S_IWUSR | S_IRGRP | S_IWGRP);
+MODULE_PARM_DESC(pcm0_mute, "Mute PCM channel 0");
+
+#define SILENSE_PCM_BUF_SIZE (2 * 128) /* 128 samples, Stereo */
+static const unsigned short btusb_lite_silence_pcm[SILENSE_PCM_BUF_SIZE] = {0};
+
+/*
+ * Local functions
+ */
+static int btusb_lite_av_parse_sbc_codec(struct btusb_lite_av_sbc_param *p_sbc, UINT8 *p_codec);
+static int btusb_lite_sbc_get_bitpool(struct btusb_lite_av_sbc_param *p_sbc_param, int target_bitrate);
+static void btusb_lite_av_pcm_cback(int pcm_stream, void *p_dev, void *p_data,
+ int nb_pcm_frames);
+static void btusb_lite_av_send_packet(struct btusb_cb *p_dev, BT_HDR *p_msg);
+
+static int btusb_lite_av_sbc_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg);
+
+static int btusb_lite_av_parse_vendor_codec(UINT8 *p_codec_info, UINT32 *p_vendor_id, UINT16 *p_vendor_codec_id);
+
+#ifdef BTUSB_LITE_SEC
+static int btusb_lite_av_parse_sec_codec(struct btusb_lite_av_sec_param *p_sec_param,
+ UINT8 *p_codec_info);
+static int btusb_lite_av_sec_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg);
+#endif
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_add
+**
+** Description Add (Sync) an AV channel.
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_add(struct btusb_cb *p_dev, tBTA_AV_SYNC_INFO *p_sync_info,
+ UINT8 multi_av_supported, UINT16 curr_mtu)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int rv;
+
+ p_av_cb->curr_mtu = curr_mtu; /* Update MTU */
+
+ if (p_sync_info->hdi >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad AV Index=%d\n", p_sync_info->hdi);
+ return;
+ }
+
+#if (BTU_MULTI_AV_INCLUDED == TRUE)
+ p_av_cb->multi_av &= ~(BTA_AV_MULTI_AV_SUPPORTED);
+ p_av_cb->multi_av |= multi_av_supported;
+#endif
+
+ p_av_scb = &p_av_cb->scb[p_sync_info->hdi];
+
+ p_av_scb->avdt_handle = p_sync_info->avdt_handle;
+ p_av_scb->chnl = p_sync_info->chnl;
+ p_av_scb->codec_type = p_sync_info->codec_type;
+ p_av_scb->cong = p_sync_info->cong;
+ p_av_scb->hdi = p_sync_info->hdi;
+ p_av_scb->hndl = p_sync_info->hndl;
+ p_av_scb->l2c_bufs = p_sync_info->l2c_bufs;
+ p_av_scb->l2c_cid = p_sync_info->l2c_cid;
+ memcpy(p_av_scb->peer_addr, p_sync_info->peer_addr, BD_ADDR_LEN);
+
+ if (p_av_cb->pcm.state == BTPCM_LITE_PCM_CLOSED)
+ {
+ /* Open the PCM Channel */
+ rv = btpcm_open(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_open failed\n");
+ return;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_OPENED;
+ p_av_cb->pcm.frequency = -1;
+ p_av_cb->pcm.channel = BTUSB_LITE_AV_PCM_CHANNEL;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_remove
+**
+** Description Remove (Cleanup) an AV channel.
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_remove(struct btusb_cb *p_dev, UINT8 scb_idx,
+ UINT8 audio_open_cnt, UINT16 curr_mtu)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int av_scb;
+ int cleanup_needed = 1;
+ int rv;
+
+ p_av_cb->curr_mtu = curr_mtu; /* Update MTU */
+ p_av_cb->audio_open_cnt = audio_open_cnt; /* Update audio_open_cnt */
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad Index=%d\n", scb_idx);
+ return;
+ }
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ /* Remove AVDT CCB and SCB */
+ btusb_lite_avdt_remove_scb(p_dev, p_av_scb->avdt_handle, NULL);
+
+ /* Clear the AV Stream Control Clock */
+ memset(p_av_scb, 0, sizeof(*p_av_scb));
+
+ /* Check this is the last AV channel removed */
+ p_av_scb = &p_av_cb->scb[0];
+ for (av_scb = 0 ; av_scb < BTA_AV_NUM_STRS ; av_scb++, p_av_scb++)
+ {
+ if (p_av_scb->hndl)
+ {
+ cleanup_needed = 0;
+ break;
+ }
+ }
+
+ if (cleanup_needed)
+ {
+ if (p_av_cb->pcm.state == BTPCM_LITE_PCM_STARTED)
+ {
+ /* Stop the PCM Channel */
+ rv = btpcm_stop(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_close failed\n");
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CONFIGURED;
+ }
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_CLOSED)
+ {
+ /* Close the PCM Channel */
+ rv = btpcm_close(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_close failed\n");
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CLOSED;
+ }
+
+ if (p_av_cb->encoder.opened)
+ {
+ switch(p_av_cb->encoder.type)
+ {
+ case A2D_MEDIA_CT_SBC:
+ btsbc_free(p_av_cb->encoder.channel);
+ break;
+#ifdef BTUSB_LITE_SEC
+ case A2D_MEDIA_CT_SEC:
+ btsec_free(p_av_cb->encoder.channel);
+ break;
+#endif
+ default:
+ BTUSB_ERR("Unknown Encoder type=%d\n", p_av_cb->encoder.encoder.codec_type);
+ break;
+ }
+ p_av_cb->encoder.opened = 0;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_start
+**
+** Description Start AV
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_start(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 start_stop_flag,
+ UINT8 audio_open_cnt, tBTA_AV_AUDIO_CODEC_INFO *p_codec_cfg)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ UINT32 vendor_id;
+ UINT16 vendor_codec_id;
+ struct btusb_lite_av_scb *p_av_scb;
+
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return;
+ }
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ if (start_stop_flag)
+ {
+ p_av_cb->scb[scb_idx].started = FALSE;
+ BTUSB_ERR("start_stop_flag TODO!!!");
+ }
+ else
+ {
+ /* If the Codec Type is SBC */
+ if (p_codec_cfg->codec_type == A2D_MEDIA_CT_SBC)
+ {
+ if (btusb_lite_av_sbc_start(p_dev, scb_idx, p_codec_cfg) < 0)
+ {
+ BTUSB_ERR("SBC Stream not started\n");
+ return;
+ }
+ }
+ /* Else if the Codec Type is a Vendor Specific Codec */
+ else if (p_codec_cfg->codec_type == A2D_MEDIA_CT_VEND)
+ {
+ if (btusb_lite_av_parse_vendor_codec(p_codec_cfg->codec_info, &vendor_id, &vendor_codec_id) < 0)
+ {
+ BTUSB_ERR("Unable to parse Vendor Codec\n");
+ return;
+ }
+#ifdef BTUSB_LITE_SEC
+ /* If This is the SEC Encoder */
+ if ((vendor_id == BTSEC_VENDOR_ID) &&
+ (vendor_codec_id == BTSEC_VENDOR_CODEC_ID))
+ {
+ btusb_lite_av_sec_start(p_dev, scb_idx, p_codec_cfg);
+ }
+ else
+#endif
+ /* Add other Vendor Specific Vendor coder Here... */
+ {
+ BTUSB_ERR("Unsupported Codec VendorId=0x%08x VendorCodecId=0x%04x\n", vendor_id, vendor_codec_id);
+ }
+ }
+ else
+ {
+ BTUSB_ERR("Unsupported Encoder type=%d\n", p_codec_cfg->codec_type);
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_parse_vendor_codec
+**
+** Description Parse Vendor Id and Vendor Codec Id from Codec information
+**
+** Returns Status, VendorId and VendorCodecId
+**
+*******************************************************************************/
+static int btusb_lite_av_parse_vendor_codec(UINT8 *p_codec_info, UINT32 *p_vendor_id, UINT16 *p_vendor_codec_id)
+{
+ UINT8 byte;
+ UINT32 vendor_id;
+ UINT16 vendor_codec_id;
+
+ if (!p_codec_info || !p_vendor_id || !p_vendor_codec_id)
+ {
+ BTUSB_ERR("Bad parameter\n");
+ return -1;
+ }
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract LOSC */
+ if (byte < (1 + 1 + 4 + 2)) /* Media Type, Media Codec Type, Vid, VCId */
+ {
+ BTUSB_ERR("Codec LOSC=%d too small\n", byte);
+ return -1;
+ }
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Type */
+ if (byte != A2D_MEDIA_TYPE_AUDIO)
+ {
+ BTUSB_ERR("Unsupported Media Type=0x%x\n", byte);
+ return -1;
+ }
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Codec Type */
+ if (byte != A2D_MEDIA_CT_VEND)
+ {
+ BTUSB_ERR("Media codec Type=0x%x is not Vendor(0xFF)\n", byte);
+ return -1;
+ }
+
+ STREAM_TO_UINT32(vendor_id, p_codec_info); /* Extract Vendor Id */
+ STREAM_TO_UINT16(vendor_codec_id, p_codec_info); /* Extract Vendor Codec Id */
+
+ *p_vendor_id = vendor_id;
+ *p_vendor_codec_id = vendor_codec_id;
+
+ BTUSB_INFO("Extracted Codec VendorId=0x%08x VendorCodecId=0x%04x\n", vendor_id, vendor_codec_id);
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_sbc_start
+**
+** Description Start AV SBC Stream
+**
+** Returns Status
+**
+*******************************************************************************/
+static int btusb_lite_av_sbc_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_encoder_ccb *p_encoder;
+ struct btusb_lite_av_scb *p_av_scb;
+ int nb_sbc_frames;
+ int rv;
+ int bitpool;
+ struct btusb_lite_av_sbc_param sbc_param;
+ int av_header_len;
+
+ /* Parse SBC Codec Info */
+ if (btusb_lite_av_parse_sbc_codec(&sbc_param, p_codec_cfg->codec_info) < 0)
+ {
+ BTUSB_ERR("Bad SBC Codec. Stream not started\n");
+ return -1;
+ }
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return -1;
+ }
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ /* Calculate the BitPool for this BitRate */
+ bitpool = btusb_lite_sbc_get_bitpool(&sbc_param, p_codec_cfg->bit_rate);
+ if (bitpool <= 0)
+ {
+ BTUSB_ERR("btusb_lite_sbc_get_bitpool return wrong bitpool=%d\n", bitpool);
+ return -1;
+ }
+ BTUSB_INFO("SBC BitPool=%d\n", bitpool);
+
+ p_av_cb->timestamp = 0; /* Reset TimeStamp */
+ p_av_cb->option = 0; /* No specific Option (RTP and Media Payload Header presents) */
+ p_av_cb->m_pt = AVDT_RTP_PAYLOAD_TYPE | A2D_MEDIA_CT_SBC;
+ p_av_cb->m_pt &= ~AVDT_MARKER_SET;
+
+ /* Calculate Packet Header Size (HCI, L2CAP, RTP and MediaPayloadHeader) */
+ p_av_cb->header_len = BTUSB_LITE_HCI_ACL_HDR_SIZE +
+ BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE +
+ BTUSB_LITE_SCMS_SIZE +
+ BTUSB_LITE_MEDIA_SIZE;
+ /* Calculate AV Header Size */
+ av_header_len = BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE +
+ BTUSB_LITE_SCMS_SIZE +
+ BTUSB_LITE_MEDIA_SIZE;
+
+ /* clear the congestion flag: full stack made it congested when opening */
+ p_av_scb->cong = FALSE;
+ p_av_scb->started = TRUE;
+
+ /* Get reference to AV's encoder */
+ p_encoder = &p_av_cb->encoder;
+
+ if (p_encoder->opened == 0)
+ {
+ /* Allocate an SBC Channel */
+ rv = btsbc_alloc();
+ if (rv < 0)
+ {
+ BTUSB_ERR("btsbc_alloc failed\n");
+ return -1;
+ }
+ p_encoder->opened = 1;
+ p_encoder->channel = rv;
+ p_encoder->type = A2D_MEDIA_CT_SBC;
+ }
+
+ /* Configure the SBC Channel */
+ rv = btsbc_config(p_encoder->channel,
+ sbc_param.frequency,
+ sbc_param.nb_blocks,
+ sbc_param.nb_subbands,
+ sbc_param.mode,
+ sbc_param.allocation,
+ (unsigned char)bitpool);
+ if (rv <= 0)
+ {
+ BTUSB_ERR("btsbc_config failed\n");
+ btsbc_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+
+ /* Save the calculated SBC Frame size */
+ p_encoder->encoded_frame_size = rv;
+ BTUSB_INFO("encoded_frame_size=%d\n", rv);
+
+ /* Configure the PCM Channel */
+ rv = btpcm_config(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_dev,
+ sbc_param.frequency,
+ sbc_param.mode==CODEC_MODE_MONO?1:2,
+ 16, /* SBC Encoder requires 16 bits per sample */
+ btusb_lite_av_pcm_cback);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_config failed\n");
+ return -1;
+ }
+
+ /* Calculate and save the PCM frame size */
+ p_encoder->pcm_frame_size = sbc_param.nb_blocks * sbc_param.nb_subbands;
+ BTUSB_INFO("pcm_frame_size=%d\n", p_encoder->pcm_frame_size);
+
+ /* Calculate nb_sbc_frames depending on MTU */
+ nb_sbc_frames = (p_av_cb->curr_mtu - av_header_len) / p_encoder->encoded_frame_size;
+
+ /* Calculate the size of the Payload */
+ p_av_cb->payload_len = nb_sbc_frames * p_encoder->encoded_frame_size;
+
+ BTUSB_INFO("nb_sbc_frames=%d payload_len=%d\n", nb_sbc_frames, p_av_cb->payload_len);
+
+ /* Start the PCM stream */
+ rv = btpcm_start(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_encoder->pcm_frame_size, nb_sbc_frames, 0);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_start failed\n");
+ return -1;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_STARTED;
+ return 0;
+}
+
+
+#ifdef BTUSB_LITE_SEC
+/*******************************************************************************
+**
+** Function btusb_lite_av_parse_vendor_codec
+**
+** Description Parse Vendor Id and Vendor Codec Id from Codec information
+**
+** Returns Status, VendorId and VendorCodecId
+**
+*******************************************************************************/
+static int btusb_lite_av_parse_sec_codec(struct btusb_lite_av_sec_param *p_sec_param,
+ UINT8 *p_codec_info)
+{
+ UINT8 byte;
+ UINT32 vendor_id;
+ UINT16 vendor_codec_id;
+
+ if (!p_codec_info || !p_sec_param)
+ {
+ BTUSB_ERR("Bad parameter\n");
+ return -1;
+ }
+
+ /* Extract/Ignore parameters already checked */
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract LOSC */
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Type */
+ STREAM_TO_UINT8(byte, p_codec_info); /* Extract Media Codec Type */
+ STREAM_TO_UINT32(vendor_id, p_codec_info); /* Extract Vendor Id */
+ STREAM_TO_UINT16(vendor_codec_id, p_codec_info); /* Extract Vendor Codec Id */
+
+ STREAM_TO_UINT8(byte, p_codec_info); /* SEC codec configuration */
+
+ /* Check Frequency */
+ switch(byte & BTSEC_FREQ_MASK)
+ {
+ case BTSEC_FREQ_48K:
+ p_sec_param->frequency = 48000;
+ break;
+ case BTSEC_FREQ_44K:
+ p_sec_param->frequency = 44100;
+ break;
+ case BTSEC_FREQ_32K:
+ p_sec_param->frequency = 32000;
+ break;
+ default:
+ BTUSB_ERR("SEC Frequency=0x%x unsupported\n", byte & BTSEC_FREQ_MASK);
+ return -1;
+ }
+
+ /* Check Mode */
+ switch(byte & BTSEC_MODE_MASK)
+ {
+ case BTSEC_MODE_MONO:
+ p_sec_param->mode = BTSEC_MODE_MONO;
+ break;
+ case BTSEC_MODE_STEREO:
+ p_sec_param->mode = BTSEC_MODE_STEREO;
+ break;
+ default:
+ BTUSB_ERR("SEC Mode=0x%x unsupported\n", byte & BTSEC_FREQ_MASK);
+ return -1;
+ }
+
+ BTUSB_INFO("SEC Frequency=%d Mode=%s\n", p_sec_param->frequency,
+ p_sec_param->mode == BTSEC_MODE_MONO?"Mono":"Stereo");
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_sec_start
+**
+** Description Start AV SBC Stream
+**
+** Returns Status
+**
+*******************************************************************************/
+static int btusb_lite_av_sec_start(struct btusb_cb *p_dev, UINT8 scb_idx,
+ tBTA_AV_AUDIO_CODEC_INFO*p_codec_cfg)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_encoder_ccb *p_encoder;
+ struct btusb_lite_av_scb *p_av_scb;
+ int nb_sec_frames;
+ int rv;
+ struct btusb_lite_av_sec_param sec_param;
+ int av_header_len;
+
+ /* Parse SBC Codec Info */
+ if (btusb_lite_av_parse_sec_codec(&sec_param, p_codec_cfg->codec_info) < 0)
+ {
+ BTUSB_ERR("Bad SEC Codec parameters. Stream not started\n");
+ return -1;
+ }
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return -1;
+ }
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ BTUSB_INFO("SEC Bitrate =%d\n", p_codec_cfg->bit_rate);
+
+ p_av_cb->timestamp = 0; /* Reset TimeStamp */
+ p_av_cb->option = BTUSB_LITE_AVDT_OPT_NO_MPH; /* No Media Payload Header */
+ p_av_cb->m_pt = AVDT_RTP_PAYLOAD_TYPE | A2D_MEDIA_CT_VEND;
+ p_av_cb->m_pt &= ~AVDT_MARKER_SET;
+
+ /* Calculate Packet Header Size (HCI, L2CAP, RTP) */
+ p_av_cb->header_len = BTUSB_LITE_HCI_ACL_HDR_SIZE +
+ BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE;
+ /* Calculate AV Header Size */
+ av_header_len = BTUSB_LITE_L2CAP_HDR_SIZE +
+ BTUSB_LITE_RTP_SIZE;
+
+ /* Clear the congestion flag: full stack made it congested when opening */
+ p_av_scb->cong = FALSE;
+ p_av_scb->started = TRUE;
+
+ /* Get reference to AV's encoder */
+ p_encoder = &p_av_cb->encoder;
+
+ if (p_encoder->opened == 0)
+ {
+ /* Allocate a SEC Channel */
+ rv = btsec_alloc();
+ if (rv < 0)
+ {
+ BTUSB_ERR("btsec_alloc failed\n");
+ return -1;
+ }
+ p_encoder->opened = 1;
+ p_encoder->channel = rv;
+ p_encoder->type = A2D_MEDIA_CT_SEC;
+
+ }
+
+ /* Configure the SEC Channel */
+ rv = btsec_config(p_encoder->channel,
+ sec_param.frequency,
+ sec_param.mode,
+ p_codec_cfg->bit_rate * 1000);
+ if (rv <= 0)
+ {
+ BTUSB_ERR("btsec_config failed\n");
+ btsec_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+
+ /* Save the calculated SEC Frame size */
+ p_encoder->encoded_frame_size = rv;
+ BTUSB_INFO("encoded_frame_size=%d\n", rv);
+
+ /* Configure the PCM Channel */
+ rv = btpcm_config(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_dev,
+ sec_param.frequency,
+ sec_param.mode==BTSEC_MODE_MONO?1:2,
+ 16, /* SBC Encoder requires 16 bits per sample */
+ btusb_lite_av_pcm_cback);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_config failed\n");
+ btsec_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+
+ /* SEC requires a fixed number of PCM Samples */
+ p_encoder->pcm_frame_size = BTSEC_FRAME_SIZE;
+ BTUSB_INFO("pcm_frame_size=%d\n", p_encoder->pcm_frame_size);
+
+ /* Calculate nb_sbc_frames depending on MTU */
+ nb_sec_frames = (p_av_cb->curr_mtu - av_header_len) / p_encoder->encoded_frame_size;
+
+ /* Calculate the size of the Payload */
+ p_av_cb->payload_len = nb_sec_frames * p_encoder->encoded_frame_size;
+
+ BTUSB_INFO("nb_sec_frames=%d payload_len=%d\n", nb_sec_frames, p_av_cb->payload_len);
+
+ /* Start the PCM stream */
+ rv = btpcm_start(BTUSB_LITE_AV_PCM_CHANNEL,
+ p_encoder->pcm_frame_size, nb_sec_frames, 0);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_start failed\n");
+ btsec_free(p_encoder->channel);
+ p_encoder->opened = 0;
+ return -1;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_STARTED;
+ return 0;
+}
+#endif
+
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_stop
+**
+** Description Start AV
+**
+** Returns None.
+**
+*******************************************************************************/
+void btusb_lite_av_stop(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int rv;
+
+ BTUSB_INFO("scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return;
+ }
+
+ p_av_cb->audio_open_cnt = audio_open_cnt;
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ p_av_cb->scb[scb_idx].started = FALSE;
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_STARTED)
+ {
+ BTUSB_ERR("BTPCM was not started\n");
+ return;
+ }
+
+ /* Stop the PCM stream */
+ rv = btpcm_stop(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_stop failed\n");
+ return;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CONFIGURED;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_suspend
+**
+** Description Suspend AV
+**
+** Returns none.
+**
+*******************************************************************************/
+void btusb_lite_av_suspend(struct btusb_cb *p_dev, UINT8 scb_idx, UINT8 audio_open_cnt)
+{
+ struct btusb_lite_av_cb *p_av_cb = &p_dev->lite_cb.av;
+ struct btusb_lite_av_scb *p_av_scb;
+ int rv;
+
+ BTUSB_INFO("scb_idx=%d audio_open_cnt=%d\n", scb_idx, audio_open_cnt);
+
+ if (scb_idx >= BTA_AV_NUM_STRS)
+ {
+ BTUSB_ERR("Bad scb_idx=%d", scb_idx);
+ return;
+ }
+
+ p_av_cb->audio_open_cnt = audio_open_cnt;
+
+ p_av_scb = &p_av_cb->scb[scb_idx];
+
+ p_av_cb->scb[scb_idx].started = FALSE;
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_STARTED)
+ {
+ BTUSB_ERR("BTPCM was not started\n");
+ return;
+ }
+
+ /* Stop the PCM stream */
+ rv = btpcm_stop(BTUSB_LITE_AV_PCM_CHANNEL);
+ if (rv < 0)
+ {
+ BTUSB_ERR("btpcm_stop failed\n");
+ return;
+ }
+ p_av_cb->pcm.state = BTPCM_LITE_PCM_CONFIGURED;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_av_parse_sbc_codec
+**
+** Description Parse an SBC A2DP Codec
+**
+** Returns Status
+**
+*******************************************************************************/
+static int btusb_lite_av_parse_sbc_codec(struct btusb_lite_av_sbc_param *p_sbc, UINT8 *p_codec)
+{
+ UINT8 byte;
+ unsigned char codec_freq;
+ unsigned char codec_blocks;
+ unsigned char codec_subbands;
+ unsigned char codec_mode;
+ unsigned char codec_alloc;
+ unsigned char bitpool_min;
+ unsigned char bitpool_max;
+
+ if (p_sbc == NULL)
+ {
+ BTUSB_ERR("p_sbc is NULL\n");
+ return -1;
+ }
+
+ /* Extract LOSC */
+ byte = *p_codec++;
+ if (byte != CODEC_SBC_LOSC)
+ {
+ BTUSB_ERR("Bad SBC LOSC=%d", byte);
+ return -1;
+ }
+
+ p_codec++; /* Ignore MT */
+
+ /* Extract Codec Type */
+ byte = *p_codec++;
+ if (byte != A2D_MEDIA_CT_SBC)
+ {
+ BTUSB_ERR("Bad SBC codec type=%d", byte);
+ return -1;
+ }
+
+ /* Extract Freq & Mode */
+ byte = *p_codec++;
+ codec_freq = byte & CODEC_SBC_FREQ_MASK;
+ codec_mode = byte & CODEC_MODE_MASK;
+
+ /* Extract NbBlock NbSubBand and Alloc Method */
+ byte = *p_codec++;
+ codec_blocks = byte & CODEC_SBC_BLOCK_MASK;
+ codec_subbands = byte & CODEC_SBC_NBBAND_MASK;
+ codec_alloc = byte & CODEC_SBC_ALLOC_MASK;
+
+ bitpool_min = *p_codec++;
+ bitpool_max = *p_codec++;
+
+ switch(codec_freq)
+ {
+ case CODEC_SBC_FREQ_48:
+ BTUSB_INFO("SBC Freq=48K\n");
+ p_sbc->frequency = 48000;
+ break;
+ case CODEC_SBC_FREQ_44:
+ BTUSB_INFO("SBC Freq=44.1K\n");
+ p_sbc->frequency = 44100;
+ break;
+ case CODEC_SBC_FREQ_32:
+ BTUSB_INFO("SBC Freq=32K\n");
+ p_sbc->frequency = 32000;
+ break;
+ case CODEC_SBC_FREQ_16:
+ BTUSB_INFO("SBC Freq=16K\n");
+ p_sbc->frequency = 16000;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC Freq=%d\n", codec_freq);
+ return -1;
+ }
+
+ switch(codec_mode)
+ {
+ case CODEC_MODE_JOIN_STEREO:
+ BTUSB_INFO("SBC Join Stereo\n");
+ p_sbc->mode = CODEC_MODE_JOIN_STEREO;
+ break;
+ case CODEC_MODE_STEREO:
+ BTUSB_INFO("SBC Stereo\n");
+ p_sbc->mode = CODEC_MODE_STEREO;
+ break;
+ case CODEC_MODE_DUAL:
+ BTUSB_INFO("SBC Dual\n");
+ p_sbc->mode = CODEC_MODE_DUAL;
+ break;
+ case CODEC_MODE_MONO:
+ BTUSB_INFO("SBC Mono\n");
+ p_sbc->mode = CODEC_MODE_MONO;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC mode=%d\n", codec_mode);
+ return -1;
+ }
+
+ switch(codec_blocks)
+ {
+ case CODEC_SBC_BLOCK_16:
+ BTUSB_INFO("SBC Block=16\n");
+ p_sbc->nb_blocks = 16;
+ break;
+ case CODEC_SBC_BLOCK_12:
+ BTUSB_INFO("SBC Block=12\n");
+ p_sbc->nb_blocks = 12;
+ break;
+ case CODEC_SBC_BLOCK_8:
+ BTUSB_INFO("SBC Block=8\n");
+ p_sbc->nb_blocks = 8;
+ break;
+ case CODEC_SBC_BLOCK_4:
+ BTUSB_INFO("SBC Block=4\n");
+ p_sbc->nb_blocks = 4;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC Block=%d\n", codec_blocks);
+ return -1;
+ }
+
+ switch(codec_subbands)
+ {
+ case CODEC_SBC_NBBAND_8:
+ BTUSB_INFO("SBC NbSubBand=8\n");
+ p_sbc->nb_subbands = 8;
+ break;
+ case CODEC_SBC_NBBAND_4:
+ BTUSB_INFO("SBC NbSubBand=4\n");
+ p_sbc->nb_subbands = 4;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC NbSubBand=%d\n", codec_blocks);
+ return -1;
+ }
+
+ switch(codec_alloc)
+ {
+ case CODEC_SBC_ALLOC_LOUDNESS:
+ BTUSB_INFO("SBC Loudness\n");
+ p_sbc->allocation = CODEC_SBC_ALLOC_LOUDNESS;
+ break;
+ case CODEC_SBC_ALLOC_SNR:
+ BTUSB_INFO("SBC SNR\n");
+ p_sbc->allocation = CODEC_SBC_ALLOC_SNR;
+ break;
+ default:
+ BTUSB_INFO("Bad SBC AllocMethod=%d\n", codec_blocks);
+ return -1;
+ }
+
+ BTUSB_INFO("BitpoolMin=%d BitpoolMax=%d\n", bitpool_min, bitpool_max);
+
+ p_sbc->bitpool_min = bitpool_min;
+ p_sbc->bitpool_max = bitpool_max;
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_sbc_get_bitpool
+ **
+ ** Description Calculate the BitPool for a specified BitRate (and other parameters)
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static int btusb_lite_sbc_get_bitpool(struct btusb_lite_av_sbc_param *p_sbc_param, int target_bitrate)
+{
+ int nb_channels;
+ int frame_length;
+ int bitpool = p_sbc_param->bitpool_max + 1;
+ int bitrate;
+
+ /* Required number of channels */
+ if (p_sbc_param->mode == CODEC_MODE_MONO)
+ nb_channels = 1;
+ else
+ nb_channels = 2;
+
+ target_bitrate *= 1000; /* Bitrate from app is in Kbps */
+
+ do
+ {
+ bitpool--; /* Reduce Bit Pool by one */
+
+ /* Calculate common SBC Frame length */
+ frame_length = 4 + (4 * p_sbc_param->nb_subbands * nb_channels) / 8;
+
+ /* Add specific SBC Frame length (depending on mode) */
+ switch(p_sbc_param->mode)
+ {
+ case CODEC_MODE_MONO:
+ case CODEC_MODE_DUAL:
+ frame_length += (p_sbc_param->nb_blocks * nb_channels * bitpool) / 8;
+ break;
+ case CODEC_MODE_JOIN_STEREO:
+ frame_length += (p_sbc_param->nb_subbands + p_sbc_param->nb_blocks * bitpool) / 8;
+ break;
+ case CODEC_MODE_STEREO:
+ frame_length += (p_sbc_param->nb_blocks * bitpool) / 8;
+ break;
+ }
+
+ /* Calculate bit rate */
+ bitrate = 8 * frame_length * p_sbc_param->frequency / p_sbc_param->nb_subbands / p_sbc_param->nb_blocks;
+
+ } while (bitrate > target_bitrate); /* While bitrate is too big */
+
+ BTUSB_INFO("final bitpool=%d frame_length=%d bitrate=%d\n", bitpool, frame_length, bitrate);
+
+ return (int)bitpool;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_av_pcm_cback
+ **
+ ** Description BTUSB Lte AV PCM Callback function.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_av_pcm_cback(int pcm_stream, void *p_dev, void *p_data,
+ int nb_pcm_frames)
+{
+ struct btusb_lite_av_cb *p_av_cb;
+ int pcm_frame_size_byte;
+ void *p_dest;
+ int written_enc_size;
+ struct btusb_lite_encoder_ccb *p_encoder;
+
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("Null _p_dev\n");
+ return;
+ }
+
+ if (p_data == NULL)
+ {
+ BTUSB_ERR("Null p_data\n");
+ return;
+ }
+
+ if (pcm_stream != BTUSB_LITE_AV_PCM_CHANNEL)
+ {
+ BTUSB_ERR("Bad stream=%d\n", pcm_stream);
+ return;
+ }
+
+ /* Get Reference on the SBC Stream (which is the same than the Encoder channel) */
+ p_av_cb = &((struct btusb_cb *)p_dev)->lite_cb.av;
+
+ if (p_av_cb->pcm.state != BTPCM_LITE_PCM_STARTED)
+ {
+ BTUSB_ERR("BTPCM is not started\n");
+ btpcm_stop(pcm_stream);
+ return;
+ }
+
+ /* Get reference to AV's encoder */
+ p_encoder = &p_av_cb->encoder;
+
+ /* Calculate the size (in byte) of an Input PCM buffer (holding one encoded frame) */
+ pcm_frame_size_byte = p_av_cb->encoder.pcm_frame_size;
+ pcm_frame_size_byte *= 2; /* Stereo */
+ pcm_frame_size_byte *= 2; /* 16 bits per sample */
+
+ /* Sanity Check */
+ if (pcm_frame_size_byte == 0)
+ {
+ BTUSB_ERR("Bad PCM Frame size=%d\n", pcm_frame_size_byte);
+ return;
+ }
+
+ /* While received buffer is not empty */
+ while (nb_pcm_frames)
+ {
+ /* Check if there are enough remaining frames in the buffer */
+ if ((nb_pcm_frames * 2 * 2) < pcm_frame_size_byte)
+ {
+ BTUSB_ERR("Bad nb_pcm_frames=%d\n", nb_pcm_frames);
+ return;
+ }
+
+ /* If no working buffer allocated */
+ if (p_av_cb->p_buf_working == NULL)
+ {
+ /* Get a buffer from the pool */
+ p_av_cb->p_buf_working = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + p_av_cb->header_len + p_av_cb->payload_len);
+ if(unlikely(p_av_cb->p_buf_working == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer - sent fail\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_av_cb->p_buf_working) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_av_cb->p_buf_working);
+ return;
+ }
+
+ /* Skip headers */
+ p_av_cb->p_buf_working->offset = p_av_cb->header_len;
+ p_av_cb->p_buf_working->len = 0;
+ p_av_cb->p_buf_working->layer_specific = 0; /* Used to store the number of Encoded Frames */
+ }
+
+ /* Fill the ACL Packet with SBC Frames */
+ do
+ {
+ /* Get Write address */
+ p_dest = (UINT8 *)(p_av_cb->p_buf_working + 1) + p_av_cb->p_buf_working->offset +
+ p_av_cb->p_buf_working->len;
+
+ if (p_encoder->type == A2D_MEDIA_CT_SBC)
+ {
+ /* Encode one PCM frame with SBC Encoder*/
+ btsbc_encode(p_encoder->channel,
+ /* If Mute => Zero filled PCM sample*/
+ /* Otherwise => regular PCM data */
+ pcm0_mute?btusb_lite_silence_pcm:p_data,
+ pcm_frame_size_byte,
+ p_dest, /* SBC Output buffer */
+ p_av_cb->encoder.encoded_frame_size, /* Expected Output SBC frame size */
+ &written_enc_size);
+ }
+#ifdef BTUSB_LITE_SEC
+ else if (p_encoder->type == A2D_MEDIA_CT_SEC)
+ {
+ /* Encode one PCM frame with SEC Encoder*/
+ written_enc_size = btsec_encode(p_av_cb->encoder.channel,
+ /* If Mute => Zero filled PCM sample*/
+ /* Otherwise => regular PCM data */
+ pcm0_mute?btusb_lite_silence_pcm:p_data,
+ pcm_frame_size_byte,
+ p_dest, /* SEC Output buffer */
+ p_encoder->encoded_frame_size);/* Expected Output SEC frame size */
+ }
+#endif
+ if (written_enc_size != p_av_cb->encoder.encoded_frame_size)
+ {
+ BTUSB_ERR("Bad Encoded Fame lenght=%d (expected=%d)\n",
+ written_enc_size, p_av_cb->encoder.encoded_frame_size);
+ }
+
+ /* Update Encoded packet length */
+ p_av_cb->p_buf_working->len += (UINT16)p_av_cb->encoder.encoded_frame_size;
+
+ /* One more Encoded Frame */
+ p_av_cb->p_buf_working->layer_specific++;
+
+ p_data += pcm_frame_size_byte; /* Jump to the next PCM sample */
+ nb_pcm_frames -= pcm_frame_size_byte / 4; /* Update number of remaining samples */
+
+ } while (nb_pcm_frames &&
+ (p_av_cb->p_buf_working->layer_specific < A2D_SBC_HDR_NUM_MSK) &&
+ ((p_av_cb->p_buf_working->len + p_av_cb->encoder.encoded_frame_size) < p_av_cb->curr_mtu));
+
+ /* If no more room to store an encoded frame */
+ if (p_av_cb->encoder.encoded_frame_size > (p_av_cb->curr_mtu - p_av_cb->p_buf_working->len))
+ {
+ /* For AV channel, send the packet */
+ btusb_lite_av_send_packet((struct btusb_cb *)p_dev, p_av_cb->p_buf_working);
+
+ /* A new working buffer must be allocated */
+ p_av_cb->p_buf_working = NULL;
+ }
+ }
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_av_send_packet
+ **
+ ** Description Send a new BAV packet to the controller
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_av_send_packet(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ struct btusb_lite_av_cb *p_av_cb;
+ struct btusb_lite_av_scb *p_av_scb;
+ int stream;
+ int nb_started_streams;
+ BT_HDR *p_msg_dup;
+
+ if (!p_dev || !p_msg)
+ {
+ BTUSB_ERR("Bad reference p_dev=%p p_msg=%p\n", p_dev, p_msg);
+ return;
+ }
+
+ /* Sanity */
+ if (p_msg->len == 0)
+ {
+ BTUSB_ERR("Length is 0=%d\n", p_msg->len);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+
+ /* Get Reference on the AV Streams */
+ p_av_cb = &((struct btusb_cb *)p_dev)->lite_cb.av;
+
+ /* Update TimeStamp */
+ p_av_cb->timestamp += p_msg->layer_specific * p_av_cb->encoder.pcm_frame_size;
+
+ nb_started_streams = 0;
+ /* Count how many AV stream are started */
+ for (stream = 0, p_av_scb = p_av_cb->scb ; stream < BTA_AV_NUM_STRS ; stream++, p_av_scb++)
+ {
+ if (p_av_scb->started)
+ {
+ nb_started_streams++; /* One more started stream */
+ }
+ }
+
+ if (nb_started_streams == 0)
+ {
+ BTUSB_ERR("No Started AV stream found\n");
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ else if (nb_started_streams == 1)
+ {
+ p_msg_dup = NULL;
+ }
+ else
+ {
+ /*
+ * Duplicate the AV packet
+ */
+ /* Get a buffer from the pool */
+ p_msg_dup = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + p_msg->offset + p_msg->offset);
+ if(p_msg_dup)
+ {
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg_dup) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg_dup);
+ p_msg_dup = NULL; /* Do not use this buffer */
+ }
+ if(p_msg_dup)
+ {
+ /* Duplicate all the data (Header, and payload */
+ memcpy(p_msg_dup, p_msg, sizeof(BT_HDR) + p_msg->offset + p_msg->offset);
+ }
+ }
+ if (nb_started_streams > 2)
+ {
+ BTUSB_ERR("nb_started_streams=%d force it to 2\n", nb_started_streams);
+ nb_started_streams = 2;
+ }
+ }
+
+ /* For every AV stream Started */
+ for (stream = 0, p_av_scb = p_av_cb->scb ; stream < BTA_AV_NUM_STRS ; stream++, p_av_scb++)
+ {
+ if (p_av_scb->started)
+ {
+ if (p_msg)
+ {
+ /* Send the original packet to AVDT */
+ btusb_lite_avdt_send(p_dev, p_msg, p_av_scb->avdt_handle,
+ p_av_cb->m_pt, p_av_cb->option, p_av_cb->timestamp);
+ p_msg = NULL;
+ }
+ else if (p_msg_dup)
+ {
+ /* Send the duplicated packet to AVDT */
+ btusb_lite_avdt_send(p_dev, p_msg_dup, p_av_scb->avdt_handle,
+ p_av_cb->m_pt, p_av_cb->option, p_av_cb->timestamp);
+ p_msg_dup = NULL;
+ }
+ else
+ {
+ BTUSB_ERR("No AV data to send for AV stream=%d \n", stream);
+ }
+ }
+ }
+}
+
diff --git a/btusb_1_6_29_1/src/btusb_lite_avdt.c b/btusb_1_6_29_1/src/btusb_lite_avdt.c
new file mode 100755
index 0000000..46cf0ce
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb_lite_avdt.c
@@ -0,0 +1,426 @@
+/*
+ *
+ * btusb_lite_avdt.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include "btusb.h"
+#include "bd.h"
+
+/*
+ * Definitions
+ */
+#define AVDT_MULTIPLEXING FALSE
+
+
+/*
+ * Local functions
+ */
+static struct btusb_lite_avdt_scb *btusb_lite_avdt_allocate_scb(struct btusb_cb *p_dev);
+static void btusb_lite_avdt_free_scb(struct btusb_cb *p_dev, struct btusb_lite_avdt_scb *p_scb_free);
+static struct btusb_lite_avdt_ccb *btusb_lite_avdt_allocate_ccb(struct btusb_cb *p_dev);
+static void btusb_lite_avdt_free_ccb(struct btusb_cb *p_dev, struct btusb_lite_avdt_ccb *p_ccb_free);
+static UINT8 *btusb_lite_avdt_write_rtp_header(UINT8 *p_data, UINT8 m_pt, UINT16 seq_number, UINT32 timestamp, UINT32 ssrc);
+
+
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_scb_by_hdl
+**
+** Description Given an scb handle (or seid), return a pointer to the scb.
+**
+**
+** Returns Pointer to scb or NULL if index is out of range or scb
+** is not allocated.
+**
+*******************************************************************************/
+struct btusb_lite_avdt_scb *btusb_lite_avdt_scb_by_hdl(struct btusb_cb *p_dev, UINT8 handle)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 scb;
+
+ p_scb = &p_dev->lite_cb.avdt.scb[0];
+ for(scb = 0; scb < AVDT_NUM_SEPS; scb++, p_scb++ )
+ {
+ if((p_scb->allocated) &&
+ (p_scb->handle == handle))
+ return(p_scb);
+ }
+ return(NULL);
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_init_scb
+**
+** Description allocate and initialize SCB/CCB with received sync info
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_init_scb(struct btusb_cb *p_dev, tAVDT_SCB_SYNC_INFO *p_scb_info)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ struct btusb_lite_avdt_ccb *p_ccb;
+
+ if((p_scb = btusb_lite_avdt_allocate_scb(p_dev)) == NULL)
+ {
+ BTUSB_ERR("No SCB for handle %d\n", p_scb_info->handle);
+ return AVDT_SYNC_FAILURE;
+ }
+ else
+ {
+ if((p_ccb = btusb_lite_avdt_allocate_ccb(p_dev)) == NULL)
+ {
+ BTUSB_ERR("No CCB for handle %d\n", p_scb_info->handle);
+ p_scb->allocated = FALSE;
+ return AVDT_SYNC_FAILURE;
+ }
+ else
+ {
+ memcpy(p_ccb->peer_addr, p_scb_info->peer_addr, BD_ADDR_LEN);
+ p_ccb->lcid = p_scb_info->local_cid;
+ p_ccb->peer_mtu = p_scb_info->peer_mtu;
+#if AVDT_MULTIPLEXING == TRUE
+ GKI_init_q(&p_scb->frag_q);
+#endif
+ p_scb->handle = p_scb_info->handle;
+ p_scb->mux_tsid_media = p_scb_info->mux_tsid_media;
+ p_scb->media_seq = p_scb_info->media_seq;
+ p_scb->p_ccb = p_ccb;
+ BTUSB_INFO("Allocated SCB/CCB for handle %d\n", p_scb_info->handle);
+ }
+ }
+ return AVDT_SYNC_SUCCESS;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_remove_scb
+**
+** Description deallocate SCB and CCB
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_remove_scb(struct btusb_cb *p_dev, UINT8 handle, tAVDT_SCB_SYNC_INFO *p_scb_info)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+
+ if((p_scb = btusb_lite_avdt_scb_by_hdl(p_dev, handle)) == NULL)
+ {
+ BTUSB_ERR("No SCB for handle %d\n", handle);
+ return AVDT_SYNC_FAILURE;
+ }
+ else
+ {
+ if (p_scb_info)
+ {
+ p_scb_info->handle = p_scb->handle;
+ p_scb_info->media_seq = p_scb->media_seq;
+ }
+ /* Free CCB first */
+ btusb_lite_avdt_free_ccb(p_dev, p_scb->p_ccb);
+ /* Free SCB */
+ btusb_lite_avdt_free_scb(p_dev, p_scb);
+
+ return AVDT_SYNC_SUCCESS;
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_allocate_ccb
+**
+** Description allocate CCB in lite stack
+**
+** Returns pointer of CCB
+**
+*******************************************************************************/
+static struct btusb_lite_avdt_ccb *btusb_lite_avdt_allocate_ccb(struct btusb_cb *p_dev)
+{
+ struct btusb_lite_avdt_ccb *p_ccb;
+ UINT8 ccb;
+
+ p_ccb = &p_dev->lite_cb.avdt.ccb[0];
+ for(ccb = 0; ccb < AVDT_NUM_LINKS; ccb++, p_ccb++)
+ {
+ if (!p_ccb->allocated)
+ {
+ BTUSB_INFO("CCB=%d allocated\n", ccb);
+ memset(p_ccb, 0, sizeof(struct btusb_lite_avdt_ccb));
+ p_ccb->allocated = TRUE;
+ return(p_ccb);
+ }
+ }
+ return(NULL);
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_free_ccb
+**
+** Description Free CCB in lite stack
+**
+** Returns None
+**
+*******************************************************************************/
+static void btusb_lite_avdt_free_ccb(struct btusb_cb *p_dev, struct btusb_lite_avdt_ccb *p_ccb_free)
+{
+ struct btusb_lite_avdt_ccb *p_ccb;
+ UINT8 ccb;
+
+ p_ccb = &p_dev->lite_cb.avdt.ccb[0];
+ for(ccb = 0; ccb < AVDT_NUM_LINKS; ccb++, p_ccb++)
+ {
+ if (p_ccb == p_ccb_free)
+ {
+ /* Sanity */
+ if (!p_ccb_free->allocated)
+ {
+ BTUSB_ERR("CCB=%d was not allocated\n", ccb);
+ }
+ BTUSB_INFO("CCB=%d freed\n", ccb);
+ p_ccb_free->allocated = FALSE;
+ return;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_allocate_scb
+**
+** Description allocate SCB in lite stack
+**
+** Returns pointer of SCB
+**
+*******************************************************************************/
+static struct btusb_lite_avdt_scb *btusb_lite_avdt_allocate_scb(struct btusb_cb *p_dev)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 scb;
+
+ p_scb = &p_dev->lite_cb.avdt.scb[0];
+ for(scb = 0; scb < AVDT_NUM_SEPS; scb++, p_scb++)
+ {
+ if(!p_scb->allocated)
+ {
+ BTUSB_INFO("SCB=%d allocated\n", scb);
+ memset(p_scb, 0, sizeof(struct btusb_lite_avdt_scb));
+ p_scb->allocated = TRUE;
+ return(p_scb);
+ }
+ }
+ return(NULL);
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_free_scb
+**
+** Description Free SCB in lite stack
+**
+** Returns None
+**
+*******************************************************************************/
+static void btusb_lite_avdt_free_scb(struct btusb_cb *p_dev, struct btusb_lite_avdt_scb *p_scb_free)
+{
+ struct btusb_lite_avdt_scb *p_scb;
+ UINT8 scb;
+
+ p_scb = &p_dev->lite_cb.avdt.scb[0];
+ for(scb = 0; scb < AVDT_NUM_SEPS; scb++, p_scb++)
+ {
+ if (p_scb == p_scb_free)
+ {
+ /* Sanity */
+ if (!p_scb_free->allocated)
+ {
+ BTUSB_ERR("SCB=%d was not allocated\n", scb);
+ }
+ BTUSB_INFO("SCB=%d freed\n", scb);
+ p_scb_free->allocated = FALSE;
+ return;
+ }
+ }
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_send
+**
+** Description AVDT packet send
+**
+** Returns None
+**
+*******************************************************************************/
+void btusb_lite_avdt_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT8 avdt_handle,
+ UINT8 m_pt, UINT8 option, UINT32 timestamp)
+{
+ UINT8 *p_data;
+ struct btusb_lite_avdt_scb *p_avdt_scb;
+ struct btusb_lite_avdt_ccb *p_avdt_ccb;
+
+ if (p_dev == NULL)
+ {
+ BTUSB_ERR("p_dev is NULL\n");
+ if (p_msg)
+ GKI_freebuf(p_msg);
+ return;
+ }
+
+ if (p_msg == NULL)
+ {
+ BTUSB_ERR("p_msg is NULL\n");
+ return;
+ }
+
+ /* Find the AVDT SCB with this handle */
+ p_avdt_scb = btusb_lite_avdt_scb_by_hdl(p_dev, avdt_handle);
+ if (p_avdt_scb == NULL)
+ {
+ BTUSB_ERR("No AVDT SCB stream found\n");
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+
+ /* Get the associated AVDT CCB */
+ p_avdt_ccb = p_avdt_scb->p_ccb;
+ if (p_avdt_ccb == NULL)
+ {
+ BTUSB_ERR("No AVDT CCB stream found\n");
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+
+ /* Write the Media Payload Header if needed */
+ if ((option & BTUSB_LITE_AVDT_OPT_NO_MPH) == 0)
+ {
+ if (p_msg->offset < BTUSB_LITE_MEDIA_SIZE)
+ {
+ BTUSB_ERR("Offset too small=%d for MediaPayloadHeader\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ p_msg->offset -= BTUSB_LITE_MEDIA_SIZE;
+ p_msg->len += BTUSB_LITE_MEDIA_SIZE;
+ /* Get write address */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ /* Write Media Payload Header (Number of SBC Frames) */
+ UINT8_TO_BE_STREAM(p_data, p_msg->layer_specific & A2D_SBC_HDR_NUM_MSK);
+ }
+
+ /* Write the SCMS content Protection Header if needed */
+ if (p_avdt_scb->scms.enable)
+ {
+ if (p_msg->offset < BTUSB_LITE_SCMS_SIZE)
+ {
+ BTUSB_ERR("Offset too small=%d for CP Header\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ p_msg->offset -= BTUSB_LITE_SCMS_SIZE;
+ p_msg->len += BTUSB_LITE_SCMS_SIZE;
+ /* Get write address */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ /* Write Media Payload Header (Number of SBC Frames) */
+ UINT8_TO_BE_STREAM(p_data, p_avdt_scb->scms.header);
+ }
+
+ /* Write the RTP Header if needed */
+ if ((option & BTUSB_LITE_AVDT_OPT_NO_RTP) == 0)
+ {
+ if (p_msg->offset < BTUSB_LITE_RTP_SIZE)
+ {
+ BTUSB_ERR("Offset too small=%d for RTP Header\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return;
+ }
+ p_msg->offset -= BTUSB_LITE_RTP_SIZE;
+ p_msg->len += BTUSB_LITE_RTP_SIZE;
+ /* Get write address */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+ /* Write RTP Header */
+ p_data = btusb_lite_avdt_write_rtp_header(p_data, m_pt, p_avdt_scb->media_seq, timestamp, 0);
+ }
+
+ p_avdt_scb->media_seq++; /* Increment Sequence number */
+
+ /* Request L2CAP to send this packet */
+ btusb_lite_l2c_send(p_dev, p_msg, p_avdt_ccb->lcid);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_avdt_write_rtp_header
+ **
+ ** Description Write A2DP RTP Header
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_avdt_write_rtp_header(UINT8 *p_data, UINT8 m_pt, UINT16 seq_number,
+ UINT32 timestamp, UINT32 ssrc)
+{
+ /* Write RTP Header */
+ UINT8_TO_BE_STREAM(p_data, AVDT_MEDIA_OCTET1); /* Version, Padding, Ext, CSRC */
+ UINT8_TO_BE_STREAM(p_data, m_pt); /* Marker & Packet Type */
+ UINT16_TO_BE_STREAM(p_data, seq_number); /* Sequence number */
+ UINT32_TO_BE_STREAM(p_data, timestamp); /* TimeStamp */
+ UINT32_TO_BE_STREAM(p_data, ssrc); /* SSRC */
+ return p_data;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_avdt_cp_set_scms
+**
+** Description Set SCMS Content Protection for a channel
+**
+** Returns AVDT_SYNC_SUCCESS/AVDT_SYNC_FAILURE
+**
+*******************************************************************************/
+UINT8 btusb_lite_avdt_cp_set_scms(struct btusb_cb *p_dev, UINT8 avdt_handle,
+ BOOLEAN enable, UINT8 scms_hdr)
+{
+ struct btusb_lite_avdt_scb *p_avdt_scb;
+
+ /* Find the AVDT SCB with this handle */
+ p_avdt_scb = btusb_lite_avdt_scb_by_hdl(p_dev, avdt_handle);
+ if (p_avdt_scb == NULL)
+ {
+ BTUSB_ERR("No AVDT SCB stream found\n");
+ return AVDT_SYNC_FAILURE;
+ }
+
+ BTUSB_INFO("btusb_lite_avdt_cp_set_scms handle=0x%x enable=%d header=0x%x\n",
+ avdt_handle, enable, scms_hdr);
+
+ p_avdt_scb->scms.enable = enable;
+ p_avdt_scb->scms.header = scms_hdr;
+
+ return AVDT_SYNC_SUCCESS;
+
+}
diff --git a/btusb_1_6_29_1/src/btusb_lite_hci.c b/btusb_1_6_29_1/src/btusb_lite_hci.c
new file mode 100755
index 0000000..83835d9
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb_lite_hci.c
@@ -0,0 +1,440 @@
+/*
+ *
+ * btusb_lite_hci.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include "btusb.h"
+
+/*
+ * Definitions
+ */
+#define BTUSB_LITE_HCI_NUM_CMD 0x01 /* HCI Num Command */
+
+/* HCI Definitions for the NumberOfCompletePacket Event */
+#define BTUSB_LITE_HCI_NOCP_HCI_LEN 7 /* HCI Length of the NumOfCpltPacket Event */
+#define BTUSB_A2DP_NOCP_LEN 5 /* Length of the NumOfCpltPacket Param */
+
+/*
+ * Local functions
+ */
+static UINT8 *btusb_lite_hci_write_acl_header(UINT8 *p_data, UINT16 con_hdl, UINT16 length);
+static UINT8 *btusb_lite_hci_write_evt_header(UINT8 *p_data, UINT8 event, UINT8 length);
+
+static int btusb_lite_hci_transport_pause_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static int btusb_lite_hci_transport_resume_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg);
+static void btusb_lite_hci_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len);
+static int btusb_lite_hci_nocp_event_hdlr(struct btusb_cb *p_dev, UINT8 *p_data, int length);
+
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_acl_send
+ **
+ ** Description Send an ACL packet to HCI
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+int btusb_lite_hci_acl_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 con_hdl)
+{
+ UINT8 *p_data;
+
+ /* Sanity */
+ if (p_msg->offset < BTUSB_LITE_HCI_ACL_HDR_SIZE)
+ {
+ BTUSB_ERR("offset too small=%d\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return -1;
+ }
+
+ /* Decrement offset to add headers */
+ p_msg->offset -= BTUSB_LITE_HCI_ACL_HDR_SIZE;
+
+ /* Get address of the HCI Header */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ /* Write L2CAP Header (length field is SBC Frames + RTP/A2DP/Media Header) */
+ p_data = btusb_lite_hci_write_acl_header(p_data, con_hdl, p_msg->len);
+
+ /* Increment length */
+ p_msg->len += BTUSB_LITE_HCI_ACL_HDR_SIZE;
+
+ /* Add this ACL data in the USB Tx queue and notify the btusb_tx_task to process */
+ GKI_enqueue(&p_dev->tx_queue, p_msg);
+
+ /* Wake up tasklet (with High priority) */
+ tasklet_schedule(&p_dev->tx_task);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_cmd_filter
+ **
+ ** Description Check if the Sent HCI Command need to be handled/caught (not
+ ** sent to BT controller).
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+int btusb_lite_hci_cmd_filter(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 *p;
+ UINT8 hci_type;
+ UINT16 opcode;
+ int rv = 1; /* HCI command not handled by default */
+
+ p = (UINT8 *)(p_msg + 1);
+
+ STREAM_TO_UINT8(hci_type, p); /* Extract HCI Type */
+
+ if (hci_type != HCIT_TYPE_COMMAND)
+ {
+ /* This is not an HCI Command */
+ return rv; /* Send it to BT Controller */
+ }
+
+ STREAM_TO_UINT16(opcode, p); /* Extract HCI Command OpCode */
+
+ switch(opcode)
+ {
+ case HCI_BRCM_PAUSE_TRANSPORT:
+ rv = btusb_lite_hci_transport_pause_hndl(p_dev, p_msg);
+ break;
+
+ case HCI_BRCM_TRANSPORT_RESUME:
+ /* Call the function in charge of filtering UIPC Over HCI VSC */
+ rv = btusb_lite_hci_transport_resume_hndl(p_dev, p_msg);
+ break;
+
+ /* Add here other HCI Command OpCodes to filter */
+ default:
+ break;
+ /* Do not filter other HCI Command OpCodes */
+ }
+ return rv;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_transport_pause_hndl
+ **
+ ** Description Handles the HCI Transport Pause VSC.
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+static int btusb_lite_hci_transport_pause_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 param[sizeof(UINT8)];
+ UINT8 *p_param = param;
+
+ BTUSB_INFO("HCI_TransportPause VSC caught\n");
+
+ UINT8_TO_STREAM(p_param, HCI_SUCCESS);
+
+ btusb_lite_hci_cmd_cplt_evt_send(p_dev, HCI_BRCM_PAUSE_TRANSPORT, param,
+ p_param - param);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_transport_resume_hndl
+ **
+ ** Description Handles the HCI Transport Pause VSC.
+ **
+ ** Returns status: <> 0 if the command must be send to BT controller
+ ** 0 if the command is handled
+ **
+ *******************************************************************************/
+static int btusb_lite_hci_transport_resume_hndl(struct btusb_cb *p_dev, BT_HDR *p_msg)
+{
+ UINT8 param[sizeof(UINT8)];
+ UINT8 *p_param = param;
+
+ BTUSB_INFO("HCI_TransportResume VSC caught\n");
+
+ UINT8_TO_STREAM(p_param, HCI_SUCCESS);
+
+ btusb_lite_hci_cmd_cplt_evt_send(p_dev, HCI_BRCM_TRANSPORT_RESUME, param,
+ p_param - param);
+
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_event_filter
+ **
+ ** Description Filter HCI Events received from BT Controller.
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+int btusb_lite_hci_event_filter(struct btusb_cb *p_dev, UINT8 *p_data, int length)
+{
+#if 0
+ BT_HDR *p_msg;
+ UINT8 *p;
+ UINT16 size;
+#endif
+
+ /* Check if HCI is over IPC */
+ if (btusb_lite_is_hci_over_ipc(p_dev) == 0)
+ {
+ /* If it is not, the event have to be sent through regular HCI */
+ return 1;
+ }
+
+ /* Check if the Event is a NumberOfCompletePacket Event */
+ if (btusb_lite_hci_nocp_event_hdlr(p_dev, p_data, length) == 0)
+ {
+ return 0; /* Do not Send this event to user space (we handled it) */
+ }
+
+ /* TODO: check if CSB VSE */
+
+ return 1;
+
+#if 0
+
+ /* Add size of both UIPC Length and Event header */
+ size = length + sizeof(UINT16) + sizeof(UINT16);
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return 0;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = 0;
+ p_msg->len = size;
+
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ UINT16_TO_STREAM(p, length + sizeof(UINT16)); /* UIPC Length */
+ UINT16_TO_STREAM(p, BT_EVT_TO_BTU_HCI_EVT); /* UIPC Event */
+ UINT8_TO_STREAM(p, hci_event); /* Write back the HCI Event (we already read it) */
+ ARRAY_TO_STREAM(p, p_data, length - 1); /* Copy Event data */
+
+ /* Send message to User Space */
+ btusb_lite_ipc_sent_to_user(p_dev, p_msg);
+
+ return 0; /* Event handled by the Stack Lite. No need to send it to HCI */
+#endif
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_nocp_event_hdlr
+ **
+ ** Description Check if the received HCI Event is A NumberOfdComplete Evt
+ ** sub opcode for a Started BAV stream.
+ **
+ ** Returns status: <> 0 if the event must be send to user space (BSA)
+ ** 0 if the event is handled
+ **
+ *******************************************************************************/
+static int btusb_lite_hci_nocp_event_hdlr(struct btusb_cb *p_dev, UINT8 *p_data, int length)
+{
+ UINT8 nb_handle;
+ UINT16 con_hdl;
+ UINT16 num_cplt_pck;
+ UINT8 byte;
+ UINT8 *p_save;
+ int send_to_user;
+ UINT16 num_cplt_pck_caugth;
+
+ /* We are waiting for an Event of, at least, 7 bytes */
+ if (length < BTUSB_LITE_HCI_NOCP_HCI_LEN)
+ {
+ return 1; /* This is not a NOCP. Send this event to user space */
+ }
+
+ /* Extract Event */
+ STREAM_TO_UINT8(byte, p_data);
+
+ /* Check if it's a NumberOfCompletePacket Event */
+ if (byte != HCI_NUM_COMPL_DATA_PKTS_EVT)
+ {
+ return 1; /* This is not a NOCP. Send this event to user space */
+ }
+
+ /* Extract Parameter Length */
+ STREAM_TO_UINT8(byte, p_data);
+
+ /* Extract Number Of Handle */
+ STREAM_TO_UINT8(nb_handle, p_data);
+
+ /* Sanity */
+ if (byte != (1 + (2 + 2) * nb_handle))
+ {
+ BTUSB_ERR("Unexpected Evt Size=%d vs.NumberOfHandle=%d\n", byte, nb_handle);
+ return 1; /* This is not a NOCP. Send this event to user space */
+ }
+
+ send_to_user = 0; /* For the moment, no Complete Packet sent to user */
+
+ /* For every Handle */
+ while(nb_handle--)
+ {
+ /* Extract the Connection Handle */
+ STREAM_TO_UINT16(con_hdl, p_data);
+
+ /* Save the current pointer position (to overwrite number of packet) */
+ p_save = p_data;
+
+ /* Extract the Number Of Complete Packet */
+ STREAM_TO_UINT16(num_cplt_pck, p_data);
+
+ /* Call the L2CAP NumberOfcompletePacket Handler */
+ num_cplt_pck_caugth = btusb_lite_l2c_nocp_hdlr(p_dev, con_hdl, num_cplt_pck);
+
+ /* If L2CAP "caught"at least one nocp packet */
+ if (num_cplt_pck_caugth)
+ {
+ /* Overwrite the Number Of Complete Packet */
+ UINT16_TO_STREAM(p_save, num_cplt_pck - num_cplt_pck_caugth);
+
+ /* If at least one Number Of Complete Packet remains */
+ if (num_cplt_pck - num_cplt_pck_caugth)
+ {
+ /* Send the event to user space */
+ send_to_user = 1;
+ }
+ }
+ else
+ {
+ /* Don't update the number but send the event to user space */
+ send_to_user = 1;
+ }
+ }
+
+ return send_to_user;
+}
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_cmd_cplt_evt_send
+ **
+ ** Description Send an HCI VSC Cmd Complete.
+ **
+ ** Returns Void
+ **
+ *******************************************************************************/
+static void btusb_lite_hci_cmd_cplt_evt_send(struct btusb_cb *p_dev,
+ UINT16 opcode, UINT8 *p_param, UINT8 param_len)
+{
+ BT_HDR *p_msg;
+ UINT16 size = param_len + 5;
+ UINT8 *p;
+
+ /* Get a buffer from the pool */
+ p_msg = (BT_HDR *)GKI_getbuf(sizeof(BT_HDR) + size);
+ if(unlikely(p_msg == NULL))
+ {
+ BTUSB_ERR("Unable to get GKI buffer\n");
+ return;
+ }
+
+ if (unlikely(dbgflags & BTUSB_GKI_CHK_MSG) &&
+ unlikely(GKI_buffer_status(p_msg) != BUF_STATUS_UNLINKED))
+ {
+ BTUSB_ERR("buffer != BUF_STATUS_UNLINKED 0x%p\n", p_msg);
+ return;
+ }
+
+ p_msg->offset = 0;
+ p_msg->event = HCIT_TYPE_EVENT;
+ p_msg->len = size;
+ p_msg->layer_specific = BTUSB_LS_GKI_BUFFER;
+
+ p = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ p = btusb_lite_hci_write_evt_header(p, HCI_COMMAND_COMPLETE_EVT, size - 2);
+
+ UINT8_TO_STREAM(p, BTUSB_LITE_HCI_NUM_CMD); /* HCI Num Command */
+ UINT16_TO_STREAM(p, opcode); /* HCI OpCode */
+
+ if (p_param)
+ {
+ ARRAY_TO_STREAM(p, p_param, param_len)
+ }
+
+ /* InQ for user-space to read */
+ GKI_enqueue(&p_dev->rx_queue, p_msg);
+
+ /* if the process is polling, indicate RX event */
+ wake_up_interruptible(&p_dev->rx_wait_q);
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_write_acl_header
+ **
+ ** Description Write HCI ACL Header (HCI_Type, Connection Handle, Length)
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_hci_write_acl_header(UINT8 *p_data, UINT16 con_hdl, UINT16 length)
+{
+ UINT8_TO_STREAM(p_data, HCIT_TYPE_ACL_DATA); /* HCI_Type */
+ UINT16_TO_STREAM(p_data, con_hdl); /* Connection Handle */
+ UINT16_TO_STREAM(p_data, length); /* Length */
+ return p_data;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_hci_write_evt_header
+ **
+ ** Description Write HCI Event Header (HCI_Type, Connection Handle, Length)
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_hci_write_evt_header(UINT8 *p_data, UINT8 event, UINT8 length)
+{
+ UINT8_TO_STREAM(p_data, event);
+ UINT8_TO_STREAM(p_data, length); /* Param Length */
+ return p_data;
+}
+
diff --git a/btusb_1_6_29_1/src/btusb_lite_l2c.c b/btusb_1_6_29_1/src/btusb_lite_l2c.c
new file mode 100755
index 0000000..5db7ecc
--- a/dev/null
+++ b/btusb_1_6_29_1/src/btusb_lite_l2c.c
@@ -0,0 +1,278 @@
+/*
+ *
+ * btusb_lite_l2c.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2013 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include "btusb.h"
+
+/*
+ * Definitions
+ */
+
+/*
+ * Local functions
+ */
+static UINT8 *btusb_lite_l2c_write_header(UINT8 *p_data, UINT16 length, UINT16 cid);
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_add
+**
+** Description Synchronize (Add) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_add(struct btusb_cb *p_dev, tL2C_STREAM_INFO *p_l2c_stream)
+{
+ int idx;
+ struct btusb_lite_l2c_cb *p_l2c = &p_dev->lite_cb.l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+
+ /* Check if this L2CAP Stream exists */
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < ARRAY_SIZE(p_l2c->ccb) ; idx++, p_l2c_ccb++)
+ {
+ if ((p_l2c_ccb->in_use) &&
+ (p_l2c_ccb->handle == p_l2c_stream->handle))
+ {
+ BTUSB_INFO("CCB=%d was already allocated. Update it.\n", idx);
+ break;
+ }
+ }
+ /* If Not found */
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ /* Look for a free CCB */
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < ARRAY_SIZE(p_l2c->ccb) ; idx++, p_l2c_ccb++)
+ {
+ if (p_l2c_ccb->in_use == FALSE)
+ {
+ BTUSB_INFO("CCB=%d allocated\n", idx);
+ memset(p_l2c_ccb, 0, sizeof(*p_l2c_ccb));
+ p_l2c_ccb->in_use = TRUE;
+ p_l2c_ccb->local_cid = p_l2c_stream->local_cid;
+ p_l2c_ccb->remote_cid = p_l2c_stream->remote_cid;
+ p_l2c_ccb->out_mtu = p_l2c_stream->out_mtu;
+ p_l2c_ccb->handle = p_l2c_stream->handle;
+ p_l2c_ccb->is_flushable = p_l2c_stream->is_flushable;
+ break;
+ }
+ }
+ }
+
+ /* If Not found ot not allocated */
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ BTUSB_ERR("No Free L2C CCB found (handle=0x%x)\n", p_l2c_stream->handle);
+ return -1;
+ }
+
+ /* Update Transmit Quota */
+ p_l2c_ccb->link_xmit_quota = p_l2c_stream->link_xmit_quota;
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_remove
+**
+** Description Synchronize (Remove) L2CAP Stream
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_remove(struct btusb_cb *p_dev, UINT16 local_cid)
+{
+ int idx;
+ struct btusb_lite_l2c_cb *p_l2c = &p_dev->lite_cb.l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+
+ /* Check if this L2CAP Stream exists */
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < ARRAY_SIZE(p_l2c->ccb) ; idx++, p_l2c_ccb++)
+ {
+ if ((p_l2c_ccb->in_use) &&
+ (p_l2c_ccb->local_cid == local_cid))
+ {
+ break;
+ }
+ }
+ /* If Not found */
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ BTUSB_ERR("L2C CCB found (lcid=0x%x)\n",local_cid);
+ return -1;
+ }
+
+ BTUSB_INFO("CCB=%d freed\n", idx);
+
+ /* Reset (Free) the L2CAP Stream */
+ memset(p_l2c_ccb, 0, sizeof(*p_l2c_ccb));
+
+ return 0;
+}
+
+/*******************************************************************************
+**
+** Function btusb_lite_l2c_send
+**
+** Description Send L2CAP packet
+**
+** Returns Status.
+**
+*******************************************************************************/
+int btusb_lite_l2c_send(struct btusb_cb *p_dev, BT_HDR *p_msg, UINT16 local_cid)
+{
+ int idx;
+ struct btusb_lite_l2c_cb *p_l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+ UINT8 *p_data;
+
+ /* Look for the first AV stream Started */
+ p_l2c = &p_dev->lite_cb.l2c;
+ for (idx = 0, p_l2c_ccb = p_l2c->ccb ; idx < BTM_SYNC_INFO_NUM_STR ; idx++, p_l2c_ccb++)
+ {
+ if (p_l2c_ccb->local_cid == local_cid)
+ {
+ break;
+ }
+ }
+ if (idx == BTM_SYNC_INFO_NUM_STR)
+ {
+ BTUSB_ERR("No L2C CCB found (lcid=0x%x)\n", local_cid);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return -1;
+ }
+
+ /* Check if the Tx Quota has been reached for this channel */
+ if (p_l2c_ccb->tx_pending >= p_l2c_ccb->link_xmit_quota)
+ {
+ BTUSB_ERR("Tx Quota reached for L2CAP channel (lcid=0x%x). Drop buffer\n", local_cid);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return -1;
+ }
+
+ /* Sanity */
+ if (p_msg->offset < BTUSB_LITE_L2CAP_HDR_SIZE)
+ {
+ BTUSB_ERR("offset too small=%d\n", p_msg->offset);
+ GKI_freebuf(p_msg); /* Free this ACL buffer */
+ return-1;
+ }
+
+ /* Decrement offset to add headers */
+ p_msg->offset -= BTUSB_LITE_L2CAP_HDR_SIZE;
+
+ /* Get address of the HCI Header */
+ p_data = (UINT8 *)(p_msg + 1) + p_msg->offset;
+
+ /* Write L2CAP Header (length field is SBC Frames + RTP/A2DP/Media Header) */
+ p_data = btusb_lite_l2c_write_header(p_data, p_msg->len, p_l2c_ccb->remote_cid);
+
+ /* Increment length */
+ p_msg->len += BTUSB_LITE_L2CAP_HDR_SIZE;
+
+
+ GKI_disable(); /* tx_pending field can be updated by another context */
+ p_l2c_ccb->tx_pending++; /* One more A2DP L2CAP packet pending */
+ BTUSB_DBG("L2C Tx Pending=%d\n", p_l2c_ccb->tx_pending);
+ GKI_enable();
+
+ if (btusb_lite_hci_acl_send(p_dev, p_msg, p_l2c_ccb->handle) < 0)
+ {
+ GKI_disable(); /* tx_pending field can be updated by another context */
+ p_l2c_ccb->tx_pending--; /* Remove A2DP L2CAP packet pending */
+ GKI_enable();
+ return -1;
+ }
+ return 0;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_l2c_write_header
+ **
+ ** Description Write L2CAP ACL Header (Length, Channel Id)
+ **
+ ** Returns New buffer location
+ **
+ *******************************************************************************/
+static UINT8 *btusb_lite_l2c_write_header(UINT8 *p_data, UINT16 length, UINT16 cid)
+{
+ UINT16_TO_STREAM(p_data, length); /* Length */
+ UINT16_TO_STREAM(p_data, cid); /* Channel Id */
+ return p_data;
+}
+
+/*******************************************************************************
+ **
+ ** Function btusb_lite_l2c_nocp_hdlr
+ **
+ ** Description L2CAP NumberOfcompletePacket Handler function
+ **
+ ** Returns Number Of Complete Packet caught
+ **
+ *******************************************************************************/
+UINT16 btusb_lite_l2c_nocp_hdlr(struct btusb_cb *p_dev, UINT16 con_hdl, UINT16 num_cplt_pck)
+{
+ struct btusb_lite_l2c_cb *p_l2c;
+ struct btusb_lite_l2c_ccb *p_l2c_ccb;
+ int i;
+ UINT16 num_cplt_pck_caugth;
+
+ /* Look for the L2CAP channel matching the Connection Handle */
+ p_l2c = &p_dev->lite_cb.l2c;
+ for (i = 0, p_l2c_ccb = p_l2c->ccb ; i < BTM_SYNC_INFO_NUM_STR ; i++, p_l2c_ccb++)
+ {
+ if (p_l2c_ccb->handle == con_hdl)
+ {
+ break;
+ }
+ }
+ /* If L2CAP channel not found/known */
+ if (i == BTM_SYNC_INFO_NUM_STR)
+ {
+ return 0;
+ }
+
+ /* If no Tx Pending */
+ if (p_l2c_ccb->tx_pending == 0)
+ {
+ return 0;
+ }
+
+ GKI_disable(); /* tx_pending field can be updated by another context */
+
+ /* Take the min between the number of pending packet and the number of acked packet */
+ num_cplt_pck_caugth = min(p_l2c_ccb->tx_pending, num_cplt_pck);
+
+ /* Update the number of pending packet */
+ p_l2c_ccb->tx_pending-= num_cplt_pck_caugth;
+
+ BTUSB_DBG("L2C NOCP Tx Pending=%d\n", p_l2c_ccb->tx_pending);
+
+ GKI_enable();
+
+ return num_cplt_pck_caugth;
+}
diff --git a/btusb_1_6_29_1/src/gki/.svn/all-wcprops b/btusb_1_6_29_1/src/gki/.svn/all-wcprops
new file mode 100755
index 0000000..0fc5fe2
--- a/dev/null
+++ b/btusb_1_6_29_1/src/gki/.svn/all-wcprops
@@ -0,0 +1,17 @@
+K 25
+svn:wc:ra_dav:version-url
+V 76
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/gki
+END
+gki_buffer.c
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/gki/gki_buffer.c
+END
+gki_klinux.c
+K 25
+svn:wc:ra_dav:version-url
+V 89
+/svn/SiP/!svn/ver/725/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/gki/gki_klinux.c
+END
diff --git a/btusb_1_6_29_1/src/gki/.svn/entries b/btusb_1_6_29_1/src/gki/.svn/entries
new file mode 100755
index 0000000..6ded4eb
--- a/dev/null
+++ b/btusb_1_6_29_1/src/gki/.svn/entries
@@ -0,0 +1,96 @@
+10
+
+dir
+941
+http://10.10.29.8/svn/SiP/Broadcom/Android/Trunk/BT/BTUSB/btusb_1_6_29_1/src/gki
+http://10.10.29.8/svn/SiP
+
+
+
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+e48500f2-7125-4e9d-852c-c0ee60673d08
+
+gki_buffer.c
+file
+
+
+
+
+2014-08-14T08:53:29.712694Z
+a2f67e488104296ce096c5aa1706cdb6
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+35299
+
+gki_klinux.c
+file
+
+
+
+
+2014-08-14T08:53:29.708694Z
+74401143a2ce1b771b31aaeb0b14e10e
+2014-08-14T09:21:52.961444Z
+725
+luke
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+6695
+
diff --git a/btusb_1_6_29_1/src/gki/.svn/text-base/gki_buffer.c.svn-base b/btusb_1_6_29_1/src/gki/.svn/text-base/gki_buffer.c.svn-base
new file mode 100755
index 0000000..e85670d
--- a/dev/null
+++ b/btusb_1_6_29_1/src/gki/.svn/text-base/gki_buffer.c.svn-base
@@ -0,0 +1,1280 @@
+/*
+ *
+ * gki_buffer.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#include "gki_int.h"
+#include "btusb.h"
+
+#if (GKI_NUM_TOTAL_BUF_POOLS > 16)
+#error Number of pools out of range (16 Max)!
+#endif
+
+static void gki_add_to_pool_list(UINT8 pool_id);
+static void gki_remove_from_pool_list(UINT8 pool_id);
+
+static BOOL _b_in_gki_getbuf = FALSE;
+
+/*******************************************************************************
+**
+** Function gki_init_free_queue
+**
+** Description Internal function called at startup to initialize a free
+** queue. It is called once for each free queue.
+**
+** Returns void
+**
+*******************************************************************************/
+static BOOL gki_init_free_queue(UINT8 id, UINT16 size, UINT16 total, void *p_mem)
+{
+ UINT16 i;
+ UINT16 act_size;
+ BUFFER_HDR_T *hdr;
+ BUFFER_HDR_T *hdr1 = NULL;
+ UINT32 *magic;
+ int seg_inx = gki_cb.pool_additions[id];
+ FREE_QUEUE_T *p_freeq = &gki_cb.freeq[id];
+
+ if (seg_inx >= MAX_BUFFPOOL_SEGS)
+ {
+ GKI_exception(GKI_ERROR_SEGS_EXCEEDED, "Max segs exceeded");
+ return(FALSE);
+ }
+
+ act_size = (UINT16)(size + BUFFER_PADDING_SIZE);
+
+ if (!p_mem)
+ p_mem = gki_reserve_os_memory(act_size * total);
+
+ if (!p_mem)
+ {
+ GKI_exception(GKI_ERROR_NO_MEMORY_FOR_SEG, "No memory for segment");
+ return(FALSE);
+ }
+
+ /* Remember pool start and end addresses */
+ p_freeq->seg_start[seg_inx] = (UINT8 *)p_mem;
+ p_freeq->seg_end[seg_inx] = (UINT8 *)p_mem + (act_size * total);
+
+ if (seg_inx == 0)
+ {
+ gki_cb.freeq[id].total = total;
+ gki_cb.freeq[id].cur_cnt = 0;
+ gki_cb.freeq[id].max_cnt = 0;
+ }
+ else
+ gki_cb.freeq[id].total += total;
+
+ /* Initialize index table */
+ hdr = (BUFFER_HDR_T *)p_mem;
+ p_freeq->p_first = hdr;
+
+#ifdef TRACE_GKI_BUFFERS
+ gki_cb.freeq[id].p_first_all = hdr;
+#endif
+
+ for (i = 0; i < total; i++)
+ {
+ hdr->task_id = GKI_INVALID_TASK;
+ hdr->q_id = id;
+ hdr->status = BUF_STATUS_FREE;
+ magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + size);
+ *magic = MAGIC_NO;
+ hdr1 = hdr;
+ hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
+ hdr1->p_next = hdr;
+#ifdef TRACE_GKI_BUFFERS
+ hdr1->p_next_all = hdr;
+ hdr1->pFile = NULL;
+ hdr1->linenum = 0;
+ hdr1->times_alloc = 0;
+#endif
+ }
+
+ hdr1->p_next = NULL;
+ p_freeq->p_last = hdr1;
+
+ gki_cb.pool_additions[id]++;
+
+ return(TRUE);
+}
+
+
+/*******************************************************************************
+**
+** Function gki_buffer_init
+**
+** Description Called once internally by GKI at startup to initialize all
+** buffers and free buffer pools.
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_buffer_init(void)
+{
+ UINT8 tt;
+ UINT16 access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
+
+#ifdef TRACE_GKI_BUFFERS
+ char aString[200];
+ sprintf(aString,"%s: %d: WARNING! Running with GKI buffer tracing enabled!!",__FILE__,__LINE__);
+ GKI_exception(GKI_ERROR_BUFFER_TRACE_ON,aString);
+#endif
+
+ for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++)
+ {
+ memset(&gki_cb.freeq[tt], 0, sizeof(FREE_QUEUE_T));
+
+ gki_cb.pool_buf_size[tt] = 0;
+ gki_cb.pool_max_count[tt] = 0;
+ gki_cb.pool_additions[tt] = 0;
+ }
+
+ /* Use default from target.h */
+ gki_cb.pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
+
+#if (GKI_USE_DYNAMIC_BUFFERS == TRUE)
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ GKI_create_pool(GKI_BUF0_SIZE, GKI_BUF0_MAX, (UINT8) (access_mask & 1), NULL);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ GKI_create_pool(GKI_BUF1_SIZE, GKI_BUF1_MAX, (UINT8) (access_mask & 1), NULL);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ GKI_create_pool(GKI_BUF2_SIZE, GKI_BUF2_MAX, (UINT8) (access_mask & 1), NULL);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ GKI_create_pool(GKI_BUF3_SIZE, GKI_BUF3_MAX, (UINT8) (access_mask & 1), NULL);
+#endif
+
+#else
+
+/* Static buffers */
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ GKI_create_pool(GKI_BUF0_SIZE, GKI_BUF0_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool0);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ GKI_create_pool(GKI_BUF1_SIZE, GKI_BUF1_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool1);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ GKI_create_pool(GKI_BUF2_SIZE, GKI_BUF2_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool2);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ GKI_create_pool(GKI_BUF3_SIZE, GKI_BUF3_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool3);
+#endif
+
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_set_pool_permission
+**
+** Description This function is called to set or change the permissions for
+** the specified pool ID.
+**
+** Parameters pool_id - (input) pool ID to be set or changed
+** permission - (input) GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL
+**
+** Returns GKI_SUCCESS if successful
+** GKI_INVALID_POOL if unsuccessful
+**
+*******************************************************************************/
+UINT8 GKI_set_pool_permission(UINT8 pool_id, UINT8 permission)
+{
+ if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ if (permission == GKI_RESTRICTED_POOL)
+ gki_cb.pool_access_mask |= (1 << pool_id);
+
+ else /* mark the pool as public */
+ gki_cb.pool_access_mask &= ~(1 << pool_id);
+
+ return(GKI_SUCCESS);
+ }
+ else
+ return(GKI_INVALID_POOL);
+}
+
+
+/*******************************************************************************
+**
+** Function gki_add_to_pool_list
+**
+** Description Adds pool to the pool list which is arranged in the
+** order of size
+**
+** Returns void
+**
+*******************************************************************************/
+static void gki_add_to_pool_list(UINT8 pool_id)
+{
+ INT32 i, j;
+
+ /* Find the position where the specified pool should be inserted into the list */
+ for (i = 0; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ if (gki_cb.pool_buf_size[pool_id] <= gki_cb.pool_buf_size[gki_cb.pool_list[i]])
+ break;
+ }
+
+ /* Insert the new buffer pool ID into the list of pools */
+ for (j = gki_cb.curr_total_no_of_pools; j > i; j--)
+ {
+ gki_cb.pool_list[j] = gki_cb.pool_list[j-1];
+ }
+
+ gki_cb.pool_list[i] = pool_id;
+}
+
+
+/*******************************************************************************
+**
+** Function gki_remove_from_pool_list
+**
+** Description Removes pool from the pool list. Called when a pool is deleted
+**
+** Returns void
+**
+*******************************************************************************/
+static void gki_remove_from_pool_list(UINT8 pool_id)
+{
+ UINT8 i;
+
+ for (i = 0; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ if (pool_id == gki_cb.pool_list[i])
+ break;
+ }
+
+ while (i < (GKI_NUM_TOTAL_BUF_POOLS - 1))
+ {
+ gki_cb.pool_list[i] = gki_cb.pool_list[i+1];
+ i++;
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_init_q
+**
+** Description Called by an application to initialize a buffer queue.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_init_q(BUFFER_Q *p_q)
+{
+ p_q->p_first = p_q->p_last = NULL;
+ p_q->count = 0;
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getbuf
+**
+** Description Called by an application to get a free buffer which
+** is of size greater or equal to the requested size.
+**
+** Note: This routine only takes buffers from public pools.
+** It will not use any buffers from pools
+** marked GKI_RESTRICTED_POOL.
+**
+** Parameters size - (input) number of bytes needed.
+**
+** Returns A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+#ifdef TRACE_GKI_BUFFERS
+void *GKI_getbuf_trace(UINT16 size, char *pFile, int linenum)
+#else
+void *GKI_getbuf(UINT16 size)
+#endif
+{
+ UINT8 i, pool_id;
+ void *pp;
+
+ if (unlikely(size == 0))
+ {
+ GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
+ return(NULL);
+ }
+
+ /* Find the first buffer pool that is public that can hold the desired size */
+ for (i = 0; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ if (gki_cb.pool_buf_size[gki_cb.pool_list[i]] >= size)
+ break;
+ }
+
+ if (i == gki_cb.curr_total_no_of_pools)
+ {
+ char buff[40];
+ sprintf(buff, "getbuf: Size: %u is too big", size);
+ GKI_exception(GKI_ERROR_BUF_SIZE_TOOBIG, buff);
+ return(NULL);
+ }
+
+ _b_in_gki_getbuf = TRUE;
+
+ /* search the public buffer pools that are big enough to hold the size
+ * until a free buffer is found */
+ for ( ; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ pool_id = gki_cb.pool_list[i];
+
+ /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
+ if (((UINT16)1 << pool_id) & gki_cb.pool_access_mask)
+ continue;
+
+ if ((pp = GKI_getpoolbuf(pool_id)) != NULL)
+ {
+ _b_in_gki_getbuf = FALSE;
+ return(pp);
+ }
+ }
+
+ _b_in_gki_getbuf = FALSE;
+
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getpoolbuf
+**
+** Description Called by an application to get a free buffer from
+** a specific buffer pool.
+**
+** Note: If there are no more buffers available from the pool,
+** the public buffers are searched for an available buffer.
+**
+** Parameters pool_id - (input) pool ID to get a buffer out of.
+**
+** Returns A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+#ifdef TRACE_GKI_BUFFERS
+void *GKI_getpoolbuf_trace(UINT8 pool_id, char *pFile, int linenum)
+#else
+void *GKI_getpoolbuf(UINT8 pool_id)
+#endif
+{
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return(NULL);
+
+ /* Make sure the buffers aren't disturbed til finished with allocation */
+ GKI_disable();
+
+ Q = &gki_cb.freeq[pool_id];
+
+ /* If we have no buffers left, see if we can allocate another segment */
+ if ((Q->cur_cnt >= Q->total) && (gki_cb.pool_additions[pool_id] < MAX_BUFFPOOL_SEGS))
+ {
+ UINT16 count = (gki_cb.pool_max_count[pool_id] + MAX_BUFFPOOL_SEGS - 1) / MAX_BUFFPOOL_SEGS;
+
+ gki_init_free_queue(pool_id, gki_cb.pool_buf_size[pool_id], count, NULL);
+ }
+
+ if (Q->cur_cnt < Q->total)
+ {
+ p_hdr = Q->p_first;
+ Q->p_first = p_hdr->p_next;
+
+ if (!Q->p_first)
+ Q->p_last = NULL;
+
+ if (++Q->cur_cnt > Q->max_cnt)
+ Q->max_cnt = Q->cur_cnt;
+
+ GKI_enable();
+
+ p_hdr->status = BUF_STATUS_UNLINKED;
+ p_hdr->p_next = NULL;
+ p_hdr->Type = 0;
+
+#ifdef TRACE_GKI_BUFFERS
+ p_hdr->pFile = pFile;
+ p_hdr->linenum = linenum;
+ p_hdr->times_alloc++;
+ /* The following is here to allow the test engineer to recognize and */
+ /* set a breakpoint when a particular buffer is allocated for the nth time. */
+ /* Simply change the address and allocation number in the following 'if' */
+ /* statement to reflect the buffer and occurance desired. */
+ if ((p_hdr == (BUFFER_HDR_T *)0x12345678) && (p_hdr->times_alloc == 123))
+ p_hdr->times_alloc = 123;
+#endif
+
+ return((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
+ }
+
+ /* If here, no buffers in the specified pool */
+ GKI_enable();
+
+ /* Try for free buffers in public pools. NOTE - no recursion allowed */
+ if (!_b_in_gki_getbuf)
+ return(GKI_getbuf(gki_cb.pool_buf_size[pool_id]));
+ else
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_freebuf
+**
+** Description Called by an application to return a buffer to the free pool.
+**
+** Parameters p_buf - (input) address of the beginning of a buffer.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_freebuf(void *p_buf)
+{
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+ void *pNextBuf;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (!p_buf || gki_chk_buf_damage(p_buf))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
+ return;
+ }
+
+ if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
+ return;
+ }
+
+#ifdef TRACE_GKI_BUFFERS
+ if ((p_hdr->pFile == NULL) || (p_hdr->linenum == 0))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - no file or line number");
+ }
+#endif
+
+ GKI_disable();
+
+ /*
+ ** Releasing all buffers in the linked list
+ */
+ while (p_buf)
+ {
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+
+ pNextBuf = NULL;
+ Q = &gki_cb.freeq[p_hdr->q_id];
+ if (Q->p_last)
+ Q->p_last->p_next = p_hdr;
+ else
+ Q->p_first = p_hdr;
+
+ Q->p_last = p_hdr;
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_FREE;
+ p_hdr->task_id = GKI_INVALID_TASK;
+#ifdef TRACE_GKI_BUFFERS
+ p_hdr->pFile = NULL;
+ p_hdr->linenum = 0;
+#endif
+ if (Q->cur_cnt > 0)
+ Q->cur_cnt--;
+
+ p_buf = pNextBuf;
+ }
+
+ GKI_enable();
+
+ return;
+}
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+/*******************************************************************************
+**
+** Function GKI_get_buf_size
+**
+** Description Called by an application to get the size of a buffer.
+**
+** Parameters p_buf - (input) address of the beginning of a buffer.
+**
+** Returns the size of the buffer
+**
+*******************************************************************************/
+UINT16 GKI_get_buf_size(void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *)((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if ((uintptr_t)p_hdr & 1)
+ {
+ return(0);
+ }
+
+ if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ return(gki_cb.pool_buf_size[p_hdr->q_id]);
+ }
+ else if (p_hdr->q_id == GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ return offsetof(tBTUSB_TRANSACTION, magic) - offsetof(tBTUSB_TRANSACTION, bt_hdr);
+ }
+
+
+ return(0);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function GKI_get_pool_bufsize
+**
+** Description Called by an application to get the size of buffers in a pool
+**
+** Parameters Pool ID.
+**
+** Returns the size of buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_get_pool_bufsize(UINT8 pool_id)
+{
+ if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
+ return(gki_cb.pool_buf_size[pool_id]);
+
+ return(0);
+}
+
+/*******************************************************************************
+**
+** Function GKI_poolfreecount
+**
+** Description Called by an application to get the number of free buffers
+** in the specified buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get the free count of.
+**
+** Returns the number of free buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_poolfreecount(UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return(0);
+
+ Q = &gki_cb.freeq[pool_id];
+
+ return((UINT16)(Q->total - Q->cur_cnt));
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_poolutilization
+**
+** Description Called by an application to get the buffer utilization
+** in the specified buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get the free count of.
+**
+** Returns % of buffers used from 0 to 100
+**
+*******************************************************************************/
+UINT16 GKI_poolutilization(UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return(100);
+
+ Q = &gki_cb.freeq[pool_id];
+
+ if (Q->total == 0)
+ return(100);
+
+ return((Q->cur_cnt * 100) / Q->total);
+}
+
+
+
+/*******************************************************************************
+**
+** Function gki_chk_buf_damage
+**
+** Description Called internally by OSS to check for buffer corruption.
+**
+** Returns TRUE if there is a problem, else FALSE
+**
+*******************************************************************************/
+BOOLEAN gki_chk_buf_damage(void *p_buf)
+{
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+
+ UINT32 *magic;
+ magic = (UINT32 *)((UINT8 *) p_buf + GKI_get_buf_size(p_buf));
+
+ if ((uintptr_t)magic & 1)
+ return(TRUE);
+
+ if (*magic == MAGIC_NO)
+ return(FALSE);
+
+ return(TRUE);
+
+#else
+
+ return(FALSE);
+
+#endif
+}
+
+/*******************************************************************************
+**
+** Function gki_chk_buf_owner
+**
+** Description Called internally by OSS to check if the current task
+** is the owner of the buffer.
+**
+** Returns TRUE if not owner, else FALSE
+**
+*******************************************************************************/
+BOOLEAN gki_chk_buf_owner(void *p_buf)
+{
+ return(FALSE);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_change_buf_owner
+**
+** Description Called to change the task ownership of a buffer.
+**
+** Parameters: p_buf - (input) pointer to the buffer
+** task_id - (input) task id to change ownership to
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_change_buf_owner(void *p_buf, UINT8 task_id)
+{
+ BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ p_hdr->task_id = task_id;
+
+ return;
+}
+
+
+
+/*******************************************************************************
+**
+** Function GKI_buffer_status
+**
+** Description check status of the buffer to see if it is linked
+**
+** Parameters: p_buf - (input) address of the buffer to enqueue
+**
+** Returns state
+* BUF_STATUS_FREE 0
+* BUF_STATUS_UNLINKED 1
+* BUF_STATUS_QUEUED 2
+**
+*******************************************************************************/
+UINT8 GKI_buffer_status(void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ return(p_hdr->status);
+}
+
+/*******************************************************************************
+**
+** Function GKI_enqueue
+**
+** Description Enqueue a buffer at the tail of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enqueue(BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(p_buf))
+ {
+ //printk("Enqueue - Buffer corrupted\n");
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ printk("Enqueue - buf already linked\n");
+ GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Enqueue - buf already linked : p_hdr->status: %d, buffer: 0x%p",p_hdr->status, p_buf);
+ return;
+ }
+
+ GKI_disable();
+
+ /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
+ /* check p_last != NULL before dereferencing it and if p_last == NULL then p_first == NULL */
+ if (p_q->p_last)
+ {
+ BUFFER_HDR_T *p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_last - BUFFER_HDR_SIZE);
+ p_last_hdr->p_next = p_hdr;
+
+ /* sanity check, this should not happen */
+ if (p_q->p_first == NULL)
+ {
+ printk("ERROR: Enqueue - first == NULL , last != NULL (0x%p)\n", p_q->p_last);
+ }
+ }
+ else
+ {
+ /* sanity check, this should not happen */
+ if (p_q->p_first != NULL)
+ {
+ printk("ERROR: Enqueue - first != NULL (0x%p), last == NULL\n", p_q->p_first);
+ }
+
+ p_q->p_first = p_buf;
+ }
+
+ p_q->p_last = p_buf;
+ p_q->count++;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_QUEUED;
+
+ GKI_enable();
+ // printk("Enqueue: out from GKI_enqueue\n");
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_enqueue_head
+**
+** Description Enqueue a buffer at the head of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enqueue_head(BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(p_buf))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Enqeueue head - buf already linked");
+ return;
+ }
+
+ GKI_disable();
+
+ if (p_q->p_first)
+ {
+ p_hdr->p_next = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+ p_q->p_first = p_buf;
+ }
+ else
+ {
+ p_q->p_first = p_buf;
+ p_q->p_last = p_buf;
+ p_hdr->p_next = NULL;
+ }
+ p_q->count++;
+
+ p_hdr->status = BUF_STATUS_QUEUED;
+
+ GKI_enable();
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_dequeue
+**
+** Description Dequeues a buffer from the head of a queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_dequeue(BUFFER_Q *p_q)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ GKI_disable();
+
+ if (!p_q || !p_q->count)
+ {
+ GKI_enable();
+ return(NULL);
+ }
+
+ p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+
+ /* Keep buffers such that GKI header is invisible */
+ if (p_hdr->p_next)
+ p_q->p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+ else
+ {
+ p_q->p_first = NULL;
+ p_q->p_last = NULL;
+ }
+
+ p_q->count--;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_UNLINKED;
+
+ GKI_enable();
+
+ return((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_remove_from_queue
+**
+** Description Dequeue a buffer from the middle of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_remove_from_queue(BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_prev;
+ BUFFER_HDR_T *p_buf_hdr;
+
+ GKI_disable();
+
+ if (p_buf == p_q->p_first)
+ {
+ GKI_enable();
+ return(GKI_dequeue(p_q));
+ }
+
+ p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+ p_prev = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+
+ for ( ; p_prev; p_prev = p_prev->p_next)
+ {
+ /* If the previous points to this one, move the pointers around */
+ if (p_prev->p_next == p_buf_hdr)
+ {
+ p_prev->p_next = p_buf_hdr->p_next;
+
+ /* If we are removing the last guy in the queue, update p_last */
+ if (p_buf == p_q->p_last)
+ p_q->p_last = p_prev + 1;
+
+ /* One less in the queue */
+ p_q->count--;
+
+ /* The buffer is now unlinked */
+ p_buf_hdr->p_next = NULL;
+ p_buf_hdr->status = BUF_STATUS_UNLINKED;
+
+ GKI_enable();
+ return(p_buf);
+ }
+ }
+
+ GKI_enable();
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getfirst
+**
+** Description Return a pointer to the first buffer in a queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns NULL if queue is empty, else buffer address
+**
+*******************************************************************************/
+void *GKI_getfirst(BUFFER_Q *p_q)
+{
+ return(p_q->p_first);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getnext
+**
+** Description Return a pointer to the next buffer in a queue
+**
+** Parameters: p_buf - (input) pointer to the buffer to find the next one from.
+**
+** Returns NULL if no more buffers in the queue, else next buffer address
+**
+*******************************************************************************/
+void *GKI_getnext(void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->p_next)
+ return((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+ else
+ return(NULL);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GKI_queue_is_empty
+**
+** Description Check the status of a queue.
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns TRUE if queue is empty, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
+{
+ return((BOOLEAN)(p_q->count == 0));
+}
+
+/*******************************************************************************
+**
+** Function GKI_find_buf_start
+**
+** Description This function is called with an address inside a buffer,
+** and returns the start address of the buffer.
+**
+** The buffer should be one allocated from one of GKI's pools.
+**
+** Parameters: p_user_area - (input) address of anywhere in a GKI buffer.
+**
+** Returns void * - Address of the beginning of the specified buffer if successful,
+** otherwise NULL if unsuccessful
+**
+*******************************************************************************/
+void *GKI_find_buf_start(void *p_user_area)
+{
+ int pool_id, seg_inx;
+ UINT16 size;
+ UINT32 yy;
+ UINT8 *p_ua = (UINT8 *)p_user_area;
+ FREE_QUEUE_T *p_fq = gki_cb.freeq;
+
+ for (pool_id = 0; pool_id < gki_cb.curr_total_no_of_pools; pool_id++, p_fq++)
+ {
+ for (seg_inx = 0; (seg_inx < MAX_BUFFPOOL_SEGS) && (p_fq->seg_start[seg_inx] != NULL); seg_inx++)
+ {
+ if ((p_ua > p_fq->seg_start[seg_inx]) && (p_ua < p_fq->seg_end[seg_inx]))
+ {
+ yy = (UINT32)(p_ua - p_fq->seg_start[seg_inx]);
+
+ size = gki_cb.pool_buf_size[pool_id] + BUFFER_PADDING_SIZE;
+
+ yy = (yy / size) * size;
+
+ return((void *) (p_fq->seg_start[seg_inx] + yy + sizeof(BUFFER_HDR_T)) );
+ }
+ }
+ }
+
+ /* If here, invalid address - not in one of our buffers */
+ GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr");
+
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_create_pool
+**
+** Description Called by applications to create a buffer pool.
+**
+** Parameters: size - (input) length (in bytes) of each buffer in the pool
+** count - (input) number of buffers to allocate for the pool
+** permission - (input) restricted or public access?
+** (GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL)
+** p_mem_pool - (input) pointer to an OS memory pool, NULL if not provided
+**
+** Returns the buffer pool ID, which should be used in calls to
+** GKI_getpoolbuf(). If a pool could not be created, this
+** function returns 0xff.
+**
+*******************************************************************************/
+UINT8 GKI_create_pool(UINT16 size, UINT16 count, UINT8 permission, void *p_mem_pool)
+{
+ int xx;
+
+ /* First make sure the size of each pool has a valid size with room for the header info */
+ if (size > MAX_USER_BUF_SIZE)
+ return(GKI_INVALID_POOL);
+
+ /* First, look for an unused pool */
+ for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++)
+ {
+ if (!gki_cb.pool_buf_size[xx])
+ break;
+ }
+
+ if (xx == GKI_NUM_TOTAL_BUF_POOLS)
+ return(GKI_INVALID_POOL);
+
+ GKI_disable();
+
+ /* Ensure an even number of longwords */
+ size = ((size + 3) / 4) * 4;
+
+ gki_cb.pool_buf_size[xx] = size;
+ gki_cb.pool_max_count[xx] = count;
+ gki_cb.pool_additions[xx] = 0;
+
+ /* If memory was not passed in, create the pool in segments */
+ if (!p_mem_pool)
+ count = (count + MAX_BUFFPOOL_SEGS - 1) / MAX_BUFFPOOL_SEGS;
+
+ /* Initialize the new pool */
+ if (gki_init_free_queue(xx, size, count, p_mem_pool))
+ {
+ gki_add_to_pool_list(xx);
+
+ (void) GKI_set_pool_permission(xx, permission);
+ gki_cb.curr_total_no_of_pools++;
+ }
+ else
+ {
+ /* Failed to create the pool ? */
+ gki_cb.pool_buf_size[xx] = 0;
+ GKI_enable();
+ return(GKI_INVALID_POOL);
+ }
+
+ /* If memory was passed in, no pool additions allowed */
+ if (p_mem_pool)
+ gki_cb.pool_additions[xx] = MAX_BUFFPOOL_SEGS;
+
+ GKI_enable();
+ return(xx);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_delete_pool
+**
+** Description Called by applications to delete a buffer pool. The function
+** calls the operating specific function to free the actual memory.
+** An exception is generated if an error is detected.
+**
+** Parameters: pool_id - (input) Id of the poll being deleted.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_delete_pool(UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+ int xx;
+
+ if ( (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!gki_cb.pool_buf_size[pool_id]) )
+ return;
+
+ GKI_disable();
+
+ Q = &gki_cb.freeq[pool_id];
+
+ Q->total = 0;
+ Q->cur_cnt = 0;
+ Q->max_cnt = 0;
+ Q->p_first = NULL;
+ Q->p_last = NULL;
+
+ for (xx = 0; xx < MAX_BUFFPOOL_SEGS; xx++)
+ {
+ if (Q->seg_start[xx])
+ gki_release_os_memory(Q->seg_start[xx]);
+
+ Q->seg_start[xx] = NULL;
+ Q->seg_end[xx] = NULL;
+ }
+
+ gki_cb.pool_buf_size[pool_id] = 0;
+
+ gki_remove_from_pool_list(pool_id);
+ gki_cb.curr_total_no_of_pools--;
+
+ GKI_enable();
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_chk_buf_pool_damage
+**
+** Description Called internally by OSS to check for buffer queue corruption.
+**
+** Returns TRUE if there is a problem, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GKI_chk_buf_pool_damage(UINT8 pool_id)
+{
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ int i;
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+ UINT8 *p_buf;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "pool_id out of range");
+ return(TRUE);
+ }
+
+ /* Make sure the buffers aren't disturbed til finished with checking */
+ GKI_disable();
+
+ Q = &gki_cb.freeq[pool_id];
+ if (!Q->p_first)
+ {
+ if (Q->cur_cnt != Q->total)
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "p_first is NULL in non-empty pool");
+ return(TRUE);
+ }
+ return(FALSE);
+ }
+ p_hdr = Q->p_first;
+ i = 1;
+ while (p_hdr->p_next)
+ {
+ p_hdr = p_hdr->p_next;
+ p_buf = ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
+ if (gki_chk_buf_damage(p_buf))
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "CHk Pool - Buf Corrupted");
+ return(TRUE);
+ }
+ i++;
+ }
+ if (p_hdr != Q->p_last)
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "last buffer in chain != p_last");
+ return(TRUE);
+ }
+ if (i != (Q->total - Q->cur_cnt))
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "cur_cnt != number of buffers in pool");
+ return(TRUE);
+ }
+
+ GKI_enable();
+ return(FALSE);
+
+#else
+
+ return(FALSE);
+
+#endif
+}
+
diff --git a/btusb_1_6_29_1/src/gki/.svn/text-base/gki_klinux.c.svn-base b/btusb_1_6_29_1/src/gki/.svn/text-base/gki_klinux.c.svn-base
new file mode 100755
index 0000000..fb424ee
--- a/dev/null
+++ b/btusb_1_6_29_1/src/gki/.svn/text-base/gki_klinux.c.svn-base
@@ -0,0 +1,271 @@
+/*
+ *
+ * gki_klinux.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/slab.h>
+
+/* The location folder of the semaphore.h file changed at Kernel version 2.6.26 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+#include "target.h"
+#include "gki_int.h"
+#include "bt_types.h"
+
+
+volatile unsigned int _gki_lock_nesting = 0;
+volatile pid_t LockThread = 0xffff; // thread currently holding the spinlock
+DEFINE_SPINLOCK(Lock);
+volatile unsigned long Kirql; // saved execution priority
+
+/* Define the structure that holds the GKI variables
+*/
+#ifndef _BT_DYNAMIC_MEMORY
+tGKI_CB gki_cb = {0};
+#else
+tGKI_CB *gp_gki_cb = NULL;
+#endif
+
+void LogMsg(int TraceMask, const char *format, ...)
+{
+ char temp1[400];
+ char *temp = temp1;
+ va_list Next;
+ int len;
+
+ // Go ahead and trace...
+ va_start(Next, format);
+ len = _vsnprintf(temp, 380, format, Next);
+ va_end(Next);
+
+
+ if ((len < 0) || (len > 380))
+ {
+ len = strlen(temp);
+ }
+
+ if (len > 380)
+ {
+ temp[380] = 0;
+ len = 380;
+
+ }
+
+ if (temp[len - 1] >= ' ')
+ {
+ temp[len] = '\n';
+ temp[len + 1] = '\0';
+ }
+
+
+ printk("%s", temp);
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_init
+**
+** Description This function is called once at startup to initialize
+** all the timer structures.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_init(void)
+{
+ memset(&gki_cb, 0, sizeof(gki_cb));
+
+ gki_buffer_init();
+
+ spin_lock_init(&Lock);
+ gki_cb.IsRunning = TRUE;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_shutdown
+**
+** Description This function is called to shut down GKI
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_shutdown(void)
+{
+ int i;
+
+ if (!gki_cb.IsRunning)
+ return;
+
+ gki_cb.IsRunning = FALSE;
+
+#if (GKI_USE_DYNAMIC_BUFFERS == TRUE)
+
+ for (i = 0; i < GKI_NUM_TOTAL_BUF_POOLS; i++)
+ {
+ if (gki_cb.pool_buf_size[i])
+ GKI_delete_pool((UINT8)i);
+ }
+
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function GKI_enable
+**
+** Description This function enables interrupts.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enable(void)
+{
+ spin_unlock_irqrestore(&Lock, Kirql);
+}
+
+/*******************************************************************************
+**
+** Function GKI_disable
+**
+** Description This function disables interrupts.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_disable(void)
+{
+ volatile unsigned long tmp_irql;
+
+ spin_lock_irqsave(&Lock, tmp_irql);
+
+ // OK, we've acquired the spinlock. It means that
+ // the other guy has released it already and we can
+ // safely overwrite his saved irql...
+ Kirql = tmp_irql;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_exception
+**
+** Description This function throws an exception.
+** This is normally only called for a non recoverable error.
+**
+** Parameters: code - (input) The code for the error
+** msg - (input) The message that has to be logged
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_exception(UINT16 code, const char *msg, ...)
+{
+ char buff[MAX_EXCEPTION_MSGLEN];
+ va_list Next;
+ int len;
+
+ va_start(Next, msg);
+ len = vsnprintf(buff, MAX_EXCEPTION_MSGLEN - 1, msg, Next);
+ va_end(Next);
+
+ LogMsg(-1, "GKI_exception: Entry Code %d Message %s\n", code, buff);
+ GKI_disable();
+
+ if (gki_cb.ExceptionCnt < MAX_EXCEPTION)
+ {
+ EXCEPTION_T *pExp;
+
+ pExp = &gki_cb.Exception[gki_cb.ExceptionCnt++];
+ pExp->type = code;
+ pExp->taskid = 0;
+ strncpy((INT8 *)pExp->msg, msg, MAX_EXCEPTION_MSGLEN - 1);
+ }
+
+ GKI_enable();
+
+ LogMsg(-1, "GKI_Exception called with code: %d", code);
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function gki_reserve_os_memory
+**
+** Description This function allocates memory
+**
+** Parameters: size - (input) The size of the memory that has to be
+** allocated
+**
+** Returns the address of the memory allocated, or NULL if failed
+**
+** NOTE This function is NOT called by the Widcomm stack and
+** profiles. It is only called from within GKI if dynamic
+** buffer pools are used.
+**
+*******************************************************************************/
+void *gki_reserve_os_memory(UINT32 size)
+{
+ void *p;
+ p = kmalloc(size, GFP_ATOMIC);
+ if (p == NULL)
+ return NULL;
+ memset(p, 0x00, sizeof(*p));
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function gki_release_os_memory
+**
+** Description This function frees memory
+**
+** Parameters: size - (input) The address of the memory that has to be
+** freed
+**
+** Returns void
+**
+** NOTE This function is NOT called by the Widcomm stack and
+** profiles. It is only called from within GKI if dynamic
+** buffer pools are used.
+**
+*******************************************************************************/
+void gki_release_os_memory(void *p_mem)
+{
+ kfree(p_mem);
+
+ return;
+}
+
+
diff --git a/btusb_1_6_29_1/src/gki/gki_buffer.c b/btusb_1_6_29_1/src/gki/gki_buffer.c
new file mode 100755
index 0000000..496cb90
--- a/dev/null
+++ b/btusb_1_6_29_1/src/gki/gki_buffer.c
@@ -0,0 +1,1282 @@
+/*
+ *
+ * gki_buffer.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+#include "gki_int.h"
+#include "btusb.h"
+
+#if (GKI_NUM_TOTAL_BUF_POOLS > 16)
+#error Number of pools out of range (16 Max)!
+#endif
+
+static void gki_add_to_pool_list(UINT8 pool_id);
+static void gki_remove_from_pool_list(UINT8 pool_id);
+
+static BOOL _b_in_gki_getbuf = FALSE;
+
+/*******************************************************************************
+**
+** Function gki_init_free_queue
+**
+** Description Internal function called at startup to initialize a free
+** queue. It is called once for each free queue.
+**
+** Returns void
+**
+*******************************************************************************/
+static BOOL gki_init_free_queue(UINT8 id, UINT16 size, UINT16 total, void *p_mem)
+{
+ UINT16 i;
+ UINT16 act_size;
+ BUFFER_HDR_T *hdr;
+ BUFFER_HDR_T *hdr1 = NULL;
+ UINT32 *magic;
+ int seg_inx = gki_cb.pool_additions[id];
+ FREE_QUEUE_T *p_freeq = &gki_cb.freeq[id];
+
+ if (seg_inx >= MAX_BUFFPOOL_SEGS)
+ {
+ GKI_exception(GKI_ERROR_SEGS_EXCEEDED, "Max segs exceeded");
+ return(FALSE);
+ }
+
+ act_size = (UINT16)(size + BUFFER_PADDING_SIZE);
+
+ if (!p_mem)
+ p_mem = gki_reserve_os_memory(act_size * total);
+
+ if (!p_mem)
+ {
+ GKI_exception(GKI_ERROR_NO_MEMORY_FOR_SEG, "No memory for segment");
+ return(FALSE);
+ }
+
+ /* Remember pool start and end addresses */
+ p_freeq->seg_start[seg_inx] = (UINT8 *)p_mem;
+ p_freeq->seg_end[seg_inx] = (UINT8 *)p_mem + (act_size * total);
+
+ if (seg_inx == 0)
+ {
+ gki_cb.freeq[id].total = total;
+ gki_cb.freeq[id].cur_cnt = 0;
+ gki_cb.freeq[id].max_cnt = 0;
+ }
+ else
+ gki_cb.freeq[id].total += total;
+
+ /* Initialize index table */
+ hdr = (BUFFER_HDR_T *)p_mem;
+ p_freeq->p_first = hdr;
+
+#ifdef TRACE_GKI_BUFFERS
+ gki_cb.freeq[id].p_first_all = hdr;
+#endif
+
+ for (i = 0; i < total; i++)
+ {
+ hdr->task_id = GKI_INVALID_TASK;
+ hdr->q_id = id;
+ hdr->status = BUF_STATUS_FREE;
+ magic = (UINT32 *)((UINT8 *)hdr + BUFFER_HDR_SIZE + size);
+ *magic = MAGIC_NO;
+ hdr1 = hdr;
+ hdr = (BUFFER_HDR_T *)((UINT8 *)hdr + act_size);
+ hdr1->p_next = hdr;
+#ifdef TRACE_GKI_BUFFERS
+ hdr1->p_next_all = hdr;
+ hdr1->pFile = NULL;
+ hdr1->linenum = 0;
+ hdr1->times_alloc = 0;
+#endif
+ }
+
+ hdr1->p_next = NULL;
+ p_freeq->p_last = hdr1;
+
+ gki_cb.pool_additions[id]++;
+
+ return(TRUE);
+}
+
+
+/*******************************************************************************
+**
+** Function gki_buffer_init
+**
+** Description Called once internally by GKI at startup to initialize all
+** buffers and free buffer pools.
+**
+** Returns void
+**
+*******************************************************************************/
+void gki_buffer_init(void)
+{
+ UINT8 tt;
+ UINT16 access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
+
+#ifdef TRACE_GKI_BUFFERS
+ char aString[200];
+ sprintf(aString,"%s: %d: WARNING! Running with GKI buffer tracing enabled!!",__FILE__,__LINE__);
+ GKI_exception(GKI_ERROR_BUFFER_TRACE_ON,aString);
+#endif
+
+ for (tt = 0; tt < GKI_NUM_TOTAL_BUF_POOLS; tt++)
+ {
+ memset(&gki_cb.freeq[tt], 0, sizeof(FREE_QUEUE_T));
+
+ gki_cb.pool_buf_size[tt] = 0;
+ gki_cb.pool_max_count[tt] = 0;
+ gki_cb.pool_additions[tt] = 0;
+ }
+
+ /* Use default from target.h */
+ gki_cb.pool_access_mask = GKI_DEF_BUFPOOL_PERM_MASK;
+
+#if (GKI_USE_DYNAMIC_BUFFERS == TRUE)
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ GKI_create_pool(GKI_BUF0_SIZE, GKI_BUF0_MAX, (UINT8) (access_mask & 1), NULL);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ GKI_create_pool(GKI_BUF1_SIZE, GKI_BUF1_MAX, (UINT8) (access_mask & 1), NULL);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ GKI_create_pool(GKI_BUF2_SIZE, GKI_BUF2_MAX, (UINT8) (access_mask & 1), NULL);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ GKI_create_pool(GKI_BUF3_SIZE, GKI_BUF3_MAX, (UINT8) (access_mask & 1), NULL);
+#endif
+
+#else
+
+/* Static buffers */
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 0)
+ GKI_create_pool(GKI_BUF0_SIZE, GKI_BUF0_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool0);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 1)
+ GKI_create_pool(GKI_BUF1_SIZE, GKI_BUF1_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool1);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 2)
+ GKI_create_pool(GKI_BUF2_SIZE, GKI_BUF2_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool2);
+ access_mask = access_mask >> 1;
+#endif
+
+#if (GKI_NUM_FIXED_BUF_POOLS > 3)
+ GKI_create_pool(GKI_BUF3_SIZE, GKI_BUF3_MAX, (UINT8) (access_mask & 1), gki_cb.bufpool3);
+#endif
+
+#endif
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_set_pool_permission
+**
+** Description This function is called to set or change the permissions for
+** the specified pool ID.
+**
+** Parameters pool_id - (input) pool ID to be set or changed
+** permission - (input) GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL
+**
+** Returns GKI_SUCCESS if successful
+** GKI_INVALID_POOL if unsuccessful
+**
+*******************************************************************************/
+UINT8 GKI_set_pool_permission(UINT8 pool_id, UINT8 permission)
+{
+ if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ if (permission == GKI_RESTRICTED_POOL)
+ gki_cb.pool_access_mask |= (1 << pool_id);
+
+ else /* mark the pool as public */
+ gki_cb.pool_access_mask &= ~(1 << pool_id);
+
+ return(GKI_SUCCESS);
+ }
+ else
+ return(GKI_INVALID_POOL);
+}
+
+
+/*******************************************************************************
+**
+** Function gki_add_to_pool_list
+**
+** Description Adds pool to the pool list which is arranged in the
+** order of size
+**
+** Returns void
+**
+*******************************************************************************/
+static void gki_add_to_pool_list(UINT8 pool_id)
+{
+ INT32 i, j;
+
+ /* Find the position where the specified pool should be inserted into the list */
+ for (i = 0; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ if (gki_cb.pool_buf_size[pool_id] <= gki_cb.pool_buf_size[gki_cb.pool_list[i]])
+ break;
+ }
+
+ /* Insert the new buffer pool ID into the list of pools */
+ j = (gki_cb.curr_total_no_of_pools < GKI_NUM_TOTAL_BUF_POOLS - 1) ? gki_cb.curr_total_no_of_pools : GKI_NUM_TOTAL_BUF_POOLS - 1;
+
+ for (; j > i; j--)
+ {
+ gki_cb.pool_list[j] = gki_cb.pool_list[j-1];
+ }
+
+ gki_cb.pool_list[i] = pool_id;
+}
+
+
+/*******************************************************************************
+**
+** Function gki_remove_from_pool_list
+**
+** Description Removes pool from the pool list. Called when a pool is deleted
+**
+** Returns void
+**
+*******************************************************************************/
+static void gki_remove_from_pool_list(UINT8 pool_id)
+{
+ UINT8 i;
+
+ for (i = 0; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ if (pool_id == gki_cb.pool_list[i])
+ break;
+ }
+
+ while (i < (GKI_NUM_TOTAL_BUF_POOLS - 1))
+ {
+ gki_cb.pool_list[i] = gki_cb.pool_list[i+1];
+ i++;
+ }
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_init_q
+**
+** Description Called by an application to initialize a buffer queue.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_init_q(BUFFER_Q *p_q)
+{
+ p_q->p_first = p_q->p_last = NULL;
+ p_q->count = 0;
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getbuf
+**
+** Description Called by an application to get a free buffer which
+** is of size greater or equal to the requested size.
+**
+** Note: This routine only takes buffers from public pools.
+** It will not use any buffers from pools
+** marked GKI_RESTRICTED_POOL.
+**
+** Parameters size - (input) number of bytes needed.
+**
+** Returns A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+#ifdef TRACE_GKI_BUFFERS
+void *GKI_getbuf_trace(UINT16 size, char *pFile, int linenum)
+#else
+void *GKI_getbuf(UINT16 size)
+#endif
+{
+ UINT8 i, pool_id;
+ void *pp;
+
+ if (unlikely(size == 0))
+ {
+ GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "getbuf: Size is zero");
+ return(NULL);
+ }
+
+ /* Find the first buffer pool that is public that can hold the desired size */
+ for (i = 0; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ if (gki_cb.pool_buf_size[gki_cb.pool_list[i]] >= size)
+ break;
+ }
+
+ if (i == gki_cb.curr_total_no_of_pools)
+ {
+ char buff[40];
+ sprintf(buff, "getbuf: Size: %u is too big", size);
+ GKI_exception(GKI_ERROR_BUF_SIZE_TOOBIG, buff);
+ return(NULL);
+ }
+
+ _b_in_gki_getbuf = TRUE;
+
+ /* search the public buffer pools that are big enough to hold the size
+ * until a free buffer is found */
+ for ( ; i < gki_cb.curr_total_no_of_pools; i++)
+ {
+ pool_id = gki_cb.pool_list[i];
+
+ /* Only look at PUBLIC buffer pools (bypass RESTRICTED pools) */
+ if (((UINT16)1 << pool_id) & gki_cb.pool_access_mask)
+ continue;
+
+ if ((pp = GKI_getpoolbuf(pool_id)) != NULL)
+ {
+ _b_in_gki_getbuf = FALSE;
+ return(pp);
+ }
+ }
+
+ _b_in_gki_getbuf = FALSE;
+
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getpoolbuf
+**
+** Description Called by an application to get a free buffer from
+** a specific buffer pool.
+**
+** Note: If there are no more buffers available from the pool,
+** the public buffers are searched for an available buffer.
+**
+** Parameters pool_id - (input) pool ID to get a buffer out of.
+**
+** Returns A pointer to the buffer, or NULL if none available
+**
+*******************************************************************************/
+#ifdef TRACE_GKI_BUFFERS
+void *GKI_getpoolbuf_trace(UINT8 pool_id, char *pFile, int linenum)
+#else
+void *GKI_getpoolbuf(UINT8 pool_id)
+#endif
+{
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return(NULL);
+
+ /* Make sure the buffers aren't disturbed til finished with allocation */
+ GKI_disable();
+
+ Q = &gki_cb.freeq[pool_id];
+
+ /* If we have no buffers left, see if we can allocate another segment */
+ if ((Q->cur_cnt >= Q->total) && (gki_cb.pool_additions[pool_id] < MAX_BUFFPOOL_SEGS))
+ {
+ UINT16 count = (gki_cb.pool_max_count[pool_id] + MAX_BUFFPOOL_SEGS - 1) / MAX_BUFFPOOL_SEGS;
+
+ gki_init_free_queue(pool_id, gki_cb.pool_buf_size[pool_id], count, NULL);
+ }
+
+ if (Q->cur_cnt < Q->total)
+ {
+ p_hdr = Q->p_first;
+ Q->p_first = p_hdr->p_next;
+
+ if (!Q->p_first)
+ Q->p_last = NULL;
+
+ if (++Q->cur_cnt > Q->max_cnt)
+ Q->max_cnt = Q->cur_cnt;
+
+ GKI_enable();
+
+ p_hdr->status = BUF_STATUS_UNLINKED;
+ p_hdr->p_next = NULL;
+ p_hdr->Type = 0;
+
+#ifdef TRACE_GKI_BUFFERS
+ p_hdr->pFile = pFile;
+ p_hdr->linenum = linenum;
+ p_hdr->times_alloc++;
+ /* The following is here to allow the test engineer to recognize and */
+ /* set a breakpoint when a particular buffer is allocated for the nth time. */
+ /* Simply change the address and allocation number in the following 'if' */
+ /* statement to reflect the buffer and occurance desired. */
+ if ((p_hdr == (BUFFER_HDR_T *)0x12345678) && (p_hdr->times_alloc == 123))
+ p_hdr->times_alloc = 123;
+#endif
+
+ return((void *) ((UINT8 *)p_hdr + BUFFER_HDR_SIZE));
+ }
+
+ /* If here, no buffers in the specified pool */
+ GKI_enable();
+
+ /* Try for free buffers in public pools. NOTE - no recursion allowed */
+ if (!_b_in_gki_getbuf)
+ return(GKI_getbuf(gki_cb.pool_buf_size[pool_id]));
+ else
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_freebuf
+**
+** Description Called by an application to return a buffer to the free pool.
+**
+** Parameters p_buf - (input) address of the beginning of a buffer.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_freebuf(void *p_buf)
+{
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+ void *pNextBuf;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (!p_buf || gki_chk_buf_damage(p_buf))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - Buf Corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_FREEBUF_BUF_LINKED, "Freeing Linked Buf");
+ return;
+ }
+
+ if (p_hdr->q_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ GKI_exception(GKI_ERROR_FREEBUF_BAD_QID, "Bad Buf QId");
+ return;
+ }
+
+#ifdef TRACE_GKI_BUFFERS
+ if ((p_hdr->pFile == NULL) || (p_hdr->linenum == 0))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Free - no file or line number");
+ }
+#endif
+
+ GKI_disable();
+
+ /*
+ ** Releasing all buffers in the linked list
+ */
+ while (p_buf)
+ {
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+
+ pNextBuf = NULL;
+ Q = &gki_cb.freeq[p_hdr->q_id];
+ if (Q->p_last)
+ Q->p_last->p_next = p_hdr;
+ else
+ Q->p_first = p_hdr;
+
+ Q->p_last = p_hdr;
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_FREE;
+ p_hdr->task_id = GKI_INVALID_TASK;
+#ifdef TRACE_GKI_BUFFERS
+ p_hdr->pFile = NULL;
+ p_hdr->linenum = 0;
+#endif
+ if (Q->cur_cnt > 0)
+ Q->cur_cnt--;
+
+ p_buf = pNextBuf;
+ }
+
+ GKI_enable();
+
+ return;
+}
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+/*******************************************************************************
+**
+** Function GKI_get_buf_size
+**
+** Description Called by an application to get the size of a buffer.
+**
+** Parameters p_buf - (input) address of the beginning of a buffer.
+**
+** Returns the size of the buffer
+**
+*******************************************************************************/
+UINT16 GKI_get_buf_size(void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *)((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if ((uintptr_t)p_hdr & 1)
+ {
+ return(0);
+ }
+
+ if (p_hdr->q_id < GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ return(gki_cb.pool_buf_size[p_hdr->q_id]);
+ }
+ else if (p_hdr->q_id == GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ return offsetof(tBTUSB_TRANSACTION, magic) - offsetof(tBTUSB_TRANSACTION, bt_hdr);
+ }
+
+
+ return(0);
+}
+#endif
+
+/*******************************************************************************
+**
+** Function GKI_get_pool_bufsize
+**
+** Description Called by an application to get the size of buffers in a pool
+**
+** Parameters Pool ID.
+**
+** Returns the size of buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_get_pool_bufsize(UINT8 pool_id)
+{
+ if (pool_id < GKI_NUM_TOTAL_BUF_POOLS)
+ return(gki_cb.pool_buf_size[pool_id]);
+
+ return(0);
+}
+
+/*******************************************************************************
+**
+** Function GKI_poolfreecount
+**
+** Description Called by an application to get the number of free buffers
+** in the specified buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get the free count of.
+**
+** Returns the number of free buffers in the pool
+**
+*******************************************************************************/
+UINT16 GKI_poolfreecount(UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return(0);
+
+ Q = &gki_cb.freeq[pool_id];
+
+ return((UINT16)(Q->total - Q->cur_cnt));
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_poolutilization
+**
+** Description Called by an application to get the buffer utilization
+** in the specified buffer pool.
+**
+** Parameters pool_id - (input) pool ID to get the free count of.
+**
+** Returns % of buffers used from 0 to 100
+**
+*******************************************************************************/
+UINT16 GKI_poolutilization(UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ return(100);
+
+ Q = &gki_cb.freeq[pool_id];
+
+ if (Q->total == 0)
+ return(100);
+
+ return((Q->cur_cnt * 100) / Q->total);
+}
+
+
+
+/*******************************************************************************
+**
+** Function gki_chk_buf_damage
+**
+** Description Called internally by OSS to check for buffer corruption.
+**
+** Returns TRUE if there is a problem, else FALSE
+**
+*******************************************************************************/
+BOOLEAN gki_chk_buf_damage(void *p_buf)
+{
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+
+ UINT32 *magic;
+ magic = (UINT32 *)((UINT8 *) p_buf + GKI_get_buf_size(p_buf));
+
+ if ((uintptr_t)magic & 1)
+ return(TRUE);
+
+ if (*magic == MAGIC_NO)
+ return(FALSE);
+
+ return(TRUE);
+
+#else
+
+ return(FALSE);
+
+#endif
+}
+
+/*******************************************************************************
+**
+** Function gki_chk_buf_owner
+**
+** Description Called internally by OSS to check if the current task
+** is the owner of the buffer.
+**
+** Returns TRUE if not owner, else FALSE
+**
+*******************************************************************************/
+BOOLEAN gki_chk_buf_owner(void *p_buf)
+{
+ return(FALSE);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_change_buf_owner
+**
+** Description Called to change the task ownership of a buffer.
+**
+** Parameters: p_buf - (input) pointer to the buffer
+** task_id - (input) task id to change ownership to
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_change_buf_owner(void *p_buf, UINT8 task_id)
+{
+ BUFFER_HDR_T *p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ p_hdr->task_id = task_id;
+
+ return;
+}
+
+
+
+/*******************************************************************************
+**
+** Function GKI_buffer_status
+**
+** Description check status of the buffer to see if it is linked
+**
+** Parameters: p_buf - (input) address of the buffer to enqueue
+**
+** Returns state
+* BUF_STATUS_FREE 0
+* BUF_STATUS_UNLINKED 1
+* BUF_STATUS_QUEUED 2
+**
+*******************************************************************************/
+UINT8 GKI_buffer_status(void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ return(p_hdr->status);
+}
+
+/*******************************************************************************
+**
+** Function GKI_enqueue
+**
+** Description Enqueue a buffer at the tail of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enqueue(BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(p_buf))
+ {
+ //printk("Enqueue - Buffer corrupted\n");
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ printk("Enqueue - buf already linked\n");
+ GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Enqueue - buf already linked : p_hdr->status: %d, buffer: 0x%p",p_hdr->status, p_buf);
+ return;
+ }
+
+ GKI_disable();
+
+ /* Since the queue is exposed (C vs C++), keep the pointers in exposed format */
+ /* check p_last != NULL before dereferencing it and if p_last == NULL then p_first == NULL */
+ if (p_q->p_last)
+ {
+ BUFFER_HDR_T *p_last_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_last - BUFFER_HDR_SIZE);
+ p_last_hdr->p_next = p_hdr;
+
+ /* sanity check, this should not happen */
+ if (p_q->p_first == NULL)
+ {
+ printk("ERROR: Enqueue - first == NULL , last != NULL (0x%p)\n", p_q->p_last);
+ }
+ }
+ else
+ {
+ /* sanity check, this should not happen */
+ if (p_q->p_first != NULL)
+ {
+ printk("ERROR: Enqueue - first != NULL (0x%p), last == NULL\n", p_q->p_first);
+ }
+
+ p_q->p_first = p_buf;
+ }
+
+ p_q->p_last = p_buf;
+ p_q->count++;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_QUEUED;
+
+ GKI_enable();
+ // printk("Enqueue: out from GKI_enqueue\n");
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_enqueue_head
+**
+** Description Enqueue a buffer at the head of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enqueue_head(BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ if (gki_chk_buf_damage(p_buf))
+ {
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "Enqueue - Buffer corrupted");
+ return;
+ }
+#endif
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->status != BUF_STATUS_UNLINKED)
+ {
+ GKI_exception(GKI_ERROR_ENQUEUE_BUF_LINKED, "Enqeueue head - buf already linked");
+ return;
+ }
+
+ GKI_disable();
+
+ if (p_q->p_first)
+ {
+ p_hdr->p_next = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+ p_q->p_first = p_buf;
+ }
+ else
+ {
+ p_q->p_first = p_buf;
+ p_q->p_last = p_buf;
+ p_hdr->p_next = NULL;
+ }
+ p_q->count++;
+
+ p_hdr->status = BUF_STATUS_QUEUED;
+
+ GKI_enable();
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_dequeue
+**
+** Description Dequeues a buffer from the head of a queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_dequeue(BUFFER_Q *p_q)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ GKI_disable();
+
+ if (!p_q || !p_q->count)
+ {
+ GKI_enable();
+ return(NULL);
+ }
+
+ p_hdr = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+
+ /* Keep buffers such that GKI header is invisible */
+ if (p_hdr->p_next)
+ p_q->p_first = ((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+ else
+ {
+ p_q->p_first = NULL;
+ p_q->p_last = NULL;
+ }
+
+ p_q->count--;
+
+ p_hdr->p_next = NULL;
+ p_hdr->status = BUF_STATUS_UNLINKED;
+
+ GKI_enable();
+
+ return((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_remove_from_queue
+**
+** Description Dequeue a buffer from the middle of the queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+** p_buf - (input) address of the buffer to enqueue
+**
+** Returns NULL if queue is empty, else buffer
+**
+*******************************************************************************/
+void *GKI_remove_from_queue(BUFFER_Q *p_q, void *p_buf)
+{
+ BUFFER_HDR_T *p_prev;
+ BUFFER_HDR_T *p_buf_hdr;
+
+ GKI_disable();
+
+ if (p_buf == p_q->p_first)
+ {
+ GKI_enable();
+ return(GKI_dequeue(p_q));
+ }
+
+ p_buf_hdr = (BUFFER_HDR_T *)((UINT8 *)p_buf - BUFFER_HDR_SIZE);
+ p_prev = (BUFFER_HDR_T *)((UINT8 *)p_q->p_first - BUFFER_HDR_SIZE);
+
+ for ( ; p_prev; p_prev = p_prev->p_next)
+ {
+ /* If the previous points to this one, move the pointers around */
+ if (p_prev->p_next == p_buf_hdr)
+ {
+ p_prev->p_next = p_buf_hdr->p_next;
+
+ /* If we are removing the last guy in the queue, update p_last */
+ if (p_buf == p_q->p_last)
+ p_q->p_last = p_prev + 1;
+
+ /* One less in the queue */
+ p_q->count--;
+
+ /* The buffer is now unlinked */
+ p_buf_hdr->p_next = NULL;
+ p_buf_hdr->status = BUF_STATUS_UNLINKED;
+
+ GKI_enable();
+ return(p_buf);
+ }
+ }
+
+ GKI_enable();
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getfirst
+**
+** Description Return a pointer to the first buffer in a queue
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns NULL if queue is empty, else buffer address
+**
+*******************************************************************************/
+void *GKI_getfirst(BUFFER_Q *p_q)
+{
+ return(p_q->p_first);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_getnext
+**
+** Description Return a pointer to the next buffer in a queue
+**
+** Parameters: p_buf - (input) pointer to the buffer to find the next one from.
+**
+** Returns NULL if no more buffers in the queue, else next buffer address
+**
+*******************************************************************************/
+void *GKI_getnext(void *p_buf)
+{
+ BUFFER_HDR_T *p_hdr;
+
+ p_hdr = (BUFFER_HDR_T *) ((UINT8 *) p_buf - BUFFER_HDR_SIZE);
+
+ if (p_hdr->p_next)
+ return((UINT8 *)p_hdr->p_next + BUFFER_HDR_SIZE);
+ else
+ return(NULL);
+}
+
+
+
+/*******************************************************************************
+**
+** Function GKI_queue_is_empty
+**
+** Description Check the status of a queue.
+**
+** Parameters: p_q - (input) pointer to a queue.
+**
+** Returns TRUE if queue is empty, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GKI_queue_is_empty(BUFFER_Q *p_q)
+{
+ return((BOOLEAN)(p_q->count == 0));
+}
+
+/*******************************************************************************
+**
+** Function GKI_find_buf_start
+**
+** Description This function is called with an address inside a buffer,
+** and returns the start address of the buffer.
+**
+** The buffer should be one allocated from one of GKI's pools.
+**
+** Parameters: p_user_area - (input) address of anywhere in a GKI buffer.
+**
+** Returns void * - Address of the beginning of the specified buffer if successful,
+** otherwise NULL if unsuccessful
+**
+*******************************************************************************/
+void *GKI_find_buf_start(void *p_user_area)
+{
+ int pool_id, seg_inx;
+ UINT16 size;
+ UINT32 yy;
+ UINT8 *p_ua = (UINT8 *)p_user_area;
+ FREE_QUEUE_T *p_fq = gki_cb.freeq;
+
+ for (pool_id = 0; pool_id < gki_cb.curr_total_no_of_pools; pool_id++, p_fq++)
+ {
+ for (seg_inx = 0; (seg_inx < MAX_BUFFPOOL_SEGS) && (p_fq->seg_start[seg_inx] != NULL); seg_inx++)
+ {
+ if ((p_ua > p_fq->seg_start[seg_inx]) && (p_ua < p_fq->seg_end[seg_inx]))
+ {
+ yy = (UINT32)(p_ua - p_fq->seg_start[seg_inx]);
+
+ size = gki_cb.pool_buf_size[pool_id] + BUFFER_PADDING_SIZE;
+
+ yy = (yy / size) * size;
+
+ return((void *) (p_fq->seg_start[seg_inx] + yy + sizeof(BUFFER_HDR_T)) );
+ }
+ }
+ }
+
+ /* If here, invalid address - not in one of our buffers */
+ GKI_exception(GKI_ERROR_BUF_SIZE_ZERO, "GKI_get_buf_start:: bad addr");
+
+ return(NULL);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_create_pool
+**
+** Description Called by applications to create a buffer pool.
+**
+** Parameters: size - (input) length (in bytes) of each buffer in the pool
+** count - (input) number of buffers to allocate for the pool
+** permission - (input) restricted or public access?
+** (GKI_PUBLIC_POOL or GKI_RESTRICTED_POOL)
+** p_mem_pool - (input) pointer to an OS memory pool, NULL if not provided
+**
+** Returns the buffer pool ID, which should be used in calls to
+** GKI_getpoolbuf(). If a pool could not be created, this
+** function returns 0xff.
+**
+*******************************************************************************/
+UINT8 GKI_create_pool(UINT16 size, UINT16 count, UINT8 permission, void *p_mem_pool)
+{
+ int xx;
+
+ /* First make sure the size of each pool has a valid size with room for the header info */
+ if (size > MAX_USER_BUF_SIZE)
+ return(GKI_INVALID_POOL);
+
+ /* First, look for an unused pool */
+ for (xx = 0; xx < GKI_NUM_TOTAL_BUF_POOLS; xx++)
+ {
+ if (!gki_cb.pool_buf_size[xx])
+ break;
+ }
+
+ if (xx == GKI_NUM_TOTAL_BUF_POOLS)
+ return(GKI_INVALID_POOL);
+
+ GKI_disable();
+
+ /* Ensure an even number of longwords */
+ size = ((size + 3) / 4) * 4;
+
+ gki_cb.pool_buf_size[xx] = size;
+ gki_cb.pool_max_count[xx] = count;
+ gki_cb.pool_additions[xx] = 0;
+
+ /* If memory was not passed in, create the pool in segments */
+ if (!p_mem_pool)
+ count = (count + MAX_BUFFPOOL_SEGS - 1) / MAX_BUFFPOOL_SEGS;
+
+ /* Initialize the new pool */
+ if (gki_init_free_queue(xx, size, count, p_mem_pool))
+ {
+ gki_add_to_pool_list(xx);
+
+ (void) GKI_set_pool_permission(xx, permission);
+ gki_cb.curr_total_no_of_pools++;
+ }
+ else
+ {
+ /* Failed to create the pool ? */
+ gki_cb.pool_buf_size[xx] = 0;
+ GKI_enable();
+ return(GKI_INVALID_POOL);
+ }
+
+ /* If memory was passed in, no pool additions allowed */
+ if (p_mem_pool)
+ gki_cb.pool_additions[xx] = MAX_BUFFPOOL_SEGS;
+
+ GKI_enable();
+ return(xx);
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_delete_pool
+**
+** Description Called by applications to delete a buffer pool. The function
+** calls the operating specific function to free the actual memory.
+** An exception is generated if an error is detected.
+**
+** Parameters: pool_id - (input) Id of the poll being deleted.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_delete_pool(UINT8 pool_id)
+{
+ FREE_QUEUE_T *Q;
+ int xx;
+
+ if ( (pool_id >= GKI_NUM_TOTAL_BUF_POOLS) || (!gki_cb.pool_buf_size[pool_id]) )
+ return;
+
+ GKI_disable();
+
+ Q = &gki_cb.freeq[pool_id];
+
+ Q->total = 0;
+ Q->cur_cnt = 0;
+ Q->max_cnt = 0;
+ Q->p_first = NULL;
+ Q->p_last = NULL;
+
+ for (xx = 0; xx < MAX_BUFFPOOL_SEGS; xx++)
+ {
+ if (Q->seg_start[xx])
+ gki_release_os_memory(Q->seg_start[xx]);
+
+ Q->seg_start[xx] = NULL;
+ Q->seg_end[xx] = NULL;
+ }
+
+ gki_cb.pool_buf_size[pool_id] = 0;
+
+ gki_remove_from_pool_list(pool_id);
+ gki_cb.curr_total_no_of_pools--;
+
+ GKI_enable();
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_chk_buf_pool_damage
+**
+** Description Called internally by OSS to check for buffer queue corruption.
+**
+** Returns TRUE if there is a problem, else FALSE
+**
+*******************************************************************************/
+BOOLEAN GKI_chk_buf_pool_damage(UINT8 pool_id)
+{
+#if (GKI_ENABLE_BUF_CORRUPTION_CHECK == TRUE)
+ int i;
+ FREE_QUEUE_T *Q;
+ BUFFER_HDR_T *p_hdr;
+ UINT8 *p_buf;
+
+ if (pool_id >= GKI_NUM_TOTAL_BUF_POOLS)
+ {
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "pool_id out of range");
+ return(TRUE);
+ }
+
+ /* Make sure the buffers aren't disturbed til finished with checking */
+ GKI_disable();
+
+ Q = &gki_cb.freeq[pool_id];
+ if (!Q->p_first)
+ {
+ if (Q->cur_cnt != Q->total)
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "p_first is NULL in non-empty pool");
+ return(TRUE);
+ }
+ return(FALSE);
+ }
+ p_hdr = Q->p_first;
+ i = 1;
+ while (p_hdr->p_next)
+ {
+ p_hdr = p_hdr->p_next;
+ p_buf = ((UINT8 *)p_hdr + BUFFER_HDR_SIZE);
+ if (gki_chk_buf_damage(p_buf))
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_CORRUPTED, "CHk Pool - Buf Corrupted");
+ return(TRUE);
+ }
+ i++;
+ }
+ if (p_hdr != Q->p_last)
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "last buffer in chain != p_last");
+ return(TRUE);
+ }
+ if (i != (Q->total - Q->cur_cnt))
+ {
+ GKI_enable();
+ GKI_exception(GKI_ERROR_BUF_POOL_CORRUPT, "cur_cnt != number of buffers in pool");
+ return(TRUE);
+ }
+
+ GKI_enable();
+ return(FALSE);
+
+#else
+
+ return(FALSE);
+
+#endif
+}
+
diff --git a/btusb_1_6_29_1/src/gki/gki_klinux.c b/btusb_1_6_29_1/src/gki/gki_klinux.c
new file mode 100755
index 0000000..fb424ee
--- a/dev/null
+++ b/btusb_1_6_29_1/src/gki/gki_klinux.c
@@ -0,0 +1,271 @@
+/*
+ *
+ * gki_klinux.c
+ *
+ *
+ *
+ * Copyright (C) 2011-2012 Broadcom Corporation.
+ *
+ *
+ *
+ * This software is licensed under the terms of the GNU General Public License,
+ * version 2, as published by the Free Software Foundation (the "GPL"), and may
+ * be copied, distributed, and modified under those terms.
+ *
+ * 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 GPL for more details.
+ *
+ *
+ * A copy of the GPL is available at http://www.broadcom.com/licenses/GPLv2.php
+ * or by writing to the Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA
+ *
+ *
+ */
+
+#include <linux/version.h>
+#include <linux/slab.h>
+
+/* The location folder of the semaphore.h file changed at Kernel version 2.6.26 */
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,6,26)
+#include <linux/semaphore.h>
+#else
+#include <asm/semaphore.h>
+#endif
+
+#include "target.h"
+#include "gki_int.h"
+#include "bt_types.h"
+
+
+volatile unsigned int _gki_lock_nesting = 0;
+volatile pid_t LockThread = 0xffff; // thread currently holding the spinlock
+DEFINE_SPINLOCK(Lock);
+volatile unsigned long Kirql; // saved execution priority
+
+/* Define the structure that holds the GKI variables
+*/
+#ifndef _BT_DYNAMIC_MEMORY
+tGKI_CB gki_cb = {0};
+#else
+tGKI_CB *gp_gki_cb = NULL;
+#endif
+
+void LogMsg(int TraceMask, const char *format, ...)
+{
+ char temp1[400];
+ char *temp = temp1;
+ va_list Next;
+ int len;
+
+ // Go ahead and trace...
+ va_start(Next, format);
+ len = _vsnprintf(temp, 380, format, Next);
+ va_end(Next);
+
+
+ if ((len < 0) || (len > 380))
+ {
+ len = strlen(temp);
+ }
+
+ if (len > 380)
+ {
+ temp[380] = 0;
+ len = 380;
+
+ }
+
+ if (temp[len - 1] >= ' ')
+ {
+ temp[len] = '\n';
+ temp[len + 1] = '\0';
+ }
+
+
+ printk("%s", temp);
+ return;
+}
+
+/*******************************************************************************
+**
+** Function GKI_init
+**
+** Description This function is called once at startup to initialize
+** all the timer structures.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_init(void)
+{
+ memset(&gki_cb, 0, sizeof(gki_cb));
+
+ gki_buffer_init();
+
+ spin_lock_init(&Lock);
+ gki_cb.IsRunning = TRUE;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_shutdown
+**
+** Description This function is called to shut down GKI
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_shutdown(void)
+{
+ int i;
+
+ if (!gki_cb.IsRunning)
+ return;
+
+ gki_cb.IsRunning = FALSE;
+
+#if (GKI_USE_DYNAMIC_BUFFERS == TRUE)
+
+ for (i = 0; i < GKI_NUM_TOTAL_BUF_POOLS; i++)
+ {
+ if (gki_cb.pool_buf_size[i])
+ GKI_delete_pool((UINT8)i);
+ }
+
+#endif
+
+}
+
+/*******************************************************************************
+**
+** Function GKI_enable
+**
+** Description This function enables interrupts.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_enable(void)
+{
+ spin_unlock_irqrestore(&Lock, Kirql);
+}
+
+/*******************************************************************************
+**
+** Function GKI_disable
+**
+** Description This function disables interrupts.
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_disable(void)
+{
+ volatile unsigned long tmp_irql;
+
+ spin_lock_irqsave(&Lock, tmp_irql);
+
+ // OK, we've acquired the spinlock. It means that
+ // the other guy has released it already and we can
+ // safely overwrite his saved irql...
+ Kirql = tmp_irql;
+}
+
+
+/*******************************************************************************
+**
+** Function GKI_exception
+**
+** Description This function throws an exception.
+** This is normally only called for a non recoverable error.
+**
+** Parameters: code - (input) The code for the error
+** msg - (input) The message that has to be logged
+**
+** Returns void
+**
+*******************************************************************************/
+void GKI_exception(UINT16 code, const char *msg, ...)
+{
+ char buff[MAX_EXCEPTION_MSGLEN];
+ va_list Next;
+ int len;
+
+ va_start(Next, msg);
+ len = vsnprintf(buff, MAX_EXCEPTION_MSGLEN - 1, msg, Next);
+ va_end(Next);
+
+ LogMsg(-1, "GKI_exception: Entry Code %d Message %s\n", code, buff);
+ GKI_disable();
+
+ if (gki_cb.ExceptionCnt < MAX_EXCEPTION)
+ {
+ EXCEPTION_T *pExp;
+
+ pExp = &gki_cb.Exception[gki_cb.ExceptionCnt++];
+ pExp->type = code;
+ pExp->taskid = 0;
+ strncpy((INT8 *)pExp->msg, msg, MAX_EXCEPTION_MSGLEN - 1);
+ }
+
+ GKI_enable();
+
+ LogMsg(-1, "GKI_Exception called with code: %d", code);
+
+ return;
+}
+
+
+/*******************************************************************************
+**
+** Function gki_reserve_os_memory
+**
+** Description This function allocates memory
+**
+** Parameters: size - (input) The size of the memory that has to be
+** allocated
+**
+** Returns the address of the memory allocated, or NULL if failed
+**
+** NOTE This function is NOT called by the Widcomm stack and
+** profiles. It is only called from within GKI if dynamic
+** buffer pools are used.
+**
+*******************************************************************************/
+void *gki_reserve_os_memory(UINT32 size)
+{
+ void *p;
+ p = kmalloc(size, GFP_ATOMIC);
+ if (p == NULL)
+ return NULL;
+ memset(p, 0x00, sizeof(*p));
+ return p;
+}
+
+/*******************************************************************************
+**
+** Function gki_release_os_memory
+**
+** Description This function frees memory
+**
+** Parameters: size - (input) The address of the memory that has to be
+** freed
+**
+** Returns void
+**
+** NOTE This function is NOT called by the Widcomm stack and
+** profiles. It is only called from within GKI if dynamic
+** buffer pools are used.
+**
+*******************************************************************************/
+void gki_release_os_memory(void *p_mem)
+{
+ kfree(p_mem);
+
+ return;
+}
+
+