btvoice: it works now.

Move TI audio code out of Blue/Z. It now runs as a
separate process, Blue/Z sends it messages containing
the BLE frame contents.

Move gfrm-voice-demo out of Blue/Z as well, we'll put it
next to the code which deals with the two types of remotes
with microphones (GFRM210 and GFRM100).

Handle TI firmware updates for GFRM210. We'll update the GP
handling when we know what those firmware updates will use as
their ID code.

Improve efficiency of handling audio data:
+ the remote always sends 102 bytes of audio data
  per Notification. Set the MTU larger when processing
  audio data, to allow the entire thing to be read at
  once and processed as a unit. Otherwise we tend to
  miss too much data and the quality isn't good.
+ add a g_attrib_get_mtu, to allow the MTU to be restored
  when we're done.

Change-Id: Ica55843d549c0c1a2c493de19eecd051f78de1c1
diff --git a/Makefile.plugins b/Makefile.plugins
index ec10695..78530ec 100644
--- a/Makefile.plugins
+++ b/Makefile.plugins
@@ -137,6 +137,4 @@
 builtin_sources += profiles/audioOverBle/main.c profiles/audioOverBle/manager.h \
 			profiles/audioOverBle/manager.c \
 			profiles/audioOverBle/btvoice.h \
-			profiles/audioOverBle/btvoice.c \
-			profiles/audioOverBle/RAS_lib.h \
-			profiles/audioOverBle/RAS_lib.c
+			profiles/audioOverBle/btvoice.c
diff --git a/Makefile.tools b/Makefile.tools
index 661d20b..af709b8 100644
--- a/Makefile.tools
+++ b/Makefile.tools
@@ -227,9 +227,6 @@
 tools_mpris_proxy_SOURCES = tools/mpris-proxy.c
 tools_mpris_proxy_LDADD = gdbus/libgdbus-internal.la @GLIB_LIBS@ @DBUS_LIBS@
 
-bin_PROGRAMS += tools/gfrm-voice-demo
-tools_gfrm_voice_demo_SOURCES = tools/gfrm-voice-demo.c
-
 dist_man_MANS += tools/hciattach.1 tools/hciconfig.1 \
 			tools/hcitool.1 tools/hcidump.1 \
 			tools/rfcomm.1 tools/rctest.1 tools/l2ping.1 \
diff --git a/attrib/gattrib.c b/attrib/gattrib.c
index e3d7d3d..6bb6e6d 100644
--- a/attrib/gattrib.c
+++ b/attrib/gattrib.c
@@ -455,6 +455,14 @@
 	return attrib->buf;
 }
 
+int g_attrib_get_mtu(GAttrib *attrib)
+{
+	if (!attrib)
+		return -1;
+
+	return bt_att_get_mtu(attrib->att);
+}
+
 gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu)
 {
 	if (!attrib)
diff --git a/attrib/gattrib.h b/attrib/gattrib.h
index 611f952..6cd3bf9 100644
--- a/attrib/gattrib.h
+++ b/attrib/gattrib.h
@@ -65,6 +65,7 @@
 				GDestroyNotify notify);
 
 uint8_t *g_attrib_get_buffer(GAttrib *attrib, size_t *len);
+int g_attrib_get_mtu(GAttrib *attrib);
 gboolean g_attrib_set_mtu(GAttrib *attrib, int mtu);
 
 gboolean g_attrib_unregister(GAttrib *attrib, guint id);
diff --git a/profiles/audioOverBle/RAS_lib.c b/profiles/audioOverBle/RAS_lib.c
deleted file mode 100755
index b4aed7e..0000000
--- a/profiles/audioOverBle/RAS_lib.c
+++ /dev/null
@@ -1,333 +0,0 @@
-/*
-* Copyright (c) [2015] Texas Instruments Incorporated
-*
-* All rights reserved not granted herein.
-* Limited License.
-*
-* Texas Instruments Incorporated grants a world-wide, royalty-free,
-* non-exclusive license under copyrights and patents it now or hereafter
-* owns or controls to make, have made, use, import, offer to sell and sell ("Utilize")
-* this software subject to the terms herein.  With respect to the foregoing patent
-*license, such license is granted  solely to the extent that any such patent is necessary
-* to Utilize the software alone.  The patent license shall not apply to any combinations which
-* include this software, other than combinations with devices manufactured by or for TI ("TI Devices").
-* No hardware patent is licensed hereunder.
-*
-* Redistributions must preserve existing copyright notices and reproduce this license (including the
-* above copyright notice and the disclaimer and (if applicable) source code license limitations below)
-* in the documentation and/or other materials provided with the distribution
-*
-* Redistribution and use in binary form, without modification, are permitted provided that the
-* following conditions are met:
-*
-*             * No reverse engineering, decompilation, or disassembly of this software is permitted
-*             	with respect to any software provided in binary form.
-*             * any redistribution and use are licensed by TI for use only with TI Devices.
-*             * Nothing shall obligate TI to provide you with source code for the software licensed
-*             	and provided to you in object code.
-*
-* If software source code is provided to you, modification and redistribution of the source code are
-* permitted provided that the following conditions are met:
-*
-*   * any redistribution and use of the source code, including any resulting derivative works, are
-*     licensed by TI for use only with TI Devices.
-*   * any redistribution and use of any object code compiled from the source code and any resulting
-*     derivative works, are licensed by TI for use only with TI Devices.
-*
-* Neither the name of Texas Instruments Incorporated nor the names of its suppliers may be used to
-* endorse or promote products derived from this software without specific prior written permission.
-*
-* DISCLAIMER.
-*
-* THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY
-* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-#ifdef HAVE_CONFIG_H
-#include <config.h>
-#endif
-#include "src/log.h"
-#include "RAS_lib.h"
-
-static int16 PV_Dec;
-static int8 SI_Dec;
-
-
-#define NULL	0
-#define PRED_CYPHER_CONST 0x3292
-#define STEP_CYPHER_CONST 0x5438
-
-#define HDR_NOT_SCRAMBLED 1
-
-
-static uint8 ras_pec_mode;
-static int16 per_buff[MAX_INPUT_BUF_SIZE*4];
-
-const uint16 codec_stepsize_Lut[89] =
-{
-  7,    8,    9,   10,   11,   12,   13,   14,
-  16,   17,   19,   21,   23,   25,   28,   31,
-  34,   37,   41,   45,   50,   55,   60,   66, 73,   80,   88,   97,  107,  118,  130,  143,
-  157,  173,  190,  209,  230,  253,  279,  307, 337,  371,  408,  449,  494,  544,  598,  658,
-  724,  796,  876,  963, 1060, 1166, 1282, 1411, 1552, 1707, 1878, 2066, 2272, 2499, 2749, 3024,
-  3327, 3660, 4026, 4428, 4871, 5358, 5894, 6484, 7132, 7845, 8630, 9493,10442,11487,12635,13899,
-  15289,16818,18500,20350,22385,24623,27086,29794, 32767
-};
-
-const int8 codec_IndexLut[16] =
-{
-  -1, -1, -1, -1, 2, 4, 6, 8,
-  -1, -1, -1, -1, 2, 4, 6, 8
-};
-
-
-/**************************************************************************************************
-*
-* @fn          codec_DecodeSingle
-*
-* @brief       This routine decode a 4bits ADPCM sample to a uin16 PCM audio sample.
-*
-* @param       uint8 a 4 bits ADPCM sample
-*
-*
-* @return      the 16 bits PCM samples.
-*/
-static int16 codec_DecodeSingle(uint8 codec_4bits)
-{
-  int16 step = codec_stepsize_Lut[SI_Dec];
-  int16 cum_diff  = step>>3;
-
-	// DBG("step %d cum_diff %d\n", step, cum_diff);
-
-  SI_Dec += codec_IndexLut[codec_4bits];
-  if(SI_Dec<0) SI_Dec = 0; else if(SI_Dec>88) SI_Dec = 88;
-
-  if(codec_4bits&4)
-     cum_diff += step;
-  if(codec_4bits&2)
-     cum_diff += step>>1;
-  if(codec_4bits&1)
-     cum_diff += step>>2;
-
-   if(codec_4bits&8)
-   {
-     if (PV_Dec < (-32767+cum_diff))
-       (PV_Dec) = -32767;
-     else
-       PV_Dec -= cum_diff;
-   }
-   else
-   {
-     if (PV_Dec > (0x7fff-cum_diff))
-       (PV_Dec) = 0x7fff;
-     else
-     PV_Dec += cum_diff;
-   }
-  return PV_Dec;
-}
-
-/**************************************************************************************************
- *
- * @fn          codec_DecodeBuff
- *
- * @brief       This routine encode a buffer with ADPCM IMA.
- *
- * @param       int16* dst  pointer to buffer where decoding result will be copy
- *              uint8* src  input buffer, size must be a multiple of 4 bytes
- *              srcSize     Number of byte that will be generated by the encoder (4* (src buffer size in byte))
- *
- *
- * @return      none
- */
-static void codec_DecodeBuff(int16* dst, uint8* src, unsigned int srcSize,  int8 *si, int16 *pv)
-{
-
-  // calculate pointers to iterate output buffer
-  int16* out = dst;
-  int16* end = out+(srcSize>>1);
-	int16 temp;
-
-  PV_Dec = *pv;
-  SI_Dec = *si;
-
-  while(out<end)
-  {
-     // get byte from src
-     uint8 codec = *src;
-	// DBG("codec %04x\n", codec);
-     // *out++ = codec_DecodeSingle((codec&0xF));  // decode value and store it
-     temp = codec_DecodeSingle((codec&0xF));  // decode value and store it
-		// DBG("from low %04x\n", temp);
-		*out++ = temp;
-     codec >>= 4;  // use high nibble of byte
-     codec &= 0xF;  // use high nibble of byte
-     // *out++ = codec_DecodeSingle(codec);  // decode value and store it
-     temp = codec_DecodeSingle((codec));  // decode value and store it
-		// DBG("from high %04x\n", temp);
-		*out++ = temp;
-     ++src;        // move on a byte for next sample
-  }
-
-  *pv = PV_Dec;
-  *si = SI_Dec;
-}
-
-
-/**************************************************************************************************
- *
- * @fn      RAS_Init
- *
- * @brief   RemoTI Audio Subsystem, initialization function
- *
- * input parameters
- *
- * @param   pec_mode:    	Packet Error concealment algorithm to apply:
- * 							RAS_NO_PEC(0): 		None (default)
- * 							RAS_PEC_MODE1(1): 	Replace lost packets by last valid.
- *
- * output parameters
- *codec_ima_DecodeBuff
- * None.
- *
- * @return      .
- * status.	0				SUCCESS
- * 			-1				ERROR: INVALID PARAMETER
- */
-uint8 RAS_Init( uint8 pec_mode )
-{
-	uint16 i;
-	if (pec_mode>RAS_PEC_MODE1) return -1;
-	ras_pec_mode = pec_mode;
-
-	for (i=0; i<(MAX_INPUT_BUF_SIZE*4);i++)
-		per_buff[i]=0;
-
-	return 0;
-}
-
-/**************************************************************************************************
- *
- * @fn      RAS_GetVersion
- *
- * @brief   RemoTI Audio Subsystem, retrieve software version
- *
- * input parameters
- *
- * none
- *
- * output parameters
- *
- * None.
- *
- * @return      .
- * Software Version.	MSB	 Major revision number
- *						LSB: Minor revision number
- */
-uint16 RAS_GetVersion( void )
-{
-	return RAS_SOFTWARE_VERSION;
-}
-/**************************************************************************************************
- *
- * @fn      RAS_Decode
- *
- * @brief   RemoTI Audio Subsystem, decoding function. decode encoded audioframe to PCM samples.
- *
- * input parameters
- *
- * @param   option:    		decoding option. can be pure decoding, or packet lot concealment algorithm:
- * 							RAS_PACKET_LOST(0)
- * 							RAS_DECODE(1)
- * @param   input: 			address of the buffer to decode, this buffer must include the 3 bytes header..
- *
- * @param   inputLength:  	length of the buffer to decode, excluding the 3 bytes header.
- * 							cannot be greater than 128 (MAX_INPUT_BUF_SIZE);
- *
- * output parameters
- *
- * @param   output:     	buffer where the decoded PCM will be written. This buffer must be allocated by the caller.
- * 							it must have a length of 4 times the inputLength variable
- *
- * @param   outputLenght:  	length of the decoded buffer.
- * 							max possible value 512 (4*MAX_INPUT_BUF_SIZE);
- *
- *
- * @return      .
- * status.	0				SUCCESS
- * 			-1				ERROR: INVALID PARAMETER
- *
- */
-uint8 RAS_Decode( uint8 option, uint8* input, uint16 inputLength, int16* output,uint16 *outputLenght )
-{
-    int8 step_index;
-    int16 predicted_value;
-    uint16 i;
-    static uint8 *rf_DataFrame;
-    *outputLenght = 0;
-
-	// DBG("RAS_Decode option %d input %04x inputLength %d output %04x outputLength %d\n", option, input, inputLength, output, outputLenght);
-
-    if ((output == NULL) || (inputLength > MAX_INPUT_BUF_SIZE)) return -1;
-
-#ifdef HDR_NOT_SCRAMBLED
-	predicted_value = (input [0] + ((input[1])<<8));
-    step_index = input [2] & 0xFF;
-#else
-    predicted_value = (int16)(((int16)((input[0])<<8))+((int16)(input [2] ))) ^ PRED_CYPHER_CONST;
-    step_index      = (input [1] & 0xFF) ^STEP_CYPHER_CONST;
-#endif
-
-    //extract Predicted value and step index from the header.
-    inputLength-=3;  //Remove Header Size
-    // check Option
-    switch(option)
-    {
-    	case RAS_PACKET_LOST:
-    	{
-    		switch (ras_pec_mode)
-    		{
-				case RAS_PEC_MODE1:
-					for (i=0; i<(inputLength*4);i++)
-						output[i] = per_buff[i];
-					break;
-		    	default:
-		    		break;
-    		}
-
-    	}
-    	break;
-
-    	case RAS_DECODE_TI_TYPE1:
-    	    if (input == NULL) return -1;
-    	    rf_DataFrame = input+3;
-    	    codec_DecodeBuff(output, rf_DataFrame, inputLength*4,  &step_index, &predicted_value);
-
-			//Save Frame for packet error concealment
-	   		switch (ras_pec_mode)
-			{
-				case RAS_PEC_MODE1:
-					for (i=0; i<(inputLength*4);i++)
-						per_buff[i] = output[i];
-					break;
-				default:
-					break;
-			}
-
-    		break;
-
-    	default:
-    		break;
-
-
-    }
-    *outputLenght = inputLength*4;
-    return 0;
-};
-
-
diff --git a/profiles/audioOverBle/RAS_lib.h b/profiles/audioOverBle/RAS_lib.h
deleted file mode 100755
index e009902..0000000
--- a/profiles/audioOverBle/RAS_lib.h
+++ /dev/null
@@ -1,195 +0,0 @@
-/*
-* Copyright (c) [2015] Texas Instruments Incorporated
-*
-* All rights reserved not granted herein.
-* Limited License.
-*
-* Texas Instruments Incorporated grants a world-wide, royalty-free,
-* non-exclusive license under copyrights and patents it now or hereafter
-* owns or controls to make, have made, use, import, offer to sell and sell ("Utilize")
-* this software subject to the terms herein.  With respect to the foregoing patent
-*license, such license is granted  solely to the extent that any such patent is necessary
-* to Utilize the software alone.  The patent license shall not apply to any combinations which
-* include this software, other than combinations with devices manufactured by or for TI ("TI Devices").
-* No hardware patent is licensed hereunder.
-*
-* Redistributions must preserve existing copyright notices and reproduce this license (including the
-* above copyright notice and the disclaimer and (if applicable) source code license limitations below)
-* in the documentation and/or other materials provided with the distribution
-*
-* Redistribution and use in binary form, without modification, are permitted provided that the
-* following conditions are met:
-*
-*             * No reverse engineering, decompilation, or disassembly of this software is permitted
-*             	with respect to any software provided in binary form.
-*             * any redistribution and use are licensed by TI for use only with TI Devices.
-*             * Nothing shall obligate TI to provide you with source code for the software licensed
-*             	and provided to you in object code.
-*
-* If software source code is provided to you, modification and redistribution of the source code are
-* permitted provided that the following conditions are met:
-*
-*   * any redistribution and use of the source code, including any resulting derivative works, are
-*     licensed by TI for use only with TI Devices.
-*   * any redistribution and use of any object code compiled from the source code and any resulting
-*     derivative works, are licensed by TI for use only with TI Devices.
-*
-* Neither the name of Texas Instruments Incorporated nor the names of its suppliers may be used to
-* endorse or promote products derived from this software without specific prior written permission.
-*
-* DISCLAIMER.
-*
-* THIS SOFTWARE IS PROVIDED BY TI AND TI'S LICENSORS "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES,
-* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A
-* PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL TI AND TI'S LICENSORS BE LIABLE FOR ANY
-* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
-* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
-* BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
-* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
-* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
-*/
-
-
-#ifndef RSA_LIB_H
-#define RSA_LIB_H
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-
-#if !defined PACK_1
-#define PACK_1
-#endif
-
-
-#if defined(_MSC_VER) || defined(unix) || (defined(__ICC430__) && (__ICC430__==1))
-#pragma pack(1)
-#endif
-
-
-/////////////////////////////////////////////////////////////////////////////
-// Defines
-
-#define MAX_INPUT_BUF_SIZE 		128
-
-#define RAS_PACKET_LOST 		0
-#define RAS_DECODE_TI_TYPE1		1
-
-#define RAS_NO_PEC		   		0
-#define RAS_PEC_MODE1   		1
-
-//RAS Software Version: v1.3
-#define RAS_SOFTWARE_VERSION	0x0103
-/////////////////////////////////////////////////////////////////////////////
-// Typedefs
-#ifndef int8
-typedef signed   char   int8;
-#endif
-
-#ifndef uint8
-typedef unsigned char   uint8;
-#endif
-
-#ifndef int16
-typedef signed   short  int16;
-#endif
-
-#ifndef uint16
-typedef unsigned short  uint16;
-#endif
-
-#ifndef int32
-typedef signed   int  int32;
-#endif
-
-#ifndef uint32
-typedef unsigned int  uint32;
-#endif
-
-/////////////////////////////////////////////////////////////////////////////
-// Global variable
-
-
-/////////////////////////////////////////////////////////////////////////////
-// Function declarations
-/**************************************************************************************************
- *
- * @fn      RAS_GetVersion
- *
- * @brief   RemoTI Audio Subsystem, retrieve software version
- *
- * input parameters
- *
- * none
- *
- * output parameters
- *
- * None.
- *
- * @return      .
- * Software Version.	MSB	 Major revision number
- *						LSB: Minor revision number
- */
-uint16 RAS_GetVersion( void );
-
-/**************************************************************************************************
- *
- * @fn      RAS_Init
- *
- * @brief   RemoTI Audio Subsystem, initialization function
- *
- * input parameters
- *
- * @param   pec_mode:    	Packet Error concealment algorithm to apply:
- * 							RAS_NO_PEC(0): 		None (default)
- * 							RAS_PEC_MODE1(1): 	Replace lost packets by last valid.
- *
- * output parameters
- *
- * None.
- *
- * @return      .
- * status.	0				SUCCESS
- * 			-1				ERROR: INVALID PARAMETER
- */
-uint8 RAS_Init( uint8 pec_mode );
-
-
-/**************************************************************************************************
- *
- * @fn      RAS_Decode
- *
- * @brief   RemoTI Audio Subsystem, decoding function. decode encoded audioframe to PCM samples.
- *
- * input parameters
- *
- * @param   option:    		decoding option. can be pure decoding, or packet lot concealment algorithm:
- * 							RAS_PACKET_LOST(0)
- * 							RAS_DECODE(1)
- * @param   input: 			address of the buffer to decode, this buffer must include the 3 bytes header..
- *
- * @param   inputLenght:  	length of the buffer to decode, excluding the 3 bytes header.
- * 							cannot be greater than 128 (MAX_INPUT_BUF_SIZE);
- *
- * output parameters
- *
- * @param   output:     	buffer where the decoded PCM will be written. This buffer must be allocated by the caller.
- * 							it must have a length of 4 times the inputLength variable
- *
- * @param   outputLenght:  	length of the decoded buffer.
- * 							max possible value 512 (4*MAX_INPUT_BUF_SIZE);
- *
- *
- * @return      .
- * status.	0				SUCCESS
- * 			-1				ERROR: INVALID PARAMETER
- *
- */
-uint8 RAS_Decode( uint8 option, uint8* input, uint16 inputLenght, int16* output,uint16 *outputLenght );
-
-#ifdef __cplusplus
-}
-#endif
-
-#endif // RSA_LIB_H
diff --git a/profiles/audioOverBle/btvoice.c b/profiles/audioOverBle/btvoice.c
index 27ebeda..fd90b63 100644
--- a/profiles/audioOverBle/btvoice.c
+++ b/profiles/audioOverBle/btvoice.c
@@ -4,7 +4,7 @@
  *
  *  Copyright (C) 2011  Nokia Corporation
  *  Copyright (C) 2011  Marcel Holtmann <marcel@holtmann.org>
- *
+ *  Copyright (C) 2016  Google Fiber
  *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
@@ -35,6 +35,7 @@
 #include <stdint.h>
 #include <stdio.h>
 #include <stdlib.h>
+#include <sys/un.h>
 #include <sys/stat.h>
 
 #include <glib.h>
@@ -60,16 +61,13 @@
 
 #include "btvoice.h"
 
-#include "RAS_lib.h"
-
 #define AUD_START_UUID 0xFFF1
 #define AUD_CONFIG_UUID 0xFFF2
 #define AUD_STREAM_UUID 0xFFF4
 
-static pthread_mutex_t audio_mutex = PTHREAD_MUTEX_INITIALIZER;
-
 struct btvoice_device {
   uint16_t id;
+  bdaddr_t bdaddr;
   struct btd_device *device;
   GAttrib *attrib;
   guint attioid;
@@ -199,121 +197,70 @@
   }
 }
 
-#define RAS_START_CMD    0x04
-#define RAS_DATA_TIC1_CMD  0x01
-#define RAS_STOP_CMD    0x02
-#define RAS_DATA_RAW_CMD  0x03
 #define RAS_END_CMD      0x00
+#define TI_AUDIO_PATH "\0rc_audio_ti"
 
 static void audio_value_cb(const uint8_t *pdu, uint16_t len,
                            gpointer user_data)
 {
-  static int PrevSeqNum = 0;
-  static int nbFrameLost, nbFrameReceived;
-  static int starting_sync = 0;
-  static uint8_t SeqNum;
-  uint8_t frameType;
-  static char state;
-  int16_t writebuf[1024];
-  uint16 to_write;
-  uint16_t libVersion;
-  int wrote;
-  int fp;
-  const struct sigaction ignore = { .sa_handler = SIG_IGN, };
+  struct audiostream *audiostream = user_data;
+  struct btvoice_device *btvoicedev = audiostream->btvoicedev;
+  static int audio_fd = -1;
+  static uint16_t old_mtu;
+  static int sent = 0, dropped = 0;
 
-  if (sigaction(SIGPIPE, &ignore, NULL) != 0) {
-    perror("sigaction:");
-  }
+  if (audio_fd == -1) {
+    struct sockaddr_un sun;
 
-  pthread_mutex_lock(&audio_mutex);
-  fp = open(FIFO_BTD2AUDIO_FILE, O_WRONLY);
+    memset(&sun, 0, sizeof(sun));
+    sun.sun_family = AF_UNIX;
+    snprintf(sun.sun_path, sizeof(sun.sun_path), "%s", TI_AUDIO_PATH);
 
-  if (fp != -1) {
-    switch (len) {
-      case 4:
-        switch (pdu[3]) {
-          case RAS_DATA_TIC1_CMD:
-            break;
-
-          case RAS_START_CMD:
-            state = 0;
-            PrevSeqNum = 0;
-            starting_sync = 1;
-
-            libVersion = RAS_GetVersion();
-            DBG("Library version: %d.%d\n", (libVersion & 0xFF00) >> 8, libVersion & 0x00FF);
-            RAS_Init(RAS_PEC_MODE1);
-            break;
-
-          case RAS_END_CMD:
-            break;
-        }
-        break;
-
-      case 23:
-        switch (state) {
-          case 0:
-            SeqNum = ((pdu[3] >> 3) & 0x1f);
-            DBG("SeqNum %d PrevSeqNum %d", SeqNum, PrevSeqNum);
-
-            if (SeqNum != (0x1f & (PrevSeqNum + 1))) {
-              DBG("missed %d SeqNum", SeqNum - PrevSeqNum - 1);
-
-              if (starting_sync) {
-                DBG("throwing it away");
-                break;
-              }
-            } else {
-              starting_sync = 0;
-            }
-
-            PrevSeqNum = SeqNum;
-            // nobreak;
-
-          case 1:
-          case 2:
-          case 3:
-            RAS_Decode(RAS_DECODE_TI_TYPE1, (uint8 *)&pdu[4], len - 4, writebuf, &to_write);
-            wrote = write(fp, writebuf, to_write);
-            state++;
-            break;
-
-          case 4:
-            RAS_Decode(RAS_DECODE_TI_TYPE1, (uint8 *)&pdu[4], len - 4, writebuf, &to_write);
-            wrote = write(fp, writebuf, to_write);
-            state = 0;
-            break;
-        }
-        break;
-
-      case 103:
-        SeqNum = ((pdu[3] >> 3) & 0x1f);
-        DBG("SeqNum %d PrevSeqNum %d", SeqNum, PrevSeqNum);
-
-        if (SeqNum != (0x1f & (PrevSeqNum + 1))) {
-          DBG("missed %d SeqNum", SeqNum - PrevSeqNum - 1);
-
-          if (starting_sync) {
-            DBG("throwing it away");
-            break;
-          }
-        } else {
-          starting_sync = 0;
-        }
-
-        PrevSeqNum = SeqNum;
-        RAS_Decode(RAS_DECODE_TI_TYPE1, (uint8 *)&pdu[4],
-            len - 4, writebuf, &to_write);
-        wrote = write(fp, writebuf, to_write);
-        break;
+    audio_fd = socket(AF_UNIX, SOCK_CLOEXEC | SOCK_NONBLOCK | SOCK_DGRAM, 0);
+    if (connect(audio_fd, (const struct sockaddr *) &sun, sizeof(sun)) < 0) {
+      perror("connect(AF_UNIX, TI_AUDIO_PATH)");
+      close(audio_fd);
+      audio_fd = -1;
+      dropped++;
+      return;
     }
 
-    close(fp);
-  } else {
-    DBG("can't open the pipe: %s", FIFO_BTD2AUDIO_FILE);
+    /* Remote sends 103 byte notifications, plus metadata. */
+    old_mtu = g_attrib_get_mtu(btvoicedev->attrib);
+    g_attrib_set_mtu(btvoicedev->attrib, 105);
   }
 
-  pthread_mutex_unlock(&audio_mutex);
+  if (audio_fd != -1) {
+    if (len == 4 && pdu[3] == RAS_END_CMD) {
+      close(audio_fd);
+      audio_fd = -1;
+      g_attrib_set_mtu(btvoicedev->attrib, old_mtu);
+      DBG("Finished audio stream; sent = %d dropped = %d\n", sent, dropped);
+      sent = dropped = 0;
+    } else {
+      struct iovec iov[3];
+      struct msghdr mh;
+      uint8_t remote_type = 0;  /* GFRM210 */
+
+      memset(&iov, 0, sizeof(iov));
+      iov[0].iov_base = &btvoicedev->bdaddr;
+      iov[0].iov_len = sizeof(btvoicedev->bdaddr);
+      iov[1].iov_base = (void *)&remote_type;
+      iov[1].iov_len = 1;
+      iov[2].iov_base = (void *)(pdu + 3);  /* Skip 3 bytes of BLE header */
+      iov[2].iov_len = len - 3;
+
+      memset(&mh, 0, sizeof(mh));
+      mh.msg_iov = iov;
+      mh.msg_iovlen = 3;
+
+      if (sendmsg(audio_fd, &mh, MSG_DONTWAIT) >= 0) {
+        sent++;
+      } else {
+        dropped++;
+      }
+    }
+  }
 }
 
 static void audio_ccc_written_cb(guint8 status, const guint8 *pdu, guint16 plen,
@@ -535,6 +482,7 @@
     struct btd_device *device)
 {
   struct btvoice_device *btvoicedev;
+  const bdaddr_t *bdaddr = device_get_address(device);
 
   btvoicedev = find_btvoicedev(device);
   if (btvoicedev != NULL) return btvoicedev;
@@ -543,6 +491,7 @@
   if (!btvoicedev) return NULL;
 
   btvoicedev->device = btd_device_ref(device);
+  btvoicedev->bdaddr = *bdaddr;
 
   btvoicedevices = g_slist_append(btvoicedevices, btvoicedev);
 
@@ -576,15 +525,6 @@
 
   update_btvoicedevice(btvoicedev);
 
-  // Create Pipe for audio data exchange
-  if (access(FIFO_BTD2AUDIO_FILE, F_OK) == -1) {
-    int res = mkfifo(FIFO_BTD2AUDIO_FILE, 0666);
-    if (res != 0) {
-      DBG("Could not create fifo %s\n", FIFO_BTD2AUDIO_FILE);
-      exit(1);
-    }
-  }
-
   return 0;
 }
 
diff --git a/profiles/audioOverBle/btvoice.h b/profiles/audioOverBle/btvoice.h
index 8a9b259..0cddfe3 100644
--- a/profiles/audioOverBle/btvoice.h
+++ b/profiles/audioOverBle/btvoice.h
@@ -25,8 +25,6 @@
 #ifndef BTVOICE_H_
 #define BTVOICE_H_
 
-#define FIFO_BTD2AUDIO_FILE "/tmp/rcu_audio_pcm"
-
 struct btvoiceenable {
 	gboolean audioOverBle;
 	int	 mode;
diff --git a/profiles/audioOverBle/main.c b/profiles/audioOverBle/main.c
index a837a8f..4b44cbd 100644
--- a/profiles/audioOverBle/main.c
+++ b/profiles/audioOverBle/main.c
@@ -59,15 +59,10 @@
 
 static int audioOverBle_init(void)
 {
-	DBG("In");
 	config = open_config_file(CONFIGDIR "/audioOverBle.conf");
-
-	DBG("Config dir: %s", CONFIGDIR);
-
 	if (audioOverBle_manager_init(config) < 0)
 		return -EIO;
 
-	DBG("Out");
 	return 0;
 }
 
diff --git a/profiles/oad/oad.c b/profiles/oad/oad.c
index 8348431..3f481a3 100644
--- a/profiles/oad/oad.c
+++ b/profiles/oad/oad.c
@@ -376,9 +376,21 @@
 	uint16_t version = get_le16(header + 2);
 	uint32_t size = get_le32(header+4) & 0x00ffffff;
 	int id = header[7];
-	enum OAD_FirmwareType type = id == 'T' ? OADFW_TI : id == 'G' ? OADFW_GP : OADFW_Unknown;
+	enum OAD_FirmwareType type;
 	int index = (int)type;
 
+	switch(id) {
+	case 'T':
+	case 'U':
+		type = OADFW_TI;
+		break;
+	case 'G':
+		type = OADFW_GP;
+		break;
+	default:
+		type = OADFW_Unknown;
+		break;
+	}
 	if (type == OADFW_Unknown) {
 		error("OAD unknown firmware id '%c': file=%s version=%d.%d",
 			id, file, OAD_MAJOR_VERSION(version), OAD_MINOR_VERSION(version));
diff --git a/tools/gfrm-voice-demo.c b/tools/gfrm-voice-demo.c
deleted file mode 100644
index d40a954..0000000
--- a/tools/gfrm-voice-demo.c
+++ /dev/null
@@ -1,132 +0,0 @@
-#define _BSD_SOURCE
-#include <endian.h>
-#include <fcntl.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <sys/stat.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-typedef struct WAV_hdr
-{
-  uint32_t chunk_id;
-  uint32_t chunk_size;
-  uint32_t format;
-
-  uint32_t subchunk1_id;
-  uint32_t subchunk1_size;
-  uint16_t audio_format;
-  uint16_t num_channels;
-  uint32_t sample_rate;
-  uint32_t byte_rate;
-  uint16_t block_align;
-  uint16_t bits_per_sample;
-
-  uint32_t subchunk2_id;
-  uint32_t subchunk2_size;
-} WAV_hdr_t;
-
-
-static int usage(const char *progname)
-{
-  fprintf(stderr, "usage: %s [-f outfile]\n, where:", progname);
-  fprintf(stderr, "\t-f outfile: file to write audio to in WAV format.\n");
-  exit(1);
-}
-
-
-int main(int argc, char **argv)
-{
-  mode_t mode = S_IRUSR|S_IWUSR|S_IRGRP|S_IWGRP;
-  int fd;
-  const char *outfile = "/tmp/audio.wav";
-  int outfd;
-  uint8_t buf[8192];
-  WAV_hdr_t hdr;
-  ssize_t len, totlen=0;
-  int num_no_data = -1;
-  int c;
-
-  memset(buf, 0, sizeof(buf));
-  memset(&hdr, 0, sizeof(hdr));
-
-  while ((c = getopt(argc, argv, "f:")) != -1) {
-    switch (c) {
-      case 'f':
-        outfile = optarg;
-        break;
-      default:
-        usage(argv[0]);
-        break;
-    }
-  }
-
-  if ((fd = open("/tmp/rcu_audio_pcm", O_RDONLY)) < 0) {
-    perror("open /tmp/rcu_audio_pcm");
-    exit(1);
-  }
-
-  if ((outfd = open(outfile, O_RDWR|O_CREAT|O_TRUNC, mode)) < 0) {
-    fprintf(stderr, "Unable to open %s for writing.\n", outfile);
-    exit(1);
-  }
-
-  if ((len = write(outfd, &hdr, sizeof(WAV_hdr_t))) != sizeof(WAV_hdr_t)) {
-    fprintf(stderr, "Incorrect size for WAV header: %zd != %zd\n",
-      len, sizeof(WAV_hdr_t));
-    exit(1);
-  }
-
-  while (1) {
-    len = read(fd, buf, sizeof(buf));
-    if (len > 0) {
-      totlen += len;
-      if (write(outfd, buf, len) != len) {
-        fprintf(stderr, "short write!\n");
-        exit(1);
-      }
-      num_no_data = 0;
-    } else if (len < 0) {
-      perror("read");
-      exit(1);
-    } else if (len == 0) {
-      if (num_no_data >= 5) {
-        break;
-      }
-      sleep(1);
-      if (num_no_data >= 0) {
-        num_no_data++;
-      }
-    }
-  }
-
-  lseek(outfd, 0, SEEK_SET);
-
-  #define BITS_PER_SAMPLE 16
-  #define SAMPLES_PER_SECOND  16000
-  /* http://soundfile.sapp.org/doc/WaveFormat/ */
-  hdr.chunk_id = htole32(0x46464952);  // "RIFF"
-  hdr.chunk_size = htole32(36 + totlen);
-  hdr.format = htole32(0x45564157);  // "WAVE"
-
-  hdr.subchunk1_id = htole32(0x20746d66);  // "fmt "
-  hdr.subchunk1_size = htole32(16);
-  hdr.audio_format = htole16(1);
-  hdr.num_channels = htole16(1);
-  hdr.sample_rate = htole32(SAMPLES_PER_SECOND);
-  hdr.byte_rate = htole32(SAMPLES_PER_SECOND * 1 * BITS_PER_SAMPLE/8);
-  hdr.block_align = htole16(1 * BITS_PER_SAMPLE/8);
-  hdr.bits_per_sample = htole16(BITS_PER_SAMPLE);
-
-  hdr.subchunk2_id = htole32(0x61746164);  // "data"
-  hdr.subchunk2_size = htole32(totlen);
-  if ((len = write(outfd, &hdr, sizeof(WAV_hdr_t))) != sizeof(WAV_hdr_t)) {
-    fprintf(stderr, "Incorrect size for WAV header: %zd != %zd\n",
-      len, sizeof(WAV_hdr_t));
-    exit(1);
-  }
-
-  exit(0);
-}