Import fastrpc code from upstream am: d6d6e3bba2 am: 3b85c51d27
am: 3704a6f17f

Change-Id: Id8410063d6653b065041b3807aec53cf83391636
diff --git a/Makefile b/Makefile
new file mode 100644
index 0000000..8251c58
--- /dev/null
+++ b/Makefile
@@ -0,0 +1,84 @@
+
+CFLAGS = -fno-short-enums -U_DEBUG -DARM_ARCH_7A -DLE_ENABLE -DUSE_SYSLOG -Iinc -Isrc -DDEFAULT_DOMAIN_ID=3
+LDFLAGS = -fPIC -pie -Wl,--version-script=src/symbols.lst -ldl -lpthread -lm
+
+
+
+prefix := /usr/local
+bindir := $(prefix)/bin
+libdir := $(prefix)/lib
+
+
+LIBADSPRPC_SRC_FILES := src/fastrpc_apps_user.c \
+		src/remotectl_stub.c \
+		src/listener_android.c \
+		src/adsp_current_process_stub.c \
+		src/adsp_current_process1_stub.c \
+		src/apps_std_skel.c \
+		src/apps_std_imp.c \
+		src/apps_mem_imp.c \
+		src/apps_mem_skel.c \
+		src/rpcmem_android.c \
+		src/apps_remotectl_skel.c \
+		src/std.c \
+		src/std_path.c \
+		src/std_mem.c \
+		src/std_dtoa.c \
+		src/std_strlprintf.c \
+		src/BufBound.c \
+		src/std_SwapBytes.c \
+		src/smath.c \
+		src/atomic.c \
+		src/cae.c \
+		src/adspmsgd_apps_skel.c \
+		src/adspmsgd_adsp_stub.c \
+		src/adspmsgd_adsp1_stub.c \
+		src/adspmsgd_apps.c \
+		src/platform_libs.c \
+		src/pl_list.c \
+		src/log_config.c \
+		src/gpls.c \
+		src/adsp_perf_stub.c \
+		src/fastrpc_perf.c \
+		src/mod_table.c
+
+LIBADSPRPC_OBJ := $(LIBADSPRPC_SRC_FILES:.c=.o)
+
+LIBDEFAULT_LISTENER_SRC_FILES := src/adsp_default_listener.c \
+				src/adsp_default_listener_stub.c \
+				src/std.c \
+				src/std_mem.c
+
+LIBDEFAULT_LISTENER_OBJ := $(LIBDEFAULT_LISTENER_SRC_FILES:.c=.o)
+
+ADSPRPCD_SRC_FILES := src/cdsprpcd.c
+
+ADSPRPCD_OBJ := $(ADSPRPCD_SRC_FILES:.c=.o)
+
+%.o: %.c
+	$(CC) -fpic -pie $(CFLAGS) -c $< -o $@
+
+cdsprpcd: $(ADSPRPCD_OBJ) libcdsp_default_listener.so
+	echo $(LD) -fpic -pie $(LDFLAGS) -o cdsprpcd
+	$(CC) -fpic -pie -fPIC -pie -Wl,--version-script=src/symbols.lst -ldl -lpthread -lm $(ADSPRPCD_OBJ) -o cdsprpcd -lcdsp_default_listener -L.
+	echo "cdsprpcd built successfully"
+
+LDFLAGS = -fPIC -pie -Wl,--version-script=src/symbols.lst -shared -ldl -lpthread -lm    
+    
+libcdsp_default_listener.so: $(LIBDEFAULT_LISTENER_OBJ) libcdsprpc.so
+	echo $(LD) -fpic -pie -shared $(LDFLAGS) -o libcdsp_default_listener.so
+	$(CC) -fpic -pie -shared -fPIC -pie -Wl,--version-script=src/adsp_def_symbols.lst -ldl -lpthread -lm $(LIBDEFAULT_LISTENER_OBJ) -o libcdsp_default_listener.so -lcdsprpc -L.
+	echo "libcdsp_default_listener built successfully"
+
+libcdsprpc.so: $(LIBADSPRPC_OBJ)
+	echo $(LD) -fpic -pie -shared $(LDFLAGS) -o libcdsprpc.so
+	$(CC) -fpic -pie -shared $(LDFLAGS) $(LIBADSPRPC_OBJ) -o libcdsprpc.so
+	echo "libcdsprpc built successfully"
+
+all: libcdsprpc.so libcdsp_default_listener.so cdsprpcd
+	echo "All binaries built"
+
+install: libcdsprpc.so libcdsp_default_listener.so cdsprpcd
+	@install -D -m 755 libcdsprpc.so $(DESTDIR)$(libdir)/libcdsprpc.so
+	@install -D -m 755 libcdsp_default_listener.so $(DESTDIR)$(libdir)/libcdsp_default_listener.so
+	@install -D -m 755 cdsprpcd $(DESTDIR)$(bindir)/cdsprpcd
\ No newline at end of file
diff --git a/inc/AEEBufBound.h b/inc/AEEBufBound.h
new file mode 100644
index 0000000..583844c
--- /dev/null
+++ b/inc/AEEBufBound.h
@@ -0,0 +1,567 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 AEEBUFBOUND_H
+#define AEEBUFBOUND_H
+/*==============================================================================
+
+FILE:  AEEBufBound.h
+
+SERVICES:
+        BufBound APIs
+
+GENERAL DESCRIPTION:
+        BufBound provides a "bounded buffer" API that facilitates
+          measuring strings or character output.  It's design accomodates
+          the implementation of functions that can have the same exact logic
+          for measuring and outputting char buffer content.
+
+REVISION HISTORY:
+        Fri Aug 08 17:38:29 2003: Created
+
+==============================================================================*/
+
+typedef struct BufBound
+{
+   char* pcBuf;   /* original buffer */
+   char* pcWrite; /* write pointer */
+   char* pcEnd;   /* first illegal write pointer */
+} BufBound;
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* #ifdef __cplusplus */
+
+extern void BufBound_Init(BufBound *me, char *pBuf, int nLen);
+extern void BufBound_Write(BufBound *me, const char *pc, int nLen);
+extern void BufBound_Putc(BufBound *me, char c);
+extern void BufBound_Putnc(BufBound *me, char c, int nCount);
+extern void BufBound_ForceNullTerm(BufBound *me);
+extern void BufBound_Puts(BufBound *me, const char* cpsz);
+extern void BufBound_Advance(BufBound *me, int nLen);
+extern void BufBound_WriteLE(BufBound* me,
+                             const void *pvSrc, int nSrcSize,
+                             const char *pszFields);
+extern void BufBound_WriteBE(BufBound* me,
+                             const void *pvSrc, int nSrcSize,
+                             const char *pszFields);
+extern int BufBound_BufSize(BufBound *me);
+extern int BufBound_Left(BufBound* me);
+extern int BufBound_ReallyWrote(BufBound* me);
+extern int BufBound_Wrote(BufBound* me);
+
+static __inline int BufBound_IsFull(BufBound* me)
+{
+   return (BufBound_Left(me) <= 0);
+}
+
+// Deprecated:
+static __inline int BufBound_IsCounter(BufBound* me)
+{
+   return BufBound_BufSize(me) == 0;
+}
+
+#ifdef __cplusplus
+}
+#endif /* #ifdef __cplusplus */
+
+
+/*=====================================================================
+=======================================================================
+DATA STRUCTURE DOCUMENTATION
+=======================================================================
+
+BufBound
+
+Description:
+   An BufBound keeps track of whether appending to a bounded buffer
+    has overflowed.
+
+Definition:
+   typedef struct BufBound
+   {
+      char* pcBuf;
+      char* pcWrite;
+      char* pcEnd;
+   } BufBound;
+
+Members:
+      pcBuf: original start pointer
+      pcWrite: current write location
+      pcEnd: first illegal write position
+
+See Also:
+      BufBound Interface
+
+=======================================================================
+INTERFACE DOCUMENTATION
+=======================================================================
+BufBound Interface
+
+  BufBound is a statically-linked interface.
+
+  BufBound provides functions for safely appending to a character buffer.  On
+  initialization, the buffer start address and size are provided.  Subsequent
+  write operations are checked against the buffer bounds.
+
+  Once the buffer bounds are exceeded, no bytes will be written but the
+  BufBound will continue to increment its internal "write pointer" to reflect
+  the number of bytes that would have been written (had the bounds not been
+  exceeded).
+
+  When initialized with a buffer size of zero, a BufBound simply counts the
+  number of bytes that would be required to contain the result.  This design
+  accommodates implementations that use the same logic for generating output
+  and measuring the space required for generated output.
+
+  BufBound protects clients from numerical overflow by limiting the write
+  pointer to a maximum offset of INT_MAX from the start of the buffer.
+  Functions that write data into the buffer safely ignore negative size inputs
+  (Write and Putnc).
+
+=======================================================================
+BufBound_Init()
+
+Description:
+   initialize a BufBound for appending to a buffer
+
+Prototype:
+
+   void BufBound_Init(BufBound *me, char *pBuf, int nLen);
+
+Parameters:
+   me: the BufBound
+   pBuf: the bounded buffer
+   nLen: size of pBuf, in bytes
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+BufBound_Write()
+
+Description:
+   Appends some number of bytes to a BufBound, if possible.
+
+   When a negative size is passed, it is safely treated as zero.
+
+Prototype:
+
+   void BufBound_Write(BufBound *me, const char *pc, int nLen);
+
+Parameters:
+   me: the BufBound
+   pc: pointer to bytes to append
+   int nLen: number of bytes to write
+
+Return Value:
+   None
+
+Comments:
+   If the BufBound has overflowed, no bytes are written, but pcWrite is
+      *always* advanced by nLen.
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+BufBound_Advance()
+
+Description:
+
+   Moves the write pointer.  Advance is like a relative seek operation.  It
+   does not change the contents of the buffer, so when using a forward seek
+   (positive advance) be careful of advancing over uninitialized data.
+
+   Negative numbers will decrease the write pointer down to 0 (the start of
+   the buffer) and not below.  Positive numbers will increase the write
+   pointer up to offset INT_MAX and not beyond.
+
+Prototype:
+
+   void BufBound_Advance(BufBound *me, int nDelta);
+
+Parameters:
+   me: the BufBound
+   int nLen: number of bytes to advance
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+BufBound_Putc()
+
+Description:
+   Appends one byte to a BufBound, if possible.
+
+Prototype:
+
+   void BufBound_Putc(BufBound *me, char c);
+
+Parameters:
+   me: the BufBound
+   c: the byte
+
+Return Value:
+   None
+
+Comments:
+   If the BufBound has overflowed, no byte is written, but pcWrite is
+      *always* advanced by 1.
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_Putnc()
+
+Description:
+   Appends a byte to a BufBound repeatedly.
+
+   When a negative size is passed, it is safely treated as zero.
+
+Prototype:
+
+   void BufBound_Putnc(BufBound *me, char c, int nCount);
+
+Parameters:
+   me: the BufBound
+   c: the byte
+   nCount: number of times to append c
+
+Return Value:
+   None
+
+Comments:
+   If the BufBound has overflowed, no byte is written, but pcWrite is
+      *always* advanced by nCount.
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_ForceNullTerm()
+
+Description:
+   Appends a null terminating character to a BufBound, if possible.
+     If the BufBound has overflowed, the last legal location is
+     set to '\0'.
+
+Prototype:
+   void BufBound_ForceNullTerm(BufBound *me);
+
+Parameters:
+   me: the BufBound
+
+Return Value:
+   None
+
+Comments:
+   pcWrite is *always* advanced by 1.
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_Puts()
+
+Description:
+   Appends a null-terminated string to a BufBound, if possible
+
+Prototype:
+
+   void BufBound_Puts(BufBound *me, const char* cpsz);
+
+Parameters:
+   me: the BufBound
+   cpsz: the string to append
+
+Return Value:
+
+Comments:
+   If the BufBound has overflowed, no bytes are written, but pcWrite is
+      *always* advanced by strlen(cpsz).
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_BufSize()
+
+Description:
+   Returns the size of the buffer owned by the BufBound.  This is
+   the same as the number passed to BufBound_Init (MAXed with zero).
+
+Prototype:
+
+   int BufBound_IsCounter(BufBound* me);
+
+Parameters:
+   me: the BufBound
+
+Return Value:
+   1 if the BufBound is a counter, 0 otherwise
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_Left()
+
+Description:
+   Returns the number of bytes the BufBound can still accomodate,
+   without overflowing.  If overflow has occurred, it will return
+   a negative number.
+
+Prototype:
+
+   int BufBound_Left(BufBound* me);
+
+Parameters:
+    me: the BufBound
+
+Return Value:
+   The number of bytes the BufBound can still accomodate,
+     without overflowing.
+
+Comments:
+   The return value may be negative, if overflow has already occurred.
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_ReallyWrote()
+
+Description:
+   Returns the number of bytes actually written to the BufBound,
+     not including any overflow.
+
+Prototype:
+
+   int BufBound_ReallyWrote(BufBound* me);
+
+Parameters:
+    me: the BufBound
+
+Return Value:
+   The number of bytes actually written to the BufBound,
+     not including any overflow.
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_Wrote()
+
+Description:
+
+   Returns the number of bytes written to the BufBound, including any
+   overflow, up to INT_MAX.
+
+Prototype:
+
+   int BufBound_Wrote(BufBound* me);
+
+Parameters:
+    me: the BufBound
+
+Return Value:
+
+   The number of bytes written to the BufBound, including any overflow.
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+BufBound_IsFull()
+
+Description:
+   Tests whether an AEEBuffBound has overflowed.
+
+Prototype:
+
+   int BufBound_IsFull(BufBound* me);
+
+Parameters:
+    me: the BufBound
+
+Return Value:
+   1 if the BufBound has overflowed, 0 otherwise
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+BufBound_WriteLE()
+
+Description:
+
+   Writes data while translating numeric values between host byte ordering and
+   "little endian" byte ordering.
+
+   The input buffer is treated as an array of structures.  The 'abySizes'
+   parameter describes the sizes of fields in the structure.
+
+   When the host byte ordering matches the target byte ordering (little
+   endian) this operation is equivalent to BufBound_Write().
+
+Prototype:
+
+   void BufBound_WriteLE(BufBound* me,
+                         const void *pvSrc, int nSrcSize,
+                         const unsigned char *pszFields);
+
+Parameters:
+   me:        the BufBound
+   pvSrc:     the source buffer
+   nSrcSize:  number of bytes to copy from the source buffer
+   pszFields: Description of the fields that comprise the source data,
+              as defined in std_CopyLE.
+
+Return Value:
+   None
+
+See Also:
+   BufBound_WriteBE, std_CopyLE
+
+=======================================================================
+
+BufBound_WriteBE()
+
+Description:
+
+   BufBounf_WriteBE() has the same semantics as BufBound_WriteLE() except it
+   copies between host byte ordering and big-endian ("network") byte order.
+
+   See BufBound_WriteLE() for more details.
+
+
+Prototype:
+
+   void BufBound_WriteBE(BufBound* me,
+                         const void *pvSrc, int nSrcSize,
+                         const unsigned char *pszFields);
+
+Parameters:
+   me:        the BufBound
+   pvSrc:     the source buffer
+   nSrcSize:  number of bytes to copy from the source buffer
+   pszFields: Description of the fields that comprise the source data,
+              as defined in std_CopyLE.
+
+Return Value:
+   None
+
+See Also:
+   BufBound_WriteLE, std_CopyBE
+
+======================================================================= */
+#endif /* #ifndef AEEBUFBOUND_H */
+
diff --git a/inc/AEEQList.h b/inc/AEEQList.h
new file mode 100644
index 0000000..1b3b941
--- /dev/null
+++ b/inc/AEEQList.h
@@ -0,0 +1,851 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+/*===========================================================================
+
+FILE:  AEEQList.h
+
+GENERAL DESCRIPTION:  Doubly-linked circular list implementation
+
+===========================================================================*/
+#ifndef _AEEQLIST_H_
+#define _AEEQLIST_H_
+
+
+typedef struct QNode QNode;
+struct QNode {
+   QNode *pNext;
+   QNode *pPrev;
+};
+
+#define QLIST_DEFINE_INIT(f) QList f = { { &f.n, &f.n } }
+
+typedef struct QList QList;
+struct QList {
+   QNode n;
+};
+
+
+
+static __inline void QNode_InsPrev(QNode *me, QNode *pn)
+{
+   QNode *pPrev = me->pPrev;
+
+   pn->pNext    = me;
+   pn->pPrev    = pPrev;
+   pPrev->pNext = pn;
+   me->pPrev    = pn;
+}
+
+
+static __inline void QNode_InsNext(QNode *me, QNode *pn)
+{
+   QNode *pNext = me->pNext;
+
+   pn->pPrev    = me;
+   pn->pNext    = pNext;
+   pNext->pPrev = pn;
+   me->pNext    = pn;
+}
+
+
+
+static __inline void QNode_Dequeue(QNode *me)
+{
+   QNode *pNext = me->pNext;
+   QNode *pPrev = me->pPrev;
+
+   pPrev->pNext = pNext;
+   pNext->pPrev = pPrev;
+}
+
+static __inline void QNode_CtorZ(QNode *me)
+{
+   me->pNext = me->pPrev = 0;
+}
+
+static __inline int QNode_IsQueuedZ(QNode *me)
+{
+   return (0 != me->pNext);
+}
+
+static __inline void QNode_DequeueZ(QNode *me)
+{
+   if (QNode_IsQueuedZ(me)) {
+      QNode_Dequeue(me);
+      me->pNext = me->pPrev = 0;
+   }
+}
+
+//--------------------------------------------------------------------
+//--  QList functions  ----------------------------------------------
+//--------------------------------------------------------------------
+
+
+static __inline void QList_Zero(QList *me)
+{
+   me->n.pNext = me->n.pPrev = &me->n;
+}
+
+
+static __inline void QList_Ctor(QList *me)
+{
+   QList_Zero(me);
+}
+
+
+static __inline int QList_IsEmpty(QList *me)
+{
+   return me->n.pNext == &me->n;
+}
+
+static __inline int QList_IsNull(QList *me)
+{
+   return ((0 == me->n.pNext) && (0 == me->n.pPrev));
+}
+
+
+static __inline void QList_AppendNode(QList *me, QNode *pn)
+{
+   QNode_InsPrev(&me->n, pn);
+}
+
+
+static __inline void QList_PrependNode(QList *me, QNode *pn)
+{
+   QNode_InsNext(&me->n, pn);
+}
+
+
+static __inline void QList_CtorFrom(QList *me, QList *psrc)
+{
+   QNode *s = &psrc->n;
+   QNode *d = &me->n;
+
+   s->pNext->pPrev = d;
+   d->pPrev        = s->pPrev;
+   d->pNext        = s->pNext;
+   s->pPrev->pNext = d;
+
+   QList_Zero(psrc);
+}
+
+
+
+static __inline void QList_AppendList(QList *me, QList *psrc)
+{
+   QNode *s = &psrc->n;
+   QNode *d = &me->n;
+   QNode *dp = d->pPrev;
+   QNode *sn = s->pNext;
+   QNode *sp;
+
+   sn->pPrev   = dp;
+   dp->pNext   = sn;
+   d->pPrev    = (sp = s->pPrev);
+   sp->pNext   = d;
+
+   QList_Zero(psrc);
+}
+
+
+#define QLIST_FOR_ALL(pList, pNode) \
+   for ((pNode) = (pList)->n.pNext; \
+        (pNode) != &(pList)->n; \
+        (pNode) = (pNode)->pNext)
+
+#define QLIST_FOR_REST(pList, pNode) \
+   for (; \
+        (pNode) != &(pList)->n; \
+        (pNode) = (pNode)->pNext)
+
+#define QLIST_REV_FOR_ALL(pList, pNode) \
+   for ((pNode) = (pList)->n.pPrev; \
+        (pNode) != &(pList)->n; \
+        (pNode) = (pNode)->pPrev)
+
+#define QLIST_REV_FOR_REST(pList, pNode) \
+   for (; \
+        (pNode) != &(pList)->n; \
+        (pNode) = (pNode)->pPrev)
+
+/* Allows dequeing QNodes during iteration */
+#define QLIST_NEXTSAFE_FOR_ALL(pList, pNode, pNodeNext) \
+    for ((pNode) = (pList)->n.pNext, (pNodeNext) = (pNode)->pNext; \
+         (pNode) != &(pList)->n; \
+         (pNode) = (pNodeNext), (pNodeNext) = (pNode)->pNext)
+
+static __inline QNode *QList_GetFirst(QList *me)
+{
+   QNode *pn = me->n.pNext;
+
+   return (pn == &me->n ? 0 : pn);
+}
+
+static __inline QNode *QList_GetLast(QList *me)
+{
+   QNode *pn = me->n.pPrev;
+
+   return (pn == &me->n ? 0 : pn);
+}
+
+static __inline QNode *QList_Pop(QList *me)
+{
+   QNode *pn = me->n.pNext;
+   QNode *pnn = pn->pNext;
+
+   me->n.pNext = pnn;
+   pnn->pPrev   = &me->n;
+
+   return (pn == &me->n ? 0 : pn);
+}
+
+static __inline QNode *QList_PopZ(QList *me)
+{
+   QNode *pn = QList_Pop(me);
+   if (0 != pn) {
+      QNode_CtorZ(pn);
+   }
+   return pn;
+}
+
+static __inline QNode *QList_PopLast(QList *me)
+{
+   QNode *pp = me->n.pPrev;
+   QNode *ppp = pp->pPrev;
+
+   me->n.pPrev = ppp;
+   ppp->pNext  = &me->n;
+
+   return (pp == &me->n ? 0 : pp);
+}
+
+static __inline QNode *QList_PopLastZ(QList *me)
+{
+   QNode *pn = QList_PopLast(me);
+   if (0 != pn) {
+      QNode_CtorZ(pn);
+   }
+   return pn;
+}
+
+/*=====================================================================
+=======================================================================
+DATA STRUCTURE DOCUMENTATION
+=======================================================================
+
+QNode
+
+Description:
+ Qnode is the structure that is queued.  One or more Qnodes may be
+ embedded in other structures. An object can contain multiple QNodes if
+ it needs to be in different lists at the same time.
+
+Definition:
+
+   typedef struct QNode QNode;
+   struct QNode {
+      QNode *pNext;
+      QNode *pPrev;
+   };
+
+Members:
+
+See Also:
+
+=======================================================================
+
+QList
+
+Description:
+ QList keeps a doubly-linked list of QNode structures.
+ Each queue is represented by a 'head' node, not a head pointer,
+ simplifying and streamlining many operations.
+ Because it is doubly-linked it permits constant-time insertion or removal
+ of items or of entire queues.
+ Because it is circular it permits constant-time operations at both the
+ tail and the head of the queue.  Circularity also streamlines some
+ operations by eliminating conditional branches.
+
+ General rules:
+ QLists are always in a defined state; they should be constructed
+ before use, using one of the supplied Ctor...() functions.
+ QNodes do not track queued vs. unqueued state.  The client should
+ never dequeue an un-queued node or queue an already-queued node.
+ When not queued, QNode internal state is undefined.   A client may
+ implement marking and assertion externally.
+
+Definition:
+
+   typedef struct QList QList;
+   struct QList {
+      QNode n;
+   };
+
+Members:
+
+See Also:
+
+=======================================================================
+INTERFACE DOCUMENTATION
+=======================================================================
+QNode Interface
+
+  QNode is a statically-linked interface.
+
+=======================================================================
+QNode_CtorZ()
+
+Description:
+   Zero initialize a QNode.
+
+Prototype:
+
+   void QNode_CtorZ(QNode *me);
+
+Parameters:
+   me: the QNode
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QNode_IsQueued(), QNode_DequeueZ(), QList_PopZ()
+
+=======================================================================
+QNode_IsQueuedZ()
+
+Description:
+   Whether a QNode belongs in a Queue.
+
+Prototype:
+
+   int QNode_IsQueuedZ(QNode *me);
+
+Parameters:
+   me: the QNode
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   Does not work if a node needs to live at address 0x0.
+
+See Also:
+   QNode_CtorZ(), QNode_DequeueZ(), QList_PopZ()
+
+=======================================================================
+QNode_DequeueZ()
+
+Description:
+   Dequeue a QNode if it is in a queue. Idempotent operation.
+
+Prototype:
+
+   void QNode_DequeueZ(QNode *me);
+
+Parameters:
+   me: the QNode
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QNode_CtorZ(), QNode_IsQueued(), QList_PopZ()
+
+=======================================================================
+
+QNode_InsPrev()
+
+Description:
+	insert a node before this one.
+
+Prototype:
+	static __inline void QNode_InsPrev(QNode *me, QNode *pn)
+
+Parameters:
+	me: the QNode
+	pn: the node to be inserted.
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+QNode_InsNext()
+
+Description:
+	insert a node after this one.
+
+Prototype:
+	static __inline void QNode_InsNext(QNode *me, QNode *pn)
+
+Parameters:
+	me: the QNode
+	pn: the node to be inserted.
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QNode_Dequeue()
+
+Description:
+	dequeue this node.
+
+Prototype:
+	static __inline void QNode_Dequeue(QNode *me)
+
+Parameters:
+	me: the QNode to be dequeued
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList Interface
+
+  QList is a statically-linked interface.  It provides a Queue of
+  doubly linked nodes.
+
+=======================================================================
+QList_Zero()
+
+Description:
+   discard all queued nodes.
+
+Prototype:
+
+   void QList_Zero(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList_Ctor()
+
+Description:
+   Initialize a queue to an empty state
+
+Prototype:
+
+   void QList_Ctor(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList_IsEmpty()
+
+Description:
+   Check whether queue is empty.
+
+Prototype:
+
+   int QList_IsEmpty(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   TRUE if queue is empty.
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList_AppendNode()
+
+Description:
+   Append the node to the queue. Make it the last 'next' (and the
+   first 'prev')
+
+Prototype:
+
+   void QList_AppendNode(QList *me, QNode *pn)
+
+Parameters:
+   me: the QList
+   pn: the node to append.
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList_PrependNode()
+
+Description:
+   Prepend a node to the queue. Make it the first 'next' (and the
+   last 'prev').
+
+Prototype:
+
+   void QList_PrependNode(QList *me, QNode *pn)
+
+Parameters:
+   me: the QList
+   pn: the node to prepend.
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList_CtorFrom()
+
+Description:
+   Move nodes from one queue to a newly constructed queue.
+   Weird aliasing voodoo allows this to work without conditional branches, even
+   when psrc is empty.  In that case, "s->pNext->pPrev = d" overwrites s->pPrev with d,
+   so that "s->pPrev->pNext = d" will later overwrite d->pNext with d.
+
+Prototype:
+
+   void QList_CtorFrom(QList *me, QList *psrc)
+
+Parameters:
+   me: the QList
+   psrc: the Qlist from
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList_AppendList()
+
+Description:
+  Move all nodes from a source queue to the end of this queue.
+  Note that weird aliasing voodoo allows this to work without conditional
+  branches when psrc is empty.  A summary:
+
+      SNP = DP      =>  SP = DP, because SNP aliases SP
+      DPN = SN      =>  DPN = S
+      DP = SP       =>  DP = DP, because SP was overwritten with DP
+      SPN = D       =>  DPN = D
+
+Prototype:
+
+   void QList_AppendList(QList *me, QList *psrc)
+
+Parameters:
+   me: the QList
+   psrc: the source Qlist.
+
+Return Value:
+   None
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+QList_GetFirst()
+
+Description:
+   Get the first item on the queue
+
+Prototype:
+
+   QNode *QList_GetFirst(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   pointer to QNode or 0 if queue is empty.
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QList_GetLast
+
+=======================================================================
+QList_GetLast()
+
+Description:
+   Get the last item on the queue
+
+Prototype:
+
+   QNode *QList_GetLast(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   pointer to QNode or 0 if queue is empty.
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QList_GetFirst
+
+=======================================================================
+QList_Pop()
+
+Description:
+   Remove and return the first item on the queue (FIFO).
+
+Prototype:
+
+   QNode *QList_Pop(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   pointer to QNode or 0 if queue is empty
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QNode_PopZ, QNode_PopLast(), QNode_PopLastZ, QNode_CtorZ(), QNode_IsQueued(),
+   QNode_DequeueZ()
+
+=======================================================================
+QList_PopZ()
+
+Description:
+   Remove and return the first item on the queue (FIFO). Same as QList_Pop(),
+   except the node retured is zero-initialized.
+
+Prototype:
+
+   QNode *QList_PopZ(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   pointer to QNode or 0 if queue is empty
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QNode_Pop, QNode_PopLast(), QNode_PopLastZ, QNode_CtorZ(), QNode_IsQueued(),
+   QNode_DequeueZ()
+
+=======================================================================
+QList_PopLast()
+
+Description:
+   Remove and return the first item on the queue (FILO).
+
+Prototype:
+
+   QNode *QList_PopLast(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   pointer to QNode or 0 if queue is empty
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QNode_PopLastZ, QNode_Pop(), QNode_PopZ, QNode_CtorZ(), QNode_IsQueued(),
+   QNode_DequeueZ()
+
+=======================================================================
+
+QList_IsNull()
+
+Description:
+Checks if the QList is null or not.
+
+Prototype:
+static __inline int QList_IsNull(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   True or False.
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+	None
+
+=======================================================================
+
+QList_PopLastZ()
+
+Description:
+   Remove and return the first item on the queue (FILO).
+   Same as QList_PopLast(), except the node retured is zero-initialized.
+
+Prototype:
+
+   QNode *QList_PopLastZ(QList *me)
+
+Parameters:
+   me: the QList
+
+Return Value:
+   pointer to QNode or 0 if queue is empty
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   QNode_Pop(), QNode_PopZ, QNode_CtorZ(), QNode_IsQueued(), QNode_DequeueZ()
+
+=====================================================================*/
+#endif // _AEEQLIST_H_
diff --git a/inc/AEEStdDef.h b/inc/AEEStdDef.h
new file mode 100644
index 0000000..230950f
--- /dev/null
+++ b/inc/AEEStdDef.h
@@ -0,0 +1,1146 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 AEESTDDEF_H
+#define AEESTDDEF_H
+/*
+=======================================================================
+
+FILE:         AEEStdDef.h
+
+DESCRIPTION:  definition of basic types, constants,
+                 preprocessor macros
+
+=======================================================================
+*/
+
+#include <stdint.h>
+
+#if defined(COMDEF_H) /* guards against a known re-definer */
+#define _BOOLEAN_DEFINED
+#define _UINT32_DEFINED
+#define _UINT16_DEFINED
+#define _UINT8_DEFINED
+#define _INT32_DEFINED
+#define _INT16_DEFINED
+#define _INT8_DEFINED
+#define _UINT64_DEFINED
+#define _INT64_DEFINED
+#define _BYTE_DEFINED
+#endif /* #if !defined(COMDEF_H) */
+
+/* -----------------------------------------------------------------------
+** Standard Types
+** ----------------------------------------------------------------------- */
+
+/* The following definitions are the same accross platforms.  This first
+** group are the sanctioned types.
+*/
+#ifndef _BOOLEAN_DEFINED
+typedef  unsigned char      boolean;     /* Boolean value type. */
+#define _BOOLEAN_DEFINED
+#endif
+
+#ifndef _UINT32_DEFINED
+typedef  uint32_t           uint32;      /* Unsigned 32 bit value */
+#define _UINT32_DEFINED
+#endif
+
+#ifndef _UINT16_DEFINED
+typedef  unsigned short     uint16;      /* Unsigned 16 bit value */
+#define _UINT16_DEFINED
+#endif
+
+#ifndef _UINT8_DEFINED
+typedef  unsigned char      uint8;       /* Unsigned 8  bit value */
+#define _UINT8_DEFINED
+#endif
+
+#ifndef _INT32_DEFINED
+typedef  int32_t            int32;       /* Signed 32 bit value */
+#define _INT32_DEFINED
+#endif
+
+#ifndef _INT16_DEFINED
+typedef  signed short       int16;       /* Signed 16 bit value */
+#define _INT16_DEFINED
+#endif
+
+#ifndef _INT8_DEFINED
+typedef  signed char        int8;        /* Signed 8  bit value */
+#define _INT8_DEFINED
+#endif
+
+#if defined(__GNUC__)
+#define __int64 long long
+#endif
+
+#ifndef _UINT64_DEFINED
+typedef  unsigned __int64   uint64;      /* Unsigned 64 bit value */
+#define _UINT64_DEFINED
+#endif
+
+#ifndef _INT64_DEFINED
+typedef  __int64            int64;       /* Signed 64 bit value */
+#define _INT64_DEFINED
+#endif
+
+#ifndef _BYTE_DEFINED
+typedef  unsigned char      byte;        /* byte type */
+#define  _BYTE_DEFINED
+#endif
+
+
+#ifndef _AEEUID_DEFINED
+typedef uint32             AEEUID;
+#define _AEEUID_DEFINED
+#endif
+
+#ifndef _AEEIID_DEFINED
+typedef uint32             AEEIID;
+#define _AEEIID_DEFINED
+#endif
+
+#ifndef _AEECLSID_DEFINED
+typedef uint32             AEECLSID;
+#define _AEECLSID_DEFINED
+#endif
+
+#ifndef _AEEPRIVID_DEFINED
+typedef uint32             AEEPRIVID;
+#define _AEEPRIVID_DEFINED
+#endif
+
+#ifndef _AECHAR_DEFINED
+typedef uint16             AECHAR;
+#define _AECHAR_DEFINED
+#endif
+
+#ifndef _AEERESULT_DEFINED
+typedef int                AEEResult;
+#define _AEERESULT_DEFINED
+#endif
+
+/* -----------------------------------------------------------------------
+** Function Calling Conventions
+** ----------------------------------------------------------------------- */
+
+#ifndef CDECL
+#ifdef _MSC_VER
+#define CDECL __cdecl
+#else
+#define CDECL
+#endif /* _MSC_VER */
+#endif /* CDECL */
+
+/* -----------------------------------------------------------------------
+** Constants
+** ----------------------------------------------------------------------- */
+
+#ifndef TRUE
+#define TRUE   1   /* Boolean true value. */
+#endif
+
+#ifndef FALSE
+#define FALSE  0   /* Boolean false value. */
+#endif
+
+#ifndef NULL
+#define NULL  0
+#endif
+
+#ifndef MIN_INT8
+#define MIN_INT8 -128
+#endif
+#ifndef MIN_INT16
+#define MIN_INT16 -32768
+#endif
+#ifndef MIN_INT32
+#define MIN_INT32 (~0x7fffffff)   /* -2147483648 is unsigned */
+#endif
+#ifndef MIN_INT64
+#define MIN_INT64 (~0x7fffffffffffffffLL) /* -9223372036854775808 is unsigned */
+#endif
+
+#ifndef MAX_INT8
+#define MAX_INT8 127
+#endif
+#ifndef MAX_INT16
+#define MAX_INT16 32767
+#endif
+#ifndef MAX_INT32
+#define MAX_INT32 2147483647
+#endif
+#ifndef MAX_INT64
+#define MAX_INT64 9223372036854775807LL
+#endif
+
+#ifndef MAX_UINT8
+#define MAX_UINT8 255
+#endif
+#ifndef MAX_UINT16
+#define MAX_UINT16 65535
+#endif
+#ifndef MAX_UINT32
+#define MAX_UINT32 4294967295u
+#endif
+#ifndef MAX_UINT64
+#define MAX_UINT64 18446744073709551615uLL
+#endif
+
+#ifndef MIN_AECHAR
+#define MIN_AECHAR 0
+#endif
+#ifndef MAX_AECHAR
+#define MAX_AECHAR 65535
+#endif
+
+
+/* -----------------------------------------------------------------------
+** Preprocessor helpers
+** ----------------------------------------------------------------------- */
+#define __STR__(x) #x
+#define __TOSTR__(x) __STR__(x)
+#define __FILE_LINE__ __FILE__ ":" __TOSTR__(__LINE__)
+
+/* -----------------------------------------------------------------------
+** Types for code generated from IDL
+** ----------------------------------------------------------------------- */
+
+#ifndef __QIDL_WCHAR_T_DEFINED__
+#define __QIDL_WCHAR_T_DEFINED__
+typedef uint16 _wchar_t;
+#endif
+
+/* __STRING_OBJECT__ will be deprecated in the future */
+#if !defined(__QIDL_STRING_OBJECT_DEFINED__) && !defined(__STRING_OBJECT__)
+#define __QIDL_STRING_OBJECT_DEFINED__
+#define __STRING_OBJECT__
+typedef struct _cstring_s {
+   char* data;
+   int dataLen;
+   int dataLenReq;
+} _cstring_t;
+
+typedef struct _wstring_s {
+   _wchar_t* data;
+   int dataLen;
+   int dataLenReq;
+} _wstring_t;
+#endif /* __QIDL_STRING_OBJECT_DEFINED__ */
+
+/*
+=======================================================================
+  DATA STRUCTURES DOCUMENTATION
+=======================================================================
+
+boolean
+
+Description:
+    This type is used to express boolean values (TRUE or FALSE).
+
+Definition:
+    typedef  unsigned char boolean
+
+See Also:
+   byte
+   int8
+   int16
+   int32
+   int64
+   uint32
+   uint16
+   uint8
+   uint64
+
+=======================================================================
+
+uint32
+
+Description:
+    This is a 32-bit unsigned integer.
+
+Definition:
+    typedef  uint32_t uint32
+
+See Also:
+   boolean
+   byte
+   int8
+   int16
+   int32
+   int64
+   uint8
+   uint16
+   uint64
+
+=======================================================================
+
+uint16
+
+Description:
+    This is a 16-bit unsigned integer.
+
+Definition:
+    typedef  unsigned short     uint16
+
+See Also:
+   boolean
+   byte
+   int8
+   int16
+   int32
+   int64
+   uint8
+   uint32
+   uint64
+
+=======================================================================
+
+uint8
+
+Description:
+    This is an 8-bit unsigned integer.
+
+Definition:
+    typedef  unsigned char      uint8
+
+See Also:
+   boolean
+   byte
+   int8
+   int16
+   int32
+   int64
+   uint16
+   uint32
+   uint64
+
+=======================================================================
+
+int32
+
+Description:
+    This is a 32-bit signed integer.
+
+Definition:
+    typedef  int32_t int32
+
+See Also:
+   boolean
+   byte
+   int8
+   int16
+   int64
+   uint8
+   uint16
+   uint32
+   uint64
+
+=======================================================================
+
+int16
+
+Description:
+    This is a 16-bit signed integer.
+
+Definition:
+    typedef  signed short       int16
+
+See Also:
+   boolean
+   byte
+   int8
+   int32
+   int64
+   uint8
+   uint16
+   uint32
+   uint64
+
+=======================================================================
+
+int8
+
+Description:
+    This is an 8-bit signed integer.
+
+Definition:
+    typedef  signed char        int8
+
+See Also:
+   boolean
+   byte
+   int16
+   int32
+   int64
+   uint8
+   uint16
+   uint32
+   uint64
+
+=======================================================================
+
+uint64
+
+Description:
+    This is a 64-bit unsigned integer.
+
+Definition:
+    typedef  unsigned __int64   uint64
+
+See Also:
+   boolean
+   byte
+   int8
+   int16
+   int32
+   int64
+   uint8
+   uint16
+   uint32
+
+=======================================================================
+
+int64
+
+Description:
+    This is a 64-bit signed integer.
+
+Definition:
+    typedef  __int64            int64
+
+See Also:
+   boolean
+   byte
+   int8
+   int16
+   int32
+   uint8
+   uint16
+   uint32
+   uint64
+
+=======================================================================
+
+byte
+
+Description:
+    This is a byte.
+
+Definition:
+    typedef  unsigned char     byte
+
+See Also:
+   boolean
+   int8
+   int16
+   int32
+   int64
+   uint8
+   uint16
+   uint32
+   uint64
+
+=======================================================================
+
+AEEUID
+
+Description:
+   This is a BREW unique ID.  Used to express unique types, interfaces, classes
+     groups and privileges.  The BREW ClassID Generator generates
+     unique IDs that can be used anywhere you need a new AEEIID, AEECLSID,
+     or AEEPRIVID.
+
+Definition:
+    typedef uint32             AEEUID
+
+See Also:
+   AECHAR
+   AEECLSID
+   AEEIID
+   AEEPRIVID
+   AEEResult
+
+=======================================================================
+
+AEEIID
+
+Description:
+   This is an interface ID type, used to denote a BREW interface. It is a special case
+     of AEEUID.
+
+Definition:
+    typedef uint32             AEEIID
+
+See Also:
+   AECHAR
+   AEECLSID
+   AEEPRIVID
+   AEEResult
+   AEEUID
+
+=======================================================================
+
+AEECLSID
+
+Description:
+   This is a classe ID type, used to denote a BREW class. It is a special case
+     of AEEUID.
+
+Definition:
+    typedef uint32             AEECLSID
+
+See Also:
+   AECHAR
+   AEECLSIDs
+   AEEIID
+   AEEPRIVID
+   AEEResult
+   AEEUID
+
+=======================================================================
+
+AEEPRIVID
+
+Description:
+   This is a privilege ID type, used to express a privilege.  It is a special case
+     of AEEUID.
+
+Definition:
+    typedef uint32             AEEPRIVID
+
+See Also:
+   AECHAR
+   AEECLSID
+   AEEIID
+   AEEResult
+   AEEUID
+
+=======================================================================
+
+AECHAR
+
+Description:
+   This is a 16-bit character type.
+
+Definition:
+   typedef uint16             AECHAR
+
+See Also:
+   AEEPRIVID
+   AEECLSID
+   AEEIID
+   AEEResult
+   AEEUID
+
+=======================================================================
+
+AEEResult
+
+Description:
+   This is the standard result type.
+
+Definition:
+   typedef int                AEEResult
+
+See Also:
+   AECHAR
+   AEEPRIVID
+   AEECLSID
+   AEEIID
+   AEEUID
+
+=======================================================================
+
+_wchar_t
+
+Description:
+   This is a 16-bit character type corresponding to the IDL 'wchar'
+   type.
+
+Definition:
+   typedef uint16             _wchar_t
+
+See Also:
+   _cstring_t
+   _wstring_t
+
+=======================================================================
+
+_cstring_t
+
+Description:
+   This structure is used to represent an IDL string when used inside a
+   sequence or union.
+
+Definition:
+   typedef struct _cstring_s {
+      char* data;
+      int dataLen;
+      int dataLenReq;
+   } _cstring_t;
+
+Members:
+   data       : A pointer to the NULL-terminated string.
+   dataLen    : The size, in chars, of the buffer pointed to by 'data',
+                including the NULL terminator.  This member is only used
+                when the structure is part of an rout or inrout
+                parameter, but must be supplied by the caller as an
+                input in these cases.
+   dataLenReq : The size that would have been required to store the
+                entire result string.  This member is only used when the
+                structure is part of an rout or inrout parameter, when
+                it is an output value set by the callee.  The length of
+                the returned string (including the NULL terminator)
+                after a call is the minimum of dataLen and dataLenReq.
+
+See Also:
+   _wchar_t
+   _wstring_t
+
+=======================================================================
+
+_wstring_t
+
+Description:
+   This structure is used to represent an IDL wstring when used inside a
+   sequence or union.
+
+Definition:
+   typedef struct _wstring_s {
+      _wchar_t* data;
+      int dataLen;
+      int dataLenReq;
+   } _wstring_t;
+
+Members:
+   data       : A pointer to the NULL-terminated wide string.
+   dataLen    : The size, in 16-bit characters, of the buffer pointed to
+                by 'data', including the NULL terminator.  This member
+                is only used when the structure is part of an rout or
+                inrout parameter, but must be supplied by the caller as
+                an input in these cases.
+   dataLenReq : The number of 16-bit characters that would have been
+                required to store the entire result string.  This member
+                is only used when the structure is part of an rout or
+                inrout parameter, when it is an output value set by the
+                callee.  The length of the returned wstring (including
+                the NULL terminator) after a call is the minimum of
+                dataLen and dataLenReq.
+
+See Also:
+   _cstring_t
+   _wchar_t
+
+=======================================================================
+CONSTANTS DOCUMENTATION
+=======================================================================
+
+TRUE
+
+Description:
+   TRUE is the boolean "true."
+
+Definition:
+
+   #define TRUE    1
+
+See Also:
+   FALSE
+   NULL
+
+=======================================================================
+
+FALSE
+
+Description:
+   FALSE is the boolean "false."
+
+Definition:
+
+   #define FALSE   0
+
+See Also:
+   NULL
+   TRUE
+
+=======================================================================
+
+NULL
+
+Description:
+   NULL is the null value, usually used to test a pointer.
+
+Definition:
+
+   #define NULL   0
+
+See Also:
+   FALSE
+   TRUE
+
+=======================================================================
+
+MIN_INT8
+
+Description:
+  MIN_INT8 is the minimum signed 8-bit integer value.
+
+Definition:
+
+   #define MIN_INT8  -128
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MIN_INT16
+
+Description:
+  MIN_INT16 is the minimum signed 16-bit integer value
+
+Definition:
+
+   #define MIN_INT16  -32768
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MIN_INT32
+
+Description:
+   MIN_INT32 is the minimum signed 32-bit integer value.
+
+Definition:
+
+   #define MIN_INT32 (~0x7fffffff)
+
+Comments:
+    Brew MP uses (~0x7fffffff), because -2147483648 is treated as unsigned by compilers.
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT64
+
+=======================================================================
+
+MIN_INT64
+
+Description:
+   MIN_INT64 is the minimum signed 64-bit integer value.
+
+Definition:
+
+   #define MIN_INT64 (~0x7fffffffffffffffll)
+
+Comments:
+    Brew MP uses (~0x7fffffffffffffffll), because -9223372036854775808 is
+       treated as unsigned by compilers.
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+
+=======================================================================
+
+MAX_INT8
+
+Description:
+   MAX_INT8 is the maximum signed 8-bit integer value
+
+Definition:
+
+   #define MAX_INT8  127
+
+See Also:
+   MAX_AECHAR
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_INT16
+
+Description:
+   MAX_INT16 is the maximum signed 16-bit integer value.
+
+Definition:
+
+   #define MAX_INT16  32767
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_INT32
+
+Description:
+   MAX_INT32 is the maximum signed 32-bit integer value.
+
+Definition:
+
+   #define MAX_INT32  2147483647
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_INT64
+
+Description:
+   MAX_INT64 is the maximum signed 64-bit integer value.
+
+Definition:
+
+   #define MAX_INT64  9223372036854775807ll
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_UINT8
+
+Description:
+   MAX_UINT8 is the maximum unsigned 8-bit integer value.
+
+Definition:
+
+   #define MAX_UINT8  255
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_UINT16
+
+Description:
+   MAX_UINT16 is the maximum unsigned 16-bit integer value.
+
+Definition:
+
+   #define MAX_UINT16  65535
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT32
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_UINT32
+
+Description:
+   MAX_UINT32 is the maximum unsigned 32-bit integer value.
+
+Definition:
+
+   #define MAX_UINT32  4294967295u
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT64
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_UINT64
+
+Description:
+   MAX_UINT64 is the maximum unsigned 64-bit integer value.
+
+Definition:
+
+   #define MAX_UINT64  18446744073709551615ull
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MIN_AECHAR
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MIN_AECHAR
+
+Description:
+  MIN_AECHAR is the minimum AECHAR value.
+
+Definition:
+
+   #define MIN_AECHAR  0
+
+See Also:
+   MAX_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+
+MAX_AECHAR
+
+Description:
+  MAX_AECHAR is the maximum AECHAR value.
+
+Definition:
+
+   #define MAX_AECHAR  65535
+
+See Also:
+   MIN_AECHAR
+   MAX_INT8
+   MAX_INT16
+   MAX_INT32
+   MAX_INT64
+   MAX_UINT8
+   MAX_UINT16
+   MAX_UINT32
+   MAX_UINT64
+   MIN_INT8
+   MIN_INT16
+   MIN_INT32
+   MIN_INT64
+
+=======================================================================
+MACROS DOCUMENTATION
+=======================================================================
+
+__STR__()
+
+Description:
+   The __STR__() makes a token into a string, used to string-ize things already
+      defined.
+
+Definition:
+
+   #define __STR__(x)  #x
+
+Parameters:
+    x: token to make into a string
+
+See Also:
+   __TOSTR__()
+   __FILE_LINE__
+
+=======================================================================
+
+__TOSTR__()
+
+Description:
+   The __TOSTR__() makes a token's value into a string, used to string-ize things
+    already defined, used with __STR__.
+
+Definition:
+
+   #define __TOSTR__(x)  __STR__(x)
+
+Parameters:
+    x: token to evaluate and string-ize
+
+Evaluation Value:
+    the token's replacement as a string
+
+See Also:
+   __FILE_LINE__
+   __STR__()
+
+=======================================================================
+
+__FILE_LINE__
+
+Description:
+   The compiler's __FILE__ (a string) and __LINE__ (an integer) are pasted
+     together as a single string with a ":" between.
+
+Definition:
+
+   #define __FILE_LINE__ __FILE__ ":"  __TOSTR__(__LINE__)
+
+Evaluation Value:
+   __FILE__":""__LINE__"
+
+See Also:
+   __STR__()
+   __TOSTR__()
+
+=======================================================================
+*/
+
+#endif /* #ifndef AEESTDDEF_H */
+
diff --git a/inc/AEEStdErr.h b/inc/AEEStdErr.h
new file mode 100644
index 0000000..638410d
--- /dev/null
+++ b/inc/AEEStdErr.h
@@ -0,0 +1,356 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 AEESTDERR_H
+#define AEESTDERR_H
+
+//
+// Basic Error Codes
+//
+//
+#define AEE_SUCCESS              0  			///< No error
+#define AEE_EUNKNOWN		 -1   			/// Unknown error (should not use this)
+#define AEE_EOFFSET		 0x00000000
+#define AEE_EFAILED              (AEE_EOFFSET + 0x001)  ///< General failure
+#define AEE_ENOMEMORY            (AEE_EOFFSET + 0x002)  ///< Insufficient RAM
+#define AEE_ECLASSNOTSUPPORT     (AEE_EOFFSET + 0x003)  ///< Specified class unsupported
+#define AEE_EVERSIONNOTSUPPORT   (AEE_EOFFSET + 0x004)  ///< Version not supported
+#define AEE_EALREADYLOADED       (AEE_EOFFSET + 0x005)  ///< Object already loaded
+#define AEE_EUNABLETOLOAD        (AEE_EOFFSET + 0x006)  ///< Unable to load object/applet
+#define AEE_EUNABLETOUNLOAD      (AEE_EOFFSET + 0x007)  ///< Unable to unload
+							///< object/applet
+#define AEE_EALARMPENDING        (AEE_EOFFSET + 0x008)  ///< Alarm is pending
+#define AEE_EINVALIDTIME         (AEE_EOFFSET + 0x009)  ///< Invalid time
+#define AEE_EBADCLASS            (AEE_EOFFSET + 0x00A)  ///< NULL class object
+#define AEE_EBADMETRIC           (AEE_EOFFSET + 0x00B)  ///< Invalid metric specified
+#define AEE_EEXPIRED             (AEE_EOFFSET + 0x00C)  ///< App/Component Expired
+#define AEE_EBADSTATE            (AEE_EOFFSET + 0x00D)  ///< Invalid state
+#define AEE_EBADPARM             (AEE_EOFFSET + 0x00E)  ///< Invalid parameter
+#define AEE_ESCHEMENOTSUPPORTED  (AEE_EOFFSET + 0x00F)  ///< Invalid URL scheme
+#define AEE_EBADITEM             (AEE_EOFFSET + 0x010)  ///< Invalid item
+#define AEE_EINVALIDFORMAT       (AEE_EOFFSET + 0x011)  ///< Invalid format
+#define AEE_EINCOMPLETEITEM      (AEE_EOFFSET + 0x012)  ///< Incomplete item
+#define AEE_ENOPERSISTMEMORY     (AEE_EOFFSET + 0x013)  ///< Insufficient flash
+#define AEE_EUNSUPPORTED         (AEE_EOFFSET + 0x014)  ///< API is not supported
+#define AEE_EPRIVLEVEL           (AEE_EOFFSET + 0x015)  ///< Privileges are insufficient
+						        ///< for this operation
+#define AEE_ERESOURCENOTFOUND    (AEE_EOFFSET + 0x016)  ///< Unable to find specified
+							///< resource
+#define AEE_EREENTERED           (AEE_EOFFSET + 0x017)  ///< Non re-entrant API
+							///< re-entered
+#define AEE_EBADTASK             (AEE_EOFFSET + 0x018)  ///< API called in wrong task
+							///< context
+#define AEE_EALLOCATED           (AEE_EOFFSET + 0x019)  ///< App/Module left memory
+							///< allocated when released.
+#define AEE_EALREADY             (AEE_EOFFSET + 0x01A)  ///< Operation is already in
+							///< progress
+#define AEE_EADSAUTHBAD          (AEE_EOFFSET + 0x01B)  ///< ADS mutual authorization
+							///< failed
+#define AEE_ENEEDSERVICEPROG     (AEE_EOFFSET + 0x01C)  ///< Need service programming
+#define AEE_EMEMPTR              (AEE_EOFFSET + 0x01D)  ///< bad memory pointer
+#define AEE_EHEAP                (AEE_EOFFSET + 0x01E)  ///< heap corruption
+#define AEE_EIDLE                (AEE_EOFFSET + 0x01F)  ///< Context (system, interface,
+							///< etc.) is idle
+#define AEE_EITEMBUSY            (AEE_EOFFSET + 0x020)  ///< Context (system, interface,
+							///< etc.) is busy
+#define AEE_EBADSID              (AEE_EOFFSET + 0x021)  ///< Invalid subscriber ID
+#define AEE_ENOTYPE              (AEE_EOFFSET + 0x022)  ///< No type detected/found
+#define AEE_ENEEDMORE            (AEE_EOFFSET + 0x023)  ///< Need more data/info
+#define AEE_EADSCAPS             (AEE_EOFFSET + 0x024)  ///< ADS Capabilities do not
+							///< match those required for
+							///< phone
+#define AEE_EBADSHUTDOWN         (AEE_EOFFSET + 0x025)  ///< App failed to close properly
+#define AEE_EBUFFERTOOSMALL      (AEE_EOFFSET + 0x026)  ///< Destination buffer given is
+							///< too small
+#define AEE_ENOSUCH              (AEE_EOFFSET + 0x027)  ///< No such name, port, socket
+							///< or service exists or is
+							///< valid
+#define AEE_EACKPENDING          (AEE_EOFFSET + 0x028)  ///< ACK pending on application
+#define AEE_ENOTOWNER            (AEE_EOFFSET + 0x029)  ///< Not an owner authorized to
+							///< perform the operation
+#define AEE_EINVALIDITEM         (AEE_EOFFSET + 0x02A)  ///< Current item is invalid
+#define AEE_ENOTALLOWED          (AEE_EOFFSET + 0x02B)  ///< Not allowed to perform the
+							///< operation
+#define AEE_EBADHANDLE           (AEE_EOFFSET + 0x02C)  ///< Invalid handle
+#define AEE_EOUTOFHANDLES        (AEE_EOFFSET + 0x02D)  ///< Out of handles
+#define AEE_EINTERRUPTED         (AEE_EOFFSET + 0x02E)  ///< Waitable call is interrupted
+#define AEE_ENOMORE              (AEE_EOFFSET + 0x02F)  ///< No more items available --
+							///< reached end
+#define AEE_ECPUEXCEPTION        (AEE_EOFFSET + 0x030)  ///< A CPU exception occurred
+#define AEE_EREADONLY            (AEE_EOFFSET + 0x031)  ///< Cannot change read-only
+							///< object or parameter
+
+#define AEE_ECONNRESET           104 			///< Connection reset by peer
+#define AEE_EWOULDBLOCK          516 			///< Operation would block if not
+							///< non-blocking; wait and try
+							///< again
+
+//Error code for sigverify
+#define AEE_EUNSIGNEDMOD	     4096 				   /// 0x1000 test-sig not found, Unsigned shared object
+#define AEE_EINVALIDHASH	     8192 				   /// 0x2000 test-sig not found, Invalid hash object
+
+#define AEE_EINVALIDMSG		     (AEE_EOFFSET + 0x032)   /// Invalid SMD message from APPS
+#define AEE_EINVALIDTHREAD	     (AEE_EOFFSET + 0x033)   /// Invalid thread
+#define AEE_EINVALIDPROCESS	     (AEE_EOFFSET + 0x034)   /// Invalid Process
+#define AEE_EINVALIDFILENAME     (AEE_EOFFSET + 0x035)   /// Invalid filename
+#define AEE_EINVALIDDIGESTSIZE   (AEE_EOFFSET + 0x036)   /// Invalid digest size
+#define AEE_EINVALIDSEGS	     (AEE_EOFFSET + 0x037)   /// Invalid segments
+#define AEE_EINVALIDSIGNATURE    (AEE_EOFFSET + 0x038)   /// Invalid signature
+#define AEE_EINVALIDDOMAIN       (AEE_EOFFSET + 0x039)   /// Invalid domain
+#define AEE_EINVALIDFD           (AEE_EOFFSET + 0x03A)   /// Invalid file descriptor
+#define AEE_EINVALIDDEVICE       (AEE_EOFFSET + 0x03B)   /// Invalid Device
+#define AEE_EINVALIDMODE         (AEE_EOFFSET + 0x03C)   /// Invalid Mode
+#define AEE_EINVALIDPROCNAME     (AEE_EOFFSET + 0x03D)   /// Invalid Process name
+#define AEE_ENOSUCHMOD		     (AEE_EOFFSET + 0x03E)   /// No such module
+#define AEE_ENOSUCHINSTANCE	     (AEE_EOFFSET + 0x03F)   /// No instance in the list lookup
+#define AEE_ENOSUCHTHREAD	     (AEE_EOFFSET + 0x040)   /// No such thread
+#define AEE_ENOSUCHPROCESS	     (AEE_EOFFSET + 0x041)   /// No such process
+#define AEE_ENOSUCHSYMBOL	     (AEE_EOFFSET + 0x042)   /// No such symbol
+#define AEE_ENOSUCHDEVICE	     (AEE_EOFFSET + 0x043)   /// No such device
+#define AEE_ENOSUCHPROP	         (AEE_EOFFSET + 0x044)   /// No such dal property
+#define AEE_ENOSUCHFILE		     (AEE_EOFFSET + 0x045)   /// No such file
+#define AEE_ENOSUCHHANDLE	     (AEE_EOFFSET + 0x046)   /// No such handle
+#define AEE_ENOSUCHSTREAM        (AEE_EOFFSET + 0x047)   /// No such stream
+#define AEE_ENOSUCHMAP           (AEE_EOFFSET + 0x048)   /// No such Map
+#define AEE_ENOSUCHREGISTER	     (AEE_EOFFSET + 0x049)   /// No such register
+#define AEE_ENOSUCHCLIENT	     (AEE_EOFFSET + 0x04A)   /// No such QDI client
+#define AEE_EBADDOMAIN           (AEE_EOFFSET + 0x04B)   /// Bad domain (not initialized)
+#define AEE_EBADOFFSET		     (AEE_EOFFSET + 0x04C)   /// Bad buffer/page/heap offset
+#define AEE_EBADSIZE		     (AEE_EOFFSET + 0x04D)   /// Bad buffer/page/heap size
+#define AEE_EBADPERMS		     (AEE_EOFFSET + 0x04E)   /// Bad FILE/MAP/MEM permissions
+#define AEE_EBADFD			     (AEE_EOFFSET + 0x04F)   /// Bad file descriptor
+#define AEE_EBADPID			     (AEE_EOFFSET + 0x050)   /// Bad PID from HLOS
+#define AEE_EBADTID			     (AEE_EOFFSET + 0x051)   /// Bad TID
+#define AEE_EBADELF			     (AEE_EOFFSET + 0x052)   /// Bad elf file
+#define AEE_EBADASID		     (AEE_EOFFSET + 0x053)   /// Bad asid
+#define AEE_EBADCONTEXT		     (AEE_EOFFSET + 0x054)   /// Bad context
+#define AEE_EBADMEMALIGN	     (AEE_EOFFSET + 0x055)   /// Bad memory alignment
+#define AEE_EIOCTL               (AEE_EOFFSET + 0x056)   /// ioctl error
+#define AEE_EFOPEN               (AEE_EOFFSET + 0x057)   /// file open error
+#define AEE_EFGETS               (AEE_EOFFSET + 0x058)   /// file get string error
+#define AEE_EFFLUSH              (AEE_EOFFSET + 0x059)   /// file flush error
+#define AEE_EFCLOSE              (AEE_EOFFSET + 0x05A)   /// file close error
+#define AEE_EEOF		 	     (AEE_EOFFSET + 0x05B)   /// File EOF reached
+#define AEE_EFREAD               (AEE_EOFFSET + 0x05C)   /// file read failed
+#define AEE_EFWRITE              (AEE_EOFFSET + 0x05D)   /// file write failed
+#define AEE_EFGETPOS             (AEE_EOFFSET + 0x05E)   /// file get position failed
+#define AEE_EFSETPOS             (AEE_EOFFSET + 0x05F)   /// file set position failed
+#define AEE_EFTELL               (AEE_EOFFSET + 0x060)   /// file tell position failed
+#define AEE_EFSEEK               (AEE_EOFFSET + 0x061)   /// file seek failed
+#define AEE_EFLEN                (AEE_EOFFSET + 0x062)   /// file len failed
+#define AEE_EGETENV              (AEE_EOFFSET + 0x063)   /// get enviroment failed
+#define AEE_ESETENV              (AEE_EOFFSET + 0x064)   /// set enviroment failed
+#define AEE_EMMAP                (AEE_EOFFSET + 0x065)   /// mmap failed
+#define AEE_EIONMAP              (AEE_EOFFSET + 0x066)   /// ion map failed
+#define AEE_EIONALLOC            (AEE_EOFFSET + 0x067)   /// ion alloc failed
+#define AEE_ENORPCMEMORY         (AEE_EOFFSET + 0x068)   /// ION memory allocation failed
+#define AEE_ENOROOTOFTRUST	 (AEE_EOFFSET + 0x069)   /// No root of trust for sigverify
+#define AEE_ENOTLOCKED		 (AEE_EOFFSET + 0x06A)   /// Unlock failed, not locked before
+#define AEE_ENOTINITIALIZED	 (AEE_EOFFSET + 0x06B)   /// Not initialized
+#define AEE_EUNSUPPORTEDAPI      (AEE_EOFFSET + 0x06C)   /// unsupported API
+#define AEE_EUNPACK		 (AEE_EOFFSET + 0x06D)	 /// unpacking command failed
+#define AEE_EPOLL		 (AEE_EOFFSET + 0x06E)   /// error while polling for event
+#define AEE_EEVENTREAD		 (AEE_EOFFSET + 0x06F)   /// event read failed
+#define AEE_EMAXBUFS		 (AEE_EOFFSET + 0x070)   /// Maximum buffers
+#define AEE_EINVARGS		 (AEE_EOFFSET + 0x071)   /// Invalid Arguments
+
+#define AEE_ESMD_OFFSET		     (AEE_EOFFSET + 0x100)   /// SMD errors offset
+#define AEE_ESMDBADPACKET	     (AEE_EOFFSET + 0x101)   /// SMD invalid packet size
+#define AEE_ESMDALREADYOPEN	     (AEE_EOFFSET + 0x102)   /// SMD port is already open
+#define AEE_ESMDOPENFAILED	     (AEE_EOFFSET + 0x103)   /// SMD port open failed
+
+#define AEE_EDAL_OFFSET		     (AEE_EOFFSET + 0x120)   /// Dal error offset
+#define AEE_EDALDEVATTACH	     (AEE_EOFFSET + 0x121)   /// DAL attach error
+#define AEE_EDALINTREGISTER	     (AEE_EOFFSET + 0x122)   /// DAL interrupt register error
+#define AEE_EDALINTUNREGISTER    (AEE_EOFFSET + 0x123)   /// Dal interrupt unregister error
+#define AEE_EDALGETPROP		     (AEE_EOFFSET + 0x124)   /// Dal get property
+#define AEE_EDALGETVAL		     (AEE_EOFFSET + 0x125)   /// Dal get property value
+
+#define AEE_EQURT_OFFSET	     (AEE_EOFFSET + 0x140)   /// QURT error offset
+#define AEE_EQURTREGIONCREATE    (AEE_EOFFSET + 0x141)   /// QURT region create failed
+#define AEE_EQURTCACHECLEAN	     (AEE_EOFFSET + 0x142)   /// QURT cache clean failed
+#define AEE_EQURTREGIONGETATTR   (AEE_EOFFSET + 0x143)   /// QURT region get attribute failed
+#define AEE_EQURTBADREGIONPERMS  (AEE_EOFFSET + 0x144)   /// QURT bad permissions for region
+#define AEE_EQURTMEMPOOLADD	     (AEE_EOFFSET + 0x145)   /// QURT Add to memory pool failed
+#define AEE_EQURTREGISTERDEV     (AEE_EOFFSET + 0x146)   /// QURT register device failed
+#define AEE_EQURTMEMPOOLCREATE   (AEE_EOFFSET + 0x147)   /// QURT create memory pool failed
+#define AEE_EQURTGETVA		     (AEE_EOFFSET + 0x148)   /// QURT get VA failed
+#define AEE_EQURTREGIONDELETE    (AEE_EOFFSET + 0x149)   /// QURT region delete failed
+#define AEE_EQURTMEMPOOLATTACH   (AEE_EOFFSET + 0x14A)   /// QURT memory pool attach failed
+#define AEE_EQURTTHREADCREATE    (AEE_EOFFSET + 0x14B)   /// QURT thread create failed
+#define AEE_EQURTCOPYTOUSER	     (AEE_EOFFSET + 0x14C)   /// QURT copy to user memory failed
+#define AEE_EQURTMEMMAPCREATE    (AEE_EOFFSET + 0x14D)   /// QURT map create failed
+#define AEE_EQURTINVHANDLE	     (AEE_EOFFSET + 0x14E)   /// QURT Invalid client handle
+#define AEE_EQURTBADASID	     (AEE_EOFFSET + 0x14F)   /// QURT Bad ASIC from QURT
+#define AEE_EQURTOPENFAILED	     (AEE_EOFFSET + 0x150)   /// QURT QDI open failed
+#define AEE_EQURTCOPYFROMUSER    (AEE_EOFFSET + 0x151)   /// QURT Copy from user failed
+#define AEE_EQURTLINELOCK	     (AEE_EOFFSET + 0x152)   /// QURT Line lock failed
+#define AEE_EQURTQDIDEFMETHOD	 (AEE_EOFFSET + 0x153)	 /// QURT QDI default method failed
+
+#define AEE_EMMPM_OFFSET	     (AEE_EOFFSET + 0x170)   /// MMPM errors offset
+#define AEE_EMMPMREQUEST	     (AEE_EOFFSET + 0x171)   /// MMPM Power request to failed
+#define AEE_EMMPMRELEASE	     (AEE_EOFFSET + 0x172)   /// MMPM Release request failed
+#define AEE_EMMPMSETPARAM	     (AEE_EOFFSET + 0x173)   /// MMPM set param request failed
+#define AEE_EMMPMREGISTER	     (AEE_EOFFSET + 0x174)   /// MMPM Register request failed
+#define AEE_EMMPMGETINFO	     (AEE_EOFFSET + 0x175)   /// MMPM Get info failed
+
+
+/*
+============================================================================
+   ERRORS DOCUMENTATION
+==============================================================================
+
+Error Codes
+
+Description:
+This topic lists the categories of error codes that Brew MP returns. The topic for each
+category of error code includes the name of each error, the code that is associated with
+the error, and a description of the error.
+
+===H2>
+List of Error Code Types
+===/H2>
+===p>
+The categories of error codes include: ~
+~
+
+AddrBook error codes  ~
+AddrInfo error codes ~
+AEE_IS_REMOTE_ERR(): ~
+AEE_IS_REMOTE_ERR_PRE(): ~
+Basic AEE Error Codes   ~
+Database error codes  ~
+dbc Error Codes ~
+DNS Resolver error codes ~
+File error codes  ~
+FS AEE Error Codes ~
+ICamera error codes  ~
+ICMP error codes ~
+ILicenseSystem Error Codes ~
+Indeterminate errors: (transport failure) ~
+ISQL Error Codes ~
+ISVGDOM Error Codes: ~
+ISSL error codes  ~
+IX509Chain error codes   ~
+ModCollector Errors  ~
+ModInstallerCntx Errors ~
+ModMover Errors ~
+Multimedia error codes  ~
+Network AEE error codes ~
+Network subsystem error codes ~
+pim_IMessageStore Error Codes ~
+pim_IRecordStore Error Codes ~
+Port AEE Error Codes  ~
+PosDet error codes  ~
+Post-invocation errors: (remote errors) ~
+Pre-invocation errors: (remote errors) ~
+QoS error codes ~
+Remote error codes: ~
+SSL error codes  ~
+VOCODER error codes  ~
+VolumeDB Errors   ~
+Web error codes ~
+
+*
+
+==================================================================
+Basic AEE Error Codes
+
+Description:
+This section lists the set of basic AEE errors returned, the codes associated
+with the errors, and descriptions of the errors.
+
+Definition:
+
+Error                   Code   Description
+
+AEE_SUCCESS             0      operation Successful
+AEE_EFAILED             1      general failure
+AEE_ENOMEMORY           2      insufficient RAM
+AEE_ECLASSNOTSUPPORT    3      specified class unsupported
+AEE_EVERSIONNOTSUPPORT  4      version not supported
+AEE_EALREADYLOADED      5      object already loaded
+AEE_EUNABLETOLOAD       6      unable to load object/applet
+AEE_EUNABLETOUNLOAD     7      unable to unload object/applet
+AEE_EALARMPENDING       8      alarm is pending
+AEE_EINVALIDTIME        9      invalid time
+AEE_EBADCLASS           10     NULL class object
+AEE_EBADMETRIC          11     invalid metric specified
+AEE_EEXPIRED            12     Application/Component Expired
+AEE_EBADSTATE           13     invalid state
+AEE_EBADPARM            14     invalid parameter
+AEE_ESCHEMENOTSUPPORTED 15     invalid URL scheme
+AEE_EBADITEM            16     invalid item
+AEE_EINVALIDFORMAT      17     invalid format
+AEE_EINCOMPLETEITEM     18     incomplete item
+AEE_ENOPERSISTMEMORY    19     insufficient flash
+AEE_EUNSUPPORTED        20     API is not supported
+AEE_EPRIVLEVEL          21     application privileges are insufficient for this operation
+AEE_ERESOURCENOTFOUND   22     unable to find specified resource
+AEE_EREENTERED          23     non re-entrant API re-entered
+AEE_EBADTASK            24     API called in wrong task context
+AEE_EALLOCATED          25     Application/Module left memory allocated when released
+AEE_EALREADY            26     operation is already in progress
+AEE_EADSAUTHBAD         27     ADS mutual authorization failed
+AEE_ENEEDSERVICEPROG    28     need service programming
+AEE_EMEMPTR             29     bad memory pointer
+AEE_EHEAP               30     heap corruption
+AEE_EIDLE               31     context (system, interface, etc.) is idle
+AEE_EITEMBUSY           32     context (system, interface, etc.) is busy
+AEE_EBADSID             33     invalid subscriber ID
+AEE_ENOTYPE             34     no type detected/found
+AEE_ENEEDMORE           35     need more data/info
+AEE_EADSCAPS            36     capabilities do not match those required
+AEE_EBADSHUTDOWN        37     application failed to close properly
+AEE_EBUFFERTOOSMALL     38     destination buffer given is too small
+AEE_ENOSUCH             39     no such name/port/socket/service exists or valid
+AEE_EACKPENDING         40     ACK pending on application
+AEE_ENOTOWNER           41     not an owner authorized to perform the operation
+AEE_EINVALIDITEM        42     current item is invalid
+AEE_ENOTALLOWED         43     not allowed to perform the operation
+AEE_EBADHANDLE          44     invalid handle
+AEE_EOUTOFHANDLES       45     out of handles
+AEE_EINTERRUPTED        46     waitable call is interrupted
+AEE_ENOMORE             47     no more items available -- reached end
+AEE_ECPUEXCEPTION       48     a CPU exception occurred
+AEE_EREADONLY           49     cannot change read-only object or parameter
+AEE_ECONNRESET          104    connection reset by peer
+AEE_EWOULDBLOCK         516    operation would block if not non-blocking; wait and try again
+
+Comments:
+These Brew MP error codes have an up-to-date naming convention, and replace older BREW error
+codes that use a naming convention that did not include the "AEE_" prefix.
+
+See Also:
+  Error Codes
+
+==================================================================
+*/
+#endif /* #ifndef AEESTDERR_H */
+
diff --git a/inc/AEEVaList.h b/inc/AEEVaList.h
new file mode 100644
index 0000000..1ed8476
--- /dev/null
+++ b/inc/AEEVaList.h
@@ -0,0 +1,112 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 AEEVALIST_H
+#define AEEVALIST_H
+
+#if !defined(__clang__) && (defined(__ARMCC_VERSION) || (defined(__GNUC__) && defined(__arm__)))
+
+
+
+#if (defined(__ARMCC_VERSION) && __ARMCC_VERSION >= 200000 && !defined(__APCS_ADSABI)) || \
+    (defined(__GNUC__) && defined(__arm__) && defined(__ARM_EABI__))
+
+# define __AEEVA_ATPCS 0
+
+#else
+
+# define __AEEVA_ATPCS 1
+
+#endif
+
+typedef void* AEEVaList;
+
+#define __AEEVA_ARGALIGN(t)   (((char*)(&((struct{char c;t x;}*)1)->x))-((char*)1))
+#define __AEEVA_ARGSIZE(t)    ((sizeof(t)+sizeof(int)-1) & ~(sizeof(int)-1))
+
+static __inline void __cpy(char*d, const char*s, int len)
+{
+   while (len-- > 0) *d++ = *s++;
+}
+
+static __inline AEEVaList __AEEVa_Arg(AEEVaList args, void* pv, int nVSize,
+                                      int nArgSize, int nArgAlign)
+{
+   int   nArgs = (int)args & ~1;
+   char* pcArgs = (char*)args;
+   int   bATPCS = (int)args & 1;
+   int   nArgsOffset = 0;
+   int   nVOffset = 0;
+
+   if (!bATPCS) { /* caller was compiled with AAPCS */
+
+      if (nArgAlign > (int)sizeof(int)) {
+         nArgAlign--; /* make a mask */
+         pcArgs += ((nArgs + nArgAlign) & (int)~(unsigned)nArgAlign) - nArgs;
+         /* move pv to next alignment */
+      }
+   }
+
+#if defined(AEE_BIGENDIAN)
+   if (nArgSize < (int)sizeof(int)) {
+      nArgsOffset = (int)sizeof(int) - nArgSize;
+   }
+   nVOffset = nVSize - nArgSize;
+#else
+   (void)nVSize;
+#endif /* AEE_BIGENDIAN */
+
+   __cpy((char*)pv + nVOffset, (pcArgs - bATPCS) + nArgsOffset, nArgSize);
+
+   /* round up */
+   nArgSize = (nArgSize+(int)sizeof(int)-1) & ~((int)sizeof(int)-1);
+
+   return pcArgs + nArgSize; /* increment va */
+}
+
+#define AEEVA_START(va,v)     ((va) = (char*)&(v) + __AEEVA_ARGSIZE(v) + __AEEVA_ATPCS)
+#define AEEVA_ARG(va,v,t)     ((void)((va) = __AEEVa_Arg(va,&v,sizeof(v),sizeof(t),__AEEVA_ARGALIGN(t))))
+#define AEEVA_END(va)         ((va) = (AEEVaList)0)
+#define AEEVA_COPY(dest, src) ((void)((dest) = (src)))
+
+#else /* !defined(__clang__) && (defined(__ARMCC_VERSION) || (defined(__GNUC__) && defined(__arm__))) */
+
+#include <stdarg.h>
+
+typedef va_list AEEVaList;
+
+#define AEEVA_START(va,v)     (va_start((va), (v)))
+#define AEEVA_ARG(va,v,t)     ((v) = va_arg((va),t))
+#define AEEVA_END(va)         (va_end((va)))
+#define AEEVA_COPY(dest, src) (va_copy((dest),(src)))
+
+#endif/* !defined(__clang__) && (defined(__ARMCC_VERSION) || (defined(__GNUC__) && defined(__arm__))) */
+
+#endif /* #ifndef AEEVALIST_H */
+
diff --git a/inc/AEEatomic.h b/inc/AEEatomic.h
new file mode 100644
index 0000000..c2f28b4
--- /dev/null
+++ b/inc/AEEatomic.h
@@ -0,0 +1,198 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 AEEATOMIC_H
+#define AEEATOMIC_H
+/*
+=======================================================================
+
+FILE:         AEEatomic.h
+
+SERVICES:     atomic
+
+DESCRIPTION:  Fast Atomic ops
+
+=======================================================================
+*/
+
+#include "AEEStdDef.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* #ifdef __cplusplus */
+
+uint32 atomic_Add(uint32 * volatile puDest, int nAdd);
+uint32 atomic_Exchange(uint32 * volatile puDest, uint32 uVal);
+uint32 atomic_CompareAndExchange(uint32 * volatile puDest, uint32 uExchange, uint32 uCompare);
+uint32 atomic_CompareOrAdd(uint32 * volatile puDest, uint32 uCompare, int nAdd);
+
+uint64 atomic_CompareAndExchange64(uint64 * volatile puDest, uint64 uExchange, uint64 uCompare);
+uintptr_t atomic_CompareAndExchangeUP(uintptr_t * volatile puDest, uintptr_t uExchange, uintptr_t uCompare);
+#ifdef __cplusplus
+}
+#endif /* #ifdef __cplusplus */
+
+/*=====================================================================
+INTERFACE DOCUMENTATION
+=======================================================================
+atomic Interface
+
+  The atomic interface provides fast "atomic" operations.  The
+   operations are defined to be atomic with respect to each other.
+
+=======================================================================
+
+=======================================================================
+
+atomic_Add()
+
+Description:
+
+   Performs an atomic sum operation.
+
+Prototype:
+
+   uint32 atomic_Add(uint32* puDest, int nInc);
+
+Parameters:
+   puDest [in|out] : Points to unsigned number to add nInc and save
+   nInc : increment
+
+Return Value:
+   result.
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+atomic_Exchange()
+
+Description:
+
+   Atomic exchange of 32bit value. Performs an atomic operation of :
+      write uVal to *puDest
+      return the previous value in *puDest
+
+Prototype:
+
+   uint32 atomic_Exchange(uint32* puDest, uint32 uVal);
+
+Parameters:
+   puDest [in|out] : Points to unsigned number to be exchanged
+   uVal : new value to write.
+
+Return Value:
+   previous value at *puDest.
+
+Comments:
+   None
+
+Side Effects:
+   May cause exception if puDest is not a 32 bit aligned address.
+
+See Also:
+   None
+=======================================================================
+
+atomic_CompareAndExchange()
+
+Description:
+
+   Performs an atomic operation of :
+      if (*puDest == uCompare) {
+         *puDest = uExchange;
+      }
+
+   returns the previous value in *puDest
+
+Prototype:
+
+   uint32 atomic_CompareAndExchange(uint32 *puDest, uint32 uExchange,
+                                    uint32 uCompare);
+
+Parameters:
+   puDest [in|out] : Points to unsigned number.
+   uExchange : A new value to write to *puDest
+   uCompare : Comparand
+
+Return Value:
+   previous value at *puDest.
+
+Comments:
+   None
+
+Side Effects:
+   May cause exception if puDest is not a 32 bit aligned address.
+
+See Also:
+   None
+
+=======================================================================
+atomic_CompareOrAdd()
+
+Description:
+
+   Performs an atomic operation of :
+      if (*puDest != uCompare) {
+         *puDest += nAdd;
+      }
+
+   returns the new value in *puDest
+
+Prototype:
+
+   uint32 atomic_CompareOrAdd(uint32 *puDest, uint32 uCompare, int nAdd);
+
+Parameters:
+   puDest [in|out] : Points to unsigned number.
+   uCompare : Comparand
+   nAdd : Add to *puDest
+
+Return Value:
+   new value at *puDest.
+
+Comments:
+   None
+
+Side Effects:
+   May cause exception if puDest is not a 32 bit aligned address.
+
+See Also:
+   None
+=======================================================================*/
+
+#endif /* #ifndef AEEATOMIC_H */
+
diff --git a/inc/AEEstd.h b/inc/AEEstd.h
new file mode 100644
index 0000000..2c832e6
--- /dev/null
+++ b/inc/AEEstd.h
@@ -0,0 +1,2681 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 AEESTD_H
+#define AEESTD_H
+/*====================================================================
+
+DESCRIPTION:  Standard library; general-purpose utility functions.
+
+====================================================================*/
+#include "AEEVaList.h"
+#include "AEEStdDef.h"
+#include "string.h"
+
+#define STD_CONSTRAIN( val, min, max ) (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))
+#define STD_BETWEEN( val, minGE, maxLT ) \
+                   ( (unsigned long)((unsigned long)(val) - (unsigned long)(minGE)) < \
+                   (unsigned long)((unsigned long)(maxLT) - (unsigned long)(minGE)) )
+#define STD_ARRAY_SIZE(a)             ((int)((sizeof((a))/sizeof((a)[0]))))
+#define STD_ARRAY_MEMBER(p,a) (((p) >= (a)) && ((p) < ((a) + STD_ARRAY_SIZE(a))))
+
+#define STD_SIZEOF(x)                 ((int)sizeof(x))
+#define STD_OFFSETOF(type,member)     (((char*)(&((type*)1)->member))-((char*)1))
+
+#define STD_RECOVER_REC(type,member,p) ((void)((p)-&(((type*)1)->member)),\
+                                        (type*)(void*)(((char*)(void*)(p))-STD_OFFSETOF(type,member)))
+#define STD_MIN(a,b)   ((a)<(b)?(a):(b))
+#define STD_MAX(a,b)   ((a)>(b)?(a):(b))
+//lint -emacro(545,STD_ZEROAT)
+#define STD_ZEROAT(p)  std_memset((p), 0, sizeof(*p))
+
+#define _STD_BITS_PER(bits)     (8*sizeof((bits)[0]))
+
+#define STD_BIT_SET(bits, ix)     ((bits)[(ix)/_STD_BITS_PER((bits))] |= 0x1<<((ix) & (_STD_BITS_PER((bits))-1)))
+#define STD_BIT_CLEAR(bits, ix)   ((bits)[(ix)/_STD_BITS_PER((bits))] &= ~(0x1<<((ix) & (_STD_BITS_PER((bits))-1))))
+#define STD_BIT_TEST(bits, ix)    ((bits)[(ix)/_STD_BITS_PER((bits))] & (0x1<<((ix) & (_STD_BITS_PER((bits))-1))))
+
+//
+// Error codes
+//
+#define STD_NODIGITS   1
+#define STD_NEGATIVE   2
+#define STD_OVERFLOW   3
+#define STD_BADPARAM   4
+#define STD_UNDERFLOW  5
+
+//Compute string length using strlen
+#define std_strlen strlen
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* #ifdef __cplusplus */
+
+//Version function
+extern int           std_getversion(char *pcDst, int nDestSize);
+
+//String functions
+extern int           std_strcmp(const char *s1, const char *s2);
+extern int           std_strncmp(const char *s1, const char *s2, int n);
+extern int           std_stricmp(const char *s1, const char *s2);
+extern int           std_strnicmp(const char *s1, const char *s2, int n);
+extern int           std_strlcpy(char *pcDst, const char *pszSrc, int nDestSize);
+extern int           std_strlcat(char *pcDst, const char *pszSrc, int nDestSize);
+extern char *        std_strstr(const char *pszString, const char *pszSearch);
+
+//Character functions
+extern char          std_tolower(char c);
+extern char          std_toupper(char c);
+
+// Mem functions
+extern void *        std_memset(void *p, int c, int nLen);
+extern void *        std_memmove(void *pTo, const void *cpFrom, int nLen);
+extern int           std_memscpy(void *dst, int dst_size, const void *src, int src_size);
+extern int           std_memsmove(void *dst, int dst_size, const void *src, int src_size);
+extern int           std_memcmp(const void *a, const void *b, int length);
+extern void *        std_memchr(const void* s, int c, int n);
+extern void *        std_memstr(const char* cpHaystack, const char* cpszNeedle, int nHaystackLen);
+extern void *        std_memrchr(const void* s, int c, int n);
+extern void *        std_memrchrbegin(const void* p, int c, int nLen);
+extern void *        std_memchrend(const void* cpcSrch, int c, int nLen);
+extern void *        std_memchrsend(const void *cpSrch, const char* cpszChars, int nLen);
+
+//Other String functions
+extern char *        std_strchr(const char* s, int c);
+extern char *        std_strchrs(const char* sSrch, const char *sChars);
+extern char *        std_strrchr(const char* s, int c);
+extern char *        std_strchrend(const char *cpszSrch, char c);
+extern char *        std_strchrsend(const char* s, const char* cpszSrch);
+extern char *        std_strends(const char* cpsz, const char* cpszSuffix);
+extern char *        std_striends(const char* cpsz, const char* cpszSuffix);
+extern char *        std_strbegins(const char* cpsz, const char* cpszPrefix);
+extern char *        std_stribegins(const char* cpsz, const char* cpszPrefix);
+extern int           std_strcspn(const char* s, const char* cpszSrch);
+extern int           std_strspn(const char* s, const char* cpszSrch);
+
+//Wide char string functions
+extern int           std_wstrlen(const AECHAR *s);
+extern int           std_wstrlcpy(AECHAR *pcDst, const AECHAR *pszSrc, int nDestSize);
+extern int           std_wstrlcat(AECHAR *pcDst, const AECHAR *pszSrc, int nDestSize);
+extern int           std_wstrncmp(const AECHAR* s1, const AECHAR* s2, int nLen);
+extern int           std_wstrcmp(const AECHAR* s1, const AECHAR* s2);
+extern AECHAR*       std_wstrchr(const AECHAR* cpwszText, AECHAR ch);
+extern AECHAR*       std_wstrrchr(const AECHAR* cpwszText, AECHAR ch);
+
+//Path functions
+extern int           std_makepath(const char *cpszDir,
+                                  const char *cpszFile,
+                                  char *pszDest, int nDestSize);
+extern char *        std_splitpath(const char *cpszPath, const char *cpszDir);
+extern char *        std_cleanpath(char *pszPath);
+extern char *        std_basename(const char *pszPath);
+
+//Inet functions, number functions
+extern unsigned int        std_scanul(const char *pchBuf, int nRadix,
+                                const char **ppchEnd, int *pnError);
+extern uint64        std_scanull(const char *pchBuf, int nRadix,
+                                 const char **ppchEnd, int *pnError);
+extern double        std_scand(const char *pchBuf, const char **ppchEnd);
+
+// Rand functions
+extern unsigned      std_rand_next(unsigned uRand);
+extern uint32        std_rand(uint32 uSeed, byte* pDest, int nSize);
+
+
+// printf functions
+extern int           std_vstrlprintf(char *pszDest, int nDestSize,
+                                     const char *pszFmt, AEEVaList args);
+
+extern int           std_strlprintf(char *pszDest, int nDestSize,
+                                    const char *pszFmt, ...);
+
+extern int           std_vsnprintf(char *pszDest, int nDestSize,
+                                   const char *cpszFmt, AEEVaList args);
+
+extern int           std_snprintf(char *pszDest, int nDestSize,
+                                  const char *pszFmt, ...);
+
+// endian swapping functions
+extern int           std_CopyLE(void *pvDest,       int nDestSize,
+                                const void *pvSrc,  int nSrcSize,
+                                const char *pszFields);
+
+extern int           std_CopyBE(void *pvDest,      int nDestSize,
+                                const void *pvSrc, int nSrcSize,
+                                const char *pszFields);
+
+// sorting utilities
+extern void  std_qsort(void* pElems, int nNumElems, int nElemWidth,
+                       int (*pfnCompare)(void*, const void*, const void*),
+                       void* pCompareCx);
+
+extern int   std_bisect(const void* pElems, int nNumElems, int nElemWidth,
+                        const void* pElem,
+                        int (*pfnCompare)(void*, const void*, const void*),
+                        void* pCompareCx);
+
+extern void  std_merge(void* vpDst, int nDst,
+                       const void* vpA, int nA,
+                       const void* vpB, int nB,
+                       int nElemWidth,
+                       int (*pfnCompare)(void*, const void*, const void*),
+                       void* pCompareCx);
+
+extern int   std_uniq(void* vpElems, int nNumElems, int nElemWidth,
+                      int (*pfnCompare)(void*, const void*, const void*),
+                      void* pCompareCx);
+
+#ifdef __cplusplus
+}
+#endif /* #ifdef __cplusplus */
+
+
+#define STD_SWAPS(us) \
+   ((((us) & 0xff) << 8) + (((us) & 0xff00) >> 8))
+
+
+static __inline unsigned short std_swaps(unsigned short us)
+{
+   return STD_SWAPS(us);
+}
+
+/* note, STD_SWAPL() requires that ul be an l-value, and destroyable.
+   this macro is not intended for use outside AEEstd.h */
+#define STD_SWAPL(ul) \
+    (((ul) = (((ul) & 0x00ff00ff) << 8) | (((ul)>>8) & 0x00ff00ff)),(((ul) >> 16) | ((ul) << 16)))
+
+static __inline unsigned long std_swapl(unsigned long ul)
+{
+   return STD_SWAPL(ul);
+}
+
+#ifdef AEE_BIGENDIAN
+#  define STD_HTONL(u)     (u)
+#  define STD_HTONS(u)     (u)
+#  define STD_HTOLEL(u)    (STD_SWAPL(u))
+#  define STD_HTOLES(u)    (STD_SWAPS(u))
+#else
+#  define STD_HTONL(u)     (STD_SWAPL(u))
+#  define STD_HTONS(u)     (STD_SWAPS(u))
+#  define STD_HTOLEL(u)    (u)
+#  define STD_HTOLES(u)    (u)
+#endif
+
+static __inline unsigned short std_letohs(unsigned short us)
+{
+   return STD_HTOLES(us);
+}
+
+static __inline unsigned short std_htoles(unsigned short us)
+{
+   return STD_HTOLES(us);
+}
+
+static __inline unsigned long std_letohl(unsigned long ul)
+{
+   return STD_HTOLEL(ul);
+}
+
+static __inline unsigned long std_htolel(unsigned long ul)
+{
+   return STD_HTOLEL(ul);
+}
+
+static __inline unsigned short std_ntohs(unsigned short us)
+{
+   return STD_HTONS(us);
+}
+
+static __inline unsigned short std_htons(unsigned short us)
+{
+   return STD_HTONS(us);
+}
+
+static __inline unsigned long std_ntohl(unsigned long ul)
+{
+   return STD_HTONL(ul);
+}
+
+static __inline unsigned long std_htonl(unsigned long ul)
+{
+   return STD_HTONL(ul);
+}
+
+
+#undef STD_HTONL   // private macro; not exported as a supported API
+#undef STD_HTONS   // private macro; not exported as a supported API
+#undef STD_HTOLEL  // private macro; not exported as a supported API
+#undef STD_HTOLES  // private macro; not exported as a supported API
+#undef STD_SWAPS   // private macro; not exported as a supported API
+#undef STD_SWAPL   // private macro; not exported as a supported API
+
+
+/*
+=======================================================================
+MACROS DOCUMENTATION
+=======================================================================
+
+STD_CONTSTRAIN()
+
+Description:
+  STD_CONTSTRAIN() constrains a number to be between two other numbers.
+
+Definition:
+   STD_CONSTRAIN( val, min, max ) \
+          (((val) < (min)) ? (min) : ((val) > (max)) ? (max) : (val))
+
+Parameters:
+  val: number to constrain
+  min: number to stay greater than or equal to
+  max: number to stay less than or equal to
+
+Evaluation Value:
+   the constrained number
+
+=======================================================================
+
+STD_BETWEEN()
+
+Description:
+    STD_BETWEEN() tests whether a number is between two other numbers.
+
+Definition:
+    STD_BETWEEN( val, minGE, maxLT ) \
+               ((unsigned)((unsigned)(val) - (unsigned)(minGE)) < \
+                (unsigned)((unsigned)(maxLT) - (unsigned)(minGE)))
+
+Parameters:
+     val: value to test
+     minGE: lower bound
+     maxLT: upper bound
+
+Evaluation Value:
+     1 if val >= minGE and val < maxLT
+
+=======================================================================
+
+STD_ARRAY_SIZE()
+
+Description:
+   STD_ARRAY_SIZE() gives the number of elements in a statically allocated array.
+
+Definition:
+    STD_ARRAY_SIZE(a) (sizeof((a))/sizeof((a)[0]))
+
+Parameters:
+    a: array to test
+
+Evaluation Value:
+    number of elements in a
+
+=======================================================================
+
+STD_ARRAY_MEMBER()
+
+Description:
+   STD_ARRAY_MEMBER() tests whether an item is a member of a statically allocated array.
+
+Definition:
+   STD_ARRAY_MEMBER(p,a) (((p) >= (a)) && ((p) < ((a) + STD_ARRAY_SIZE(a))))
+
+Parameters:
+    p: item to test
+    a: array to check
+
+Evaluation Value:
+    1 if p is in a
+
+=======================================================================
+
+STD_OFFSETOF()
+
+Description:
+  STD_OFFSETOF() gives the offset of member of a struct.
+
+Definition:
+   STD_OFFSETOF(type,member) (((char *)(&((type *)0)->member))-((char *)0))
+
+Parameters:
+    type: structured type
+    member: name of member in the struct
+
+Evaluation Value:
+    offset of member (in bytes) in type
+
+=======================================================================
+
+STD_RECOVER_REC()
+
+Description:
+  STD_RECOVER_REC() provides a safe cast from a pointer to a member
+    of a struct to a pointer to the containing struct
+
+Definition:
+  STD_RECOVER_REC(type,member,p) ((type*)(((char*)(p))-STD_OFFSETOF(type,member)))
+
+Parameters:
+    type: structured type
+    member: name of member in the struct
+    p: pointer to the member of the struct
+
+Evaluation Value:
+    a pointer of type type to the containing struct
+
+=======================================================================
+
+STD_MIN()
+
+Description:
+   STD_MIN() finds the smaller of two values.
+
+Definition:
+   STD_MIN(a,b)   ((a)<(b)?(a):(b))
+
+Parameters:
+    a, b: values to compare
+
+Evaluation Value:
+    smaller of a and b
+
+=======================================================================
+
+STD_MAX()
+
+Description:
+  STD_MAX() finds the larger of two values.
+
+Definition:
+   STD_MAX(a,b)   ((a)>(b)?(a):(b))
+
+Parameters:
+    a, b: values to compare
+
+Evaluation Value:
+    larger of a and b
+
+=======================================================================
+
+STD_ZEROAT()
+
+Description:
+   STD_ZEROAT() zero-initializes the contents of a typed chunk of memory.
+
+Definition:
+   STD_ZEROAT(p)  std_memset((p), 0, sizeof(*p))
+
+Parameters:
+    p: the chunk to initialize
+
+Evaluation Value:
+    p
+
+=======================================================================
+
+STD_BIT_SET()
+
+Description:
+   STD_BIT_SET(bits, ix) sets the bit in the memory stored in bits at
+                         index ix
+
+Parameters:
+    bits: the memory address holding the  bits
+    ix:   the index of the bit to set;
+
+=======================================================================
+
+STD_BIT_CLEAR()
+
+Description:
+   STD_BIT_CLEAR(bits, ix) clears the bit in the memory stored in bits
+                           at index ix
+
+Parameters:
+    bits: the memory address holding the  bits
+    ix:   the index of the bit to clear
+
+=======================================================================
+
+STD_BIT_TEST()
+
+Description:
+   STD_BIT_TEST(bits, ix) returns the bit in the memory stored in bits
+                          at index ix
+
+Parameters:
+    bits: the memory address holding the bits
+    ix:   the index of the bit to test
+
+Evaluation Value:
+    0x1 if set 0x0 if not set
+
+=====================================================================
+INTERFACES DOCUMENTATION
+=======================================================================
+
+std Interface
+
+Description:
+   This library provides a set of general-purpose utility functions.
+   Functionality may overlap that of a subset of the C standard library, but
+   this library differs in a few respects:
+
+   - Functions are fully reentrant and avoid use of static variables.
+
+   - The library can be supported consistently across all environments.
+   Compiler-supplied libraries sometimes behave inconsistently and are
+   unavailable in some environments.
+
+   - Omits "unsafe" functions.  C standard library includes many functions
+   that are best avoided entirely: strcpy, strcat, strtok, etc.
+
+
+=======================================================================
+
+std_getversion()
+
+Description:
+
+   The std_getversion() copies the stdlib version to pcDst.  This function
+   takes the size of the destination buffer as an argument and guarantees
+   to zero-terminate the result and not to overflow the nDestSize size.
+
+   This function copies up to size-1 characters from the stdlib version
+   string to pcDest and NUL-terminates the pcDest string.
+
+Prototype:
+   int  std_getversion(char *pcDst, int nDestSize)
+
+
+Parameters:
+   pcDst :     Destination string
+   nDestSize:  Size of the destination buffer in bytes
+
+Return Value:
+
+   Returns the length of the version string (in characters).
+
+=======================================================================
+
+std_strlen()
+
+Description:
+   The std_strlen() computes the length of the given string.
+
+Prototype:
+   int std_strlen(const char *cpszStr)
+
+Parameters:
+   cpszStr : String whose length will be computed
+
+Return Value:
+   Length of the string in characters that precede the terminating NULL character.
+
+=======================================================================
+
+std_strcmp()
+
+Description:
+   The std_strcmp() compares two NUL-terminated character strings.
+   Comparison is strictly by byte values with no character set
+   interpretation.
+
+Prototype:
+
+   int std_strcmp(const char *s1, const char *s2);
+
+Parameters:
+   s1, s2: strings to compare
+
+Return Value:
+   0 if strings are the same ~
+   < 0 if s1 is less than s2 ~
+   > 0 if s1 is greater than s2
+
+See Also:
+   std_wstrcmp
+
+=======================================================================
+
+std_strncmp()
+
+Description:
+   The std_strncmp() compares at most n bytes of two NUL-terminated character strings.
+
+Prototype:
+
+   int std_strncmp(const char *s1, const char *s2, int n);
+
+Parameters:
+   s1, s2: strings to compare
+   n: maximum number of bytes to compare.  if either s1 or s2 is
+       shorter than n, the function terminates there
+
+Return Value:
+   0 if strings are the same ~
+   < 0 if s1 is less than s2 ~
+   > 0 if s1 is greater than s2
+
+See Also:
+   std_wstrncmp
+
+=======================================================================
+
+std_stricmp()
+
+Description:
+   The std_stricmp() compares two NUL-terminated character strings, case-folding any
+   ASCII characters.
+
+Prototype:
+
+   int std_stricmp(const char *s1, const char *s2);
+
+Parameters:
+   s1, s2: strings to compare
+
+Return Value:
+   0 if strings are the same ~
+   < 0 if s1 is less than s2 ~
+   > 0 if s1 is greater than s2
+
+=======================================================================
+
+std_strnicmp()
+
+Description:
+   The std_strnicmp() compares at most n bytes of 2 NUL-terminated character strings,
+   case-folding any ASCII characters.
+
+Prototype:
+
+   int std_strnicmp(const char *s1, const char *s2, int n);
+
+Parameters:
+   s1, s2: strings to compare
+   n: maximum number of bytes to compare.  if either s1 or s2 is
+       shorter than n, the function terminates there
+
+Return Value:
+   0 if strings are the same ~
+   < 0 if s1 is less than s2 ~
+   > 0 if s1 is greater than s2
+
+=======================================================================
+
+std_strlcpy()
+
+Description:
+
+   The std_strlcpy() copies pszSrc string to the pcDst.  It is a safer
+   alternative to strcpy() or strncpy().  This function takes the size of the
+   destination buffer as an argument and guarantees to NUL-terminate the
+   result and not to overflow the nDestSize size.
+
+   This function copies up to nDestSize-1 characters from the pszSrc string
+   to pcDest and NUL-terminates the pcDest string.
+
+Prototype:
+   int std_strlcpy(char *pcDst, const char *pszSrc, int nDestSize)
+
+Parameters:
+   pcDst :     Destination string
+   pcSrc :     Source string
+   nDestSize:  Size of the destination buffer in bytes
+
+Return Value:
+
+   Returns the length of the string (in characters) it tried to create,
+   which is same as length of pszSrc.
+
+   Example:
+
+   {
+      char buf[64];
+      if (std_strlcpy(buf, file_name, STD_ARRAY_SIZE(buf) >=
+          STD_ARRAY_SIZE(buf)) {
+         //Truncated -- Handle overflow....
+      }
+   }
+
+Comment:
+
+   Unlike strlcpy, std_strlcpy accepts an integer size and does nothing when a
+   negative value is passed.  When passing valid sizes for objects on our
+   supported platforms, this should not result in any observed difference.
+   However, calling strlcpy() with UINT_MAX will result in the entire source
+   string being copied, whereas std_strlcpy() will do nothing.  Passing INT_MAX
+   to str_strlcpy() will achieve the same result (although both these cases are
+   bad practice since they defeat bounds checking).
+
+
+=======================================================================
+
+std_strlcat()
+
+Description:
+
+   The std_strlcat() function concatenates a string to a string already
+   residing in a buffer.  It is a safer alternative to strcat() or strncat().
+   This function takes the size of the destination buffer as an argument and
+   guarantees not to create an improperly terminated string and not to
+   overflow the nDestSize size.
+
+   This function appends pszSrc to pcDst, copying at most nDestSize minus
+   the length of the string in pcDest minus 1 bytes, always NUL-terminating
+   the result.
+
+   For compatibility with "strlcat()", std_strlcat() does *not* zero-terminate
+   the destination buffer in cases where the buffer lacks termination on entry
+   to the function.  Do not rely on std_strlcat() to zero-terminate a buffer
+   that is not already zero-terminated; instead ensure that the buffer is
+   properly initialized using std_strlcpy() or some other means.
+
+Prototype:
+
+   int std_strlcat(char *pcDst, const char *pszSrc, int nDestSize)
+
+Parameters:
+
+   pcDst :     Destination string
+   pcSrc :     Source string
+   nDestSize:  Size of the destination buffer in bytes
+
+Return Value:
+
+   Returns the length of the string (in characters) it tried to create,
+   which is same as length of pszSrc plus the length of pszDest.
+
+   Example:
+
+   {
+      char buf[64];
+      if (std_strlcat(buf, file_name, STD_ARRAY_SIZE(buf) >=
+          STD_ARRAY_SIZE(buf)) {
+         //Truncated -- Handle overflow....
+      }
+   }
+
+
+=======================================================================
+
+std_strstr()
+
+Description:
+   The std_strstr() finds the first occurrence of a substring in a string.
+
+Prototype:
+
+   char * std_strstr(const char *pszString, const char *pszSearch);
+
+Parameters:
+   pszString: string to search
+   pszSearch: sub string to search for
+
+Return Value:
+   A pointer to the first character in the first occurrence of the substring if found, NULL otherwise
+
+=======================================================================
+
+std_tolower()
+
+Description:
+   The std_tolower() converts an uppercase letter to the corresponding
+   lowercase letter.
+
+Prototype:
+   char std_tolower(char c);
+
+Parameters:
+   c: A character.
+
+Return Value:
+   the corresponding lowercase letter if c is an ASCII character whose
+   value is representable as an uppercase letter, else the same character
+   c is returned.
+
+=======================================================================
+
+std_toupper()
+
+Description:
+   The std_toupper() converts an lowercase letter to the corresponding
+   uppercase letter.
+
+Prototype:
+   char std_toupper(char c);
+
+Parameters:
+   c: is a character.
+
+Return Value:
+   The corresponding uppercase letter if c is an ASCII character whose
+   value is representable as an lowercase letter; else the same character
+   c is returned.
+
+=======================================================================
+
+std_memset()
+
+Description:
+   The std_memset() sets each byte in a block of memory to a value.
+
+Prototype:
+
+   void *std_memset(void *p, int c, int nLen);
+
+Parameters:
+   p: memory block to set
+   c: value to set each byte to
+   nLen: size of p in bytes
+
+Return Value:
+   p
+
+=======================================================================
+
+std_memmove()
+
+Description:
+   The std_memmove() copies a block of memory from one buffer to another.
+
+Prototype:
+
+   void *std_memmove(void *pTo, const void *cpFrom, int nLen);
+
+Parameters:
+   pTo: destination buffer
+   cpFrom: source buffer
+   nLen: number of bytes to copy
+
+Return Value:
+   pTo
+
+=======================================================================
+
+std_memsmove()
+
+Description:
+
+  Size bounded memory move.
+
+  Moves bytes from the source buffer to the destination buffer.
+
+  This function ensures that there will not be a copy beyond
+  the size of the destination buffer.
+
+  This function should be used in preference to memscpy() if there
+  is the possiblity of source and destination buffers overlapping.
+  The result of the operation is defined to be as if the copy were from
+  the source to a temporary buffer that overlaps neither source nor
+  destination, followed by a copy from that temporary buffer to the
+  destination.
+
+Prototype:
+
+  int std_memsmove(void *dst, int dst_size, const void *src, int src_size);
+
+Parameters:
+  @param[out] dst       Destination buffer.
+  @param[in]  dst_size  Size of the destination buffer in bytes.
+  @param[in]  src       Source buffer.
+  @param[in]  src_size  Number of bytes to copy from source buffer.
+
+Return value:
+  The number of bytes copied to the destination buffer.  It is the
+  caller's responsibility to check for trunction if it cares about it -
+  truncation has occurred if the return value is less than src_size.
+  A negative return value indicates an error
+
+=======================================================================
+
+std_memcmp()
+
+Description:
+   The std_memcmp() compares two memory buffers, byte-wise.
+
+Prototype:
+
+   int std_memcmp(const void *a, const void *b, int length);
+
+Parameters:
+   a, b: buffers to compare
+   length: number of bytes to compare
+
+Return Value:
+   0 if buffers are the same for nLength ~
+   < 0 if a is less than b ~
+   > 0 if a is greater than b
+
+=======================================================================
+
+std_memscpy - Size bounded memory copy.
+
+Description:
+
+  Copies bytes from the source buffer to the destination buffer.
+
+  This function ensures that there will not be a copy beyond
+  the size of the destination buffer.
+
+  The result of calling this on overlapping source and destination
+  buffers is undefined.
+
+Prototype:
+
+   int std_memscpy(void *dst, int dst_size, const void *src, int src_size);
+
+Parameters:
+
+  @param[out] dst       Destination buffer.
+  @param[in]  dst_size  Size of the destination buffer in bytes.
+  @param[in]  src       Source buffer.
+  @param[in]  src_size  Number of bytes to copy from source buffer.
+
+Return value:
+
+  The number of bytes copied to the destination buffer.  It is the
+  caller's responsibility to check for trunction if it cares about it -
+  truncation has occurred if the return value is less than src_size.
+  Returs a negative value on error.
+
+=======================================================================
+
+std_memchr()
+
+Description:
+   The std_memchr() finds the first occurrence of a character in a memory
+   buffer.
+
+Prototype:
+
+   void *std_memchr(const void* s, int c, int n);
+
+Parameters:
+   s: buffer to search
+   c: value of byte to look for
+   n: size of s in bytes
+
+Return Value:
+   A pointer to the occurrence of c. NULL if not found.
+
+=======================================================================
+
+std_memstr()
+
+Description:
+   The std_memstr() finds the first occurrence of a substring in a memory
+   buffer.
+
+Prototype:
+
+   void *std_memstr(const char* cpHaystack, const char* cpszNeedle,
+                    int nHaystackLen);
+
+Parameters:
+   cpHaystack: buffer to search
+   cpszNeedle: NUL-terminated string to search for
+   nHaystackLen: size of cpHaystack in bytes
+
+Return Value:
+   a pointer to the first occurrence of cpszNeedle if found,
+       NULL otherwise
+
+Comments:
+   None
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+std_memrchr()
+
+Description:
+
+   The std_memrchr() finds the last occurrence of a character in a memory
+   buffer.
+
+Prototype:
+
+   void *std_memrchr(const void* s, int c, int n);
+
+Parameters:
+   s: buffer to search
+   c: value of byte to look for
+   n: size of s in bytes
+
+Return Value:
+   a pointer to the last occurrence of c, NULL if not found
+
+=======================================================================
+
+std_memrchrbegin()
+
+Description:
+   The std_memrchrbegin() finds the last occurrence of a character in a
+   memory buffer.
+
+Prototype:
+
+   void *std_memrchrbegin(const void* s, int c, int n);
+
+Parameters:
+   s: buffer to search
+   c: value of byte to look for
+   n: size of s in bytes
+
+Return Value:
+   a pointer to the last occurrence of c, or s if not found
+
+=======================================================================
+
+std_memchrend()
+
+Description:
+   The std_memchrend() finds the first occurrence of a character in a
+   memory buffer.
+
+Prototype:
+
+   void *std_memchrend(const void* s, int c, int n);
+
+Parameters:
+   s: buffer to search
+   c: value of byte to look for
+   n: size of s in bytes
+
+Return Value:
+   a pointer to the occurrence of c, s + n if not found
+
+=======================================================================
+std_memchrsend()
+
+Description:
+   The std_memchrsend() finds the first occurrence of any character in a
+   NUL-terminated list of characters in a memory buffer.
+
+Prototype:
+
+   void *std_memchrend(const void* s, const char* cpszChars, int n);
+
+Parameters:
+   s: buffer to search
+   cpszChars: characters to look for
+   n: size of s in bytes
+
+Return Value:
+   a pointer to the first occurrence of one of cpszChars, s + n if not found
+
+=======================================================================
+
+std_strchr()
+
+Description:
+   The std_strchr() finds the first occurrence of a character in a
+   NUL-terminated string.
+
+Prototype:
+
+   char *std_strchr(const char* s, int c);
+
+Parameters:
+   s: string to search
+   c: char to search for
+
+Return Value:
+   pointer to first occurrence, NULL if not found
+
+See Also:
+   std_wstrchr
+
+=======================================================================
+
+std_strchrs()
+
+Description:
+   The std_strchrs() searches s, a NUL-terminated string, for the first
+   occurrence of any characters in cpszSrch, a NUL-terminated list of
+   characters.
+
+Prototype:
+
+   char *std_strchrs(const char* s, const char *cpszSrch);
+
+Parameters:
+   s: string to search
+   cpszSrch: a list of characters to search for
+
+Return Value:
+   first occurrence of any of cpszSrch, NULL if not found
+
+=======================================================================
+
+std_strrchr()
+
+Description:
+   The std_strrchr() finds the last occurrence of a character in a
+   NUL-terminated string.
+
+Prototype:
+
+   char *std_strrchr(const char* s, int c);
+
+Parameters:
+   s: string to search
+   c: char to search for
+
+Return Value:
+   pointer to last occurrence, NULL if not found
+
+See Also:
+   std_wstrrchr
+
+=======================================================================
+
+std_strchrend()
+
+Description:
+   The std_strchrend() finds the first occurrence of a character in a
+   NUL-terminated string.
+
+Prototype:
+
+   char *std_strchrend(const char* s, int c);
+
+Parameters:
+   s: string to search
+   c: char to search for
+
+Return Value:
+   pointer to first occurrence, s + std_strlen(s) if not found
+
+=======================================================================
+
+std_strchrsend()
+
+Description:
+   The std_strchrsend() searches s, a NUL-terminated string, for the first
+   occurrence of any characters in cpszSrch, a NUL-terminated list of
+   characters.
+
+Prototype:
+
+   char *std_strchrsend(const char* s, const char* cpszSrch);
+
+Parameters:
+   s: string to search
+   cpszSrch: a list of characters to search for
+
+Return Value:
+   first occurrence of any of cpszSrch or s+strlen(s) if not found
+
+=======================================================================
+
+std_strends()
+
+Description:
+   The std_strends() tests whether a string ends in a particular suffix.
+
+Prototype:
+
+   char *std_strends(const char* cpsz, const char* cpszSuffix);
+
+Parameters:
+   cpsz: string to test
+   cpszSuffix: suffix to test for
+
+Return Value:
+   the first character of cpsz+std_strlen(cpsz)-std_strlen(cpszSuffix)
+     if cpsz ends with cpszSuffix.  NULL otherwise.
+
+=======================================================================
+
+std_striends()
+
+Description:
+   The std_striends() tests whether a string ends in a particular suffix,
+   case-folding ASCII characters.
+
+Prototype:
+
+   char *std_striends(const char* cpsz, const char* cpszSuffix);
+
+Parameters:
+   cpsz: string to test
+   cpszSuffix: suffix to test for
+
+Return Value:
+   the first character of cpsz+std_strlen(cpsz)-std_strlen(cpszSuffix)
+     if cpsz ends with cpszSuffix.  NULL otherwise.
+
+=======================================================================
+
+std_strbegins()
+
+Description:
+   The std_strbegins() tests whether a string begins with a particular
+   prefix string.
+
+Prototype:
+
+   char *std_strbegins(const char* cpsz, const char* cpszPrefix);
+
+Parameters:
+   cpsz: string to test
+   cpszPrefix: prefix to test for
+
+Return Value:
+   cpsz + std_strlen(cpszPrefix) if cpsz does begin with cpszPrefix,
+     NULL otherwise
+
+=======================================================================
+
+std_stribegins()
+
+Description:
+   The std_stribegins() tests whether a string begins with a particular
+   prefix string, case-folding ASCII characters.
+
+Prototype:
+
+   char *std_stribegins(const char* cpsz, const char* cpszPrefix);
+
+Parameters:
+   cpsz: string to test
+   cpszPrefix: prefix to test for
+
+Return Value:
+   cpsz + std_strlen(cpszPrefix) if cpsz does begin with cpszPrefix,
+     NULL otherwise
+
+
+=======================================================================
+
+std_strcspn()
+
+Description:
+   The std_strcspn() function searches s, a NUL-terminated string, for
+   the first occurrence of any characters in cpszSrch, a NUL-terminated
+   list of characters. This function returns the length of the longest
+   initial substring of s which consists of characters not present in
+   cpszSrch.
+
+Prototype:
+
+   int std_strcspn(const char* s, const char* cpszSrch);
+
+Parameters:
+   s: string to search
+   cpszSrch: a list of characters to search for
+
+Return Value:
+   The index into the string s of the first occurrence of any of the
+   characters in cpszSrch. If no match is found, then index of the
+   terminating NUL character is returned.
+
+See Also:
+   std_strspn, std_strchr, std_strchrs
+
+=======================================================================
+
+std_strspn()
+
+Description:
+   The std_strspn() functions searches s, a NUL-terminated string, for
+   the first occurrence of a character that matches none of the
+   characters in cpszSrch, a NUL-terminated list of characters. This
+   function returns the length of the longest initial substring of s
+   which consists of characters present in cpszSrch.
+
+Prototype:
+
+   int std_strspn(const char* s, const char* cpszSrch);
+
+Parameters:
+   s: string to search
+   cpszSrch: a list of characters to search for
+
+Return Value:
+   The index into the string s of the first occurrence of any character
+   that matches none of the characters in cpszSrch. If all characters
+   in s are present in cpszSrch, the index of the terminating NUL
+   character is returned.
+
+See Also:
+   std_strcspn, std_strchr, std_strchrs
+
+=======================================================================
+
+std_wstrlcpy()
+
+Description:
+
+   The std_wstrlcpy() function copies a string.  It is equivalent to
+   str_strlcpy() except that it operates on wide (16-bit) character strings.
+   See std_strlcpy() for details.
+
+
+Prototype:
+
+   int std_wstrlcpy(AECHAR *pcDest, const AECHAR *pszSrc, int nDestSize);
+
+Parameters:
+   pcDst: destination string
+   pszSrc: source string
+   int nDestSize: size of pcDest __in AECHARs__
+
+Return Value:
+   Returns the length of the string (in AECHARs) it tried to create,
+   which is same as length of pszSrc.
+
+   Example:
+
+   {
+      AECHAR buf[64];
+      if (std_wstrlcpy(buf, file_name, STD_ARRAY_SIZE(buf)) >=
+          STD_ARRAY_SIZE(buf)) {
+         //Truncated -- Handle overflow....
+      }
+   }
+
+See Also:
+   std_wstrlcat
+
+=======================================================================
+
+std_wstrlcat()
+
+Description:
+
+   The std_wstrlcat() function concatenates two strings.  It is equivalent to
+   std_strlcat() except that it operates on wide (16-bit) character strings.
+   See std_strlcat() for more information.
+
+Prototype:
+   int std_wstrlcat(AECHAR *pcDst, const AECHAR *pszSrc, int nDestSize)
+
+Parameters:
+   pcDst[out]: Destination string
+   pcSrc :     Source string
+   nDestSize:  Size of the destination buffer in AECHARs
+
+Return Value:
+   Returns the length of the string (in AECHARs) it tried to create,
+   which is same as length of pszSrc + the length of pszDest.
+
+   Example:
+
+   {
+      char buf[64];
+      if (std_wstrlcat(buf, file_name, STD_ARRAY_SIZE(buf)) >=
+          STD_ARRAY_SIZE(buf)) {
+         //Truncated -- Handle overflow....
+      }
+   }
+
+See Also:
+   std_wstrlcpy
+
+=======================================================================
+
+std_wstrncmp()
+
+Description:
+
+   The std_wstrncmp() function compares up to a specified number of bytes
+   in two NUL-terminated strings. It is equivalent to std_strncmp() except
+   that it operates on wide (16-bit) character strings.
+
+Prototype:
+   int std_wstrncmp(const AECHAR* s1, const AECHAR* s2, int nLen);
+
+Parameters:
+   s1, s2: strings to compare
+   n: maximum number of AECHARs to compare.  if either s1 or s2 is
+      shorter than n, the function terminates there.
+
+Return Value:
+   0 if strings are the same ~
+   < 0 if s1 is less than s2 ~
+   > 0 if s1 is greater than s2
+
+See Also:
+   std_strncmp
+
+=======================================================================
+
+std_wstrcmp()
+
+Description:
+   The std_wstrcmp() compares two NUL-terminated strings. It is equivalent
+   to std_strncmp() except that it operates on wide (16-bit) character
+   strings. Comparison is strictly by byte values with no character set
+   interpretation.
+
+Prototype:
+
+   int std_wstrcmp(const AECHAR* s1, const AECHAR* s2);
+
+Parameters:
+   s1, s2: strings to compare
+
+Return Value:
+   0 if strings are the same ~
+   < 0 if s1 is less than s2 ~
+   > 0 if s1 is greater than s2
+
+See Also:
+   std_strcmp
+
+=======================================================================
+
+std_wstrchr()
+
+Description:
+   This function is the wide string counterpart of std_strchr().
+   The std_wstrchr() finds the first occurrence of a character in a
+   NUL-terminated wide (16-bit) character string.
+
+Prototype:
+
+   AECHAR* std_wstrchr(const AECHAR* s, AECHAR ch);
+
+Parameters:
+   s: string to search
+   ch: char to search for
+
+Return Value:
+   pointer to first occurrence, NULL if not found
+
+See Also:
+   std_strchr
+
+=======================================================================
+
+std_wstrrchr()
+
+Description:
+   This function is the wide string counterpart of std_strrchr().
+   The std_wstrrchr() finds the last occurrence of a character in a
+   NUL-terminated wide (16-bit) character string.
+
+Prototype:
+
+   AECHAR* std_wstrrchr(const AECHAR* s, AECHAR ch);
+
+Parameters:
+   s: string to search
+   ch: char to search for
+
+Return Value:
+   pointer to last occurrence, NULL if not found
+
+See Also:
+   std_strrchr
+
+=======================================================================
+
+std_makepath()
+
+Description:
+   The std_makepath() constructs a path from a directory portion and a file
+   portion, using forward slashes, adding necessary slashes and deleting extra
+    slashes.  This function guarantees NUL-termination of pszDest
+
+Prototype:
+
+   int std_makepath(const char *cpszDir, const char *cpszFile,
+                    char *pszDest, int nDestSize)
+
+Parameters:
+   cpszDir: directory part
+   cpszFile: file part
+   pszDest: output buffer
+   nDestSize: size of output buffer in bytes
+
+Return Value:
+   the required length to construct the path, not including
+   NUL-termination
+
+Comments:
+   The following list of examples shows the strings returned by
+   std_makepath() for different paths.
+
+Example:
+
+   cpszDir  cpszFile  std_makepath()
+   ""        ""           ""
+   ""        "/"          ""
+   "/"       ""           "/"
+   "/"       "/"          "/"
+   "/"       "f"          "/f"
+   "/"       "/f"         "/f"
+   "d"       "f"          "d/f"
+   "d/"      "f"          "d/f"
+   "d"       "/f"         "d/f"
+   "d/"      "/f"         "d/f"
+
+See Also:
+   std_splitpath
+
+=======================================================================
+
+std_splitpath()
+
+Description:
+   The std_splitpath() finds the filename part of a path given an inclusive
+   directory, tests for cpszPath being in cpszDir. The forward slashes are
+   used as directory delimiters.
+
+Prototype:
+
+   char *std_splitpath(const char *cpszPath, const char *cpszDir);
+
+Parameters:
+   cpszPath: path to test for inclusion
+   cpszDir: directory that cpszPath might be in
+
+Return Value:
+   the part of cpszPath that actually falls beneath cpszDir, NULL if
+   cpszPath is not under cpszDir
+
+Comments:
+   The std_splitpath() is similar to std_strbegins(), but it ignores trailing
+   slashes on cpszDir, and it returns a pointer to the first character of
+   the subpath.
+
+   The return value of std_splitpath() will never begin with a '/'.
+
+   The following list of examples shows the strings returned by
+   std_splitpath() for different paths.
+
+Example:
+   cpszPath cpszDir  std_splitpath()
+   ""        ""           ""
+   ""        "/"          ""
+   "/"       ""           ""
+   "/"       "/"          ""
+   "/d"      "d"          null
+   "/d"      "/"          "d"
+   "/d/"     "/d"         ""
+   "/d/f"    "/"          "d/f"
+   "/d/f"    "/d"         "f"
+   "/d/f"    "/d/"        "f"
+
+See Also:
+   std_makepath
+
+=======================================================================
+
+std_cleanpath()
+
+Description:
+   The std_cleanpath() removes double slashes, ".", and ".." from
+   slash-delimited paths,. It operates in-place.
+
+Prototype:
+
+   char *std_cleanpath(char *pszPath);
+
+Parameters:
+   pszPath[in/out]: path to "clean"
+
+Return Value:
+   pszPath
+
+Comments:
+   Passing an "fs:/" path to this function may produce undesirable
+   results.  This function assumes '/' is the root.
+
+Examples:
+       pszPath  std_cleanpath()
+         "",           "",
+         "/",          "/",
+
+         // here"s, mostly alone
+         "./",         "/",
+         "/.",         "/",
+         "/./",        "/",
+
+         // "up"s, mostly alone
+         "..",         "",
+         "/..",        "/",
+         "../",        "/",
+         "/../",       "/",
+
+         // fun with x
+         "x/.",        "x",
+         "x/./",       "x/",
+         "x/..",       "",
+         "/x/..",      "/",
+         "x/../",      "/",
+         "/x/../",     "/",
+         "/x/../..",   "/",
+         "x/../..",    "",
+         "x/../../",   "/",
+         "x/./../",    "/",
+         "x/././",     "x/",
+         "x/.././",    "/",
+         "x/../.",     "",
+         "x/./..",     "",
+         "../x",       "/x",
+         "../../x",    "/x",
+         "/../x",      "/x",
+         "./../x",     "/x",
+
+         // double slashes
+         "//",         "/",
+         "///",        "/",
+         "////",       "/",
+         "x//x",       "x/x",
+
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+
+=======================================================================
+
+std_basename()
+
+Description:
+   The std_basename() returns the filename part of a string,
+   assuming '/' delimited filenames.
+
+Prototype:
+
+   char *std_basename(const char *cpszPath);
+
+Parameters:
+   cpszPath: path of interest
+
+Return Value:
+   pointer into cpszPath that denotes part of the string immediately
+   following the last '/'
+
+Examples:
+     cpszPath       std_basename()
+         ""            ""
+         "/"           ""
+         "x"           "x"
+         "/x"          "x"
+         "y/x"         "x"
+         "/y/x"        "x"
+
+ See Also:
+    None
+
+=======================================================================
+
+std_rand_next()
+
+Description:
+  The std_rand_next() generates pseudo-random bytes.
+
+Prototype:
+
+   unsigned std_rand_next(unsigned uRand);
+
+Parameters:
+   uRand: a seed for the pseudo-random generator
+
+Return Value:
+   the next value in the generator from uRand
+
+Comments:
+   for best results, this function should be called with its last
+   generated output.
+
+   This is an example of code to generate 256 bytes of pseudo-random data.
+
+   This is not crypto quality and should not be used for key generation
+   and the like.
+
+Example:
+   {
+       unsigned rand_buf[256/sizeof(unsigned)];
+       int      i;
+       unsigned uLast = std_rand_next(uCurrentTime);
+       for (i = 0; i < STD_ARRAY_SIZE(rand_buf); i++) {
+          rand_buf[i] = (uLast = std_rand_next(uLast));
+       }
+   }
+
+See Also:
+   std_rand()
+
+=======================================================================
+
+std_rand()
+
+Description:
+  The std_rand() functions generates pseudo-random bytes and places it
+  in an output buffer of specified size.
+
+Prototype:
+
+   uint32 std_rand(uint32 uSeed, byte* pDest, int nSize);
+
+Parameters:
+   uSeed: A seed for the pseudo-random generator
+   pDest: The output buffer where the random bytes are placed.
+   nSize: The size in bytes of pDest.
+
+Return Value:
+   The new seed value that can be used in a subsequent call to
+   std_rand().
+
+Comments:
+
+   std_rand() is a linear congruent psuedo-random number generator that
+   is seeded using the input seed. This makes the ouput predictable if
+   you can determine (or influence) the seed value used. Furthermore,
+   the random sequence of bytes generated by two different calls to this
+   function will be identical if both the calls use the same seed value.
+
+   This is not crypto quality and should not be used for key generation
+   and other cryptographic uses.
+
+See Also:
+   std_rand_next()
+
+=======================================================================
+
+std_CopyLE()
+
+Description:
+
+   The std_CopyLE() function copies data while translating numeric values
+   between host byte ordering and "little endian" byte ordering.
+
+   pvDest and pvSrc are NOT required to be 16 or 32-bit word aligned.
+
+   Behavior is undefined when the destination and source arrays overlap,
+   except in the special case where pvDest and pvSrc are equal.  In that case,
+   std_CopyLE() modifies the buffer in-place.
+
+   When the target byte ordering (little endian) matches the host byte
+   ordering, in-place translations reduce to a no-op, and copies are
+   delegated directly to std_memmove().
+
+
+Prototype:
+   int std_CopyLE(void *pvDest, int nDestSize,
+                  const void *pvSrc,  int nSrcSize,
+                  const char *pszFields);
+
+Parameters:
+   pvDest:    Pointer to destination buffer.
+   nDestSize: Size of the destination buffer.
+   pvSrc:     Pointer to buffer containing source data.
+   nSrcSize:  Size of source data.
+   pszFields: Description of the fields that comprise the source data.
+
+              Each field size is given by a positive decimal integer or one of
+              the following characters: "S", "L", "Q", or "*".  The letters
+              denote fields that should be converted to the desired byte
+              ordering:
+
+===pre>
+                S : a 2 byte (16 bit) value.
+                L : a 4 byte (32 bit) value.
+                Q : a 8 byte (64 bit) value.
+===/pre>
+
+              An integer gives a number of bytes and "*" represents the
+              remainder of the pvSrc[] buffer.  No reordering is performed on
+              data in these fields.
+
+              Comparisons are case-sensitive.  Behavior is undefined when
+              other characters are supplied in pszFields.
+
+              For example: "L12S*" would be appropriate to copy a structure
+              containing a uint32 followed by a 12 byte character array,
+              followed by a uint16, followed by an arbitrary amount of
+              character data.
+
+              If nSrcSize is greater than the structure size (total of all the
+              sizes in pszFields[]) then pvSrc[] is treated as an array of
+              structures, each of which is described by pszFields.
+
+Return Value:
+
+   The number of bytes actually copied or translated in-place.  This will be
+   the smaller of nDestSize and nSrcSize, or zero if one of them are negative.
+
+
+=======================================================================
+
+std_CopyBE()
+
+Description:
+
+   The std_CopyBE() function has the same semantics as std_CopyLE() except it
+   copies between host byte ordering and big-endian ("network") byte order.
+
+   See std_CopyLE() for more details.
+
+
+Prototype:
+   void *std_CopyBE(void *pvDest, const void *pvSrc,
+                           int cbDest, int nItems, const char *pszFields);
+
+Parameters:
+   pvDest:    Pointer to destination buffer.
+   nDestSize: Size of the destination buffer.
+   pvSrc:     Pointer to buffer containing source data.
+   nSrcSize:  Size of source data.
+   pszFields: Description of the fields that comprise the source data,
+              as defined in std_CopyLE.
+
+Return Value:
+
+   The number of bytes actually copied or translated in-place.  This will be
+   the smaller of nDestSize and nSrcSize, or zero if one of them are negative.
+
+=======================================================================
+
+std_swapl()
+
+Description:
+   The std_swapl() changes endianness of an unsigned long.
+
+Prototype:
+
+   unsigned long std_swapl(unsigned long ul)
+
+Parameters:
+   ul: input unsigned long
+
+Return Value:
+   ul, reversed in byte-ordering
+
+=======================================================================
+
+std_swaps()
+
+Description:
+   The std_swaps() changes endianness of an unsigned short.
+
+Prototype:
+
+   unsigned short std_swaps(unsigned short us)
+
+Parameters:
+   us: input unsigned short
+
+Return Value:
+   us, reversed in byte-ordering
+
+=======================================================================
+
+std_letohs()
+
+Description:
+   The std_letohs() changes a short from little-endian to host byte order.
+
+Prototype:
+
+   unsigned short std_letohs(unsigned short us)
+
+Parameters:
+   us: short to convert
+
+Return Value:
+   us converted from little-endian to host byte order.  If the
+     host is little endian, just returns us
+
+=======================================================================
+
+std_htoles()
+
+Description:
+   The std_htoles() converts a short from host byte-order to little-endian.
+
+Prototype:
+
+   unsigned short std_htoles(unsigned short us)
+
+Parameters:
+   us: short to convert
+
+Return Value:
+   us converted from host byte order to little-endian.  If the
+   host is little endian, just returns us
+
+=======================================================================
+
+std_letohl()
+
+Description:
+   The std_letohl() changes a long from little-endian to host byte order.
+
+Prototype:
+
+   unsigned long std_letohl(unsigned long ul)
+
+Parameters:
+   ul: long to convert
+
+Return Value:
+   ul converted from little-endian to host byte order.  If the
+   host is little endian, just returns ul
+
+=======================================================================
+
+std_htolel()
+
+Description:
+   The std_htolel() converts a long from host byte-order to little-endian.
+
+Prototype:
+
+   unsigned long std_htolel(unsigned long ul)
+
+Parameters:
+   ul: long to convert
+
+Return Value:
+   ul converted from host byte order to little-endian.  If the
+   host is little endian, just returns ul.
+
+
+=======================================================================
+
+std_ntohs()
+
+Description:
+   The std_ntohs() changes a short from big-endian to host byte order.
+
+Prototype:
+
+   unsigned short std_ntohs(unsigned short us)
+
+Parameters:
+   us: short to convert
+
+Return Value:
+   us converted from big-endian to host byte order.  If the
+   host is big endian, just returns us.
+
+=======================================================================
+
+std_htons()
+
+Description:
+   The std_htons() converts a short from host byte-order to big-endian.
+
+Prototype:
+
+   unsigned short std_htons(unsigned short us)
+
+Parameters:
+   us: short to convert
+
+Return Value:
+   us converted from host byte order to big-endian.  If the
+   host is big endian, just returns us.
+
+=======================================================================
+
+std_ntohl()
+
+Description:
+   The std_ntohl() changes a long from big-endian to host byte order.
+
+Prototype:
+
+   unsigned long std_ntohl(unsigned long ul)
+
+Parameters:
+   ul: long to convert
+
+Return Value:
+   ul converted from big-endian to host byte order.  If the
+   host is big endian, just returns ul.
+
+=======================================================================
+
+std_htonl()
+
+Description:
+   The std_htonl() converts a long from host byte-order to big-endian.
+
+Prototype:
+
+   unsigned long std_htonl(unsigned long ul)
+
+Parameters:
+   ul: long to convert
+
+Return Value:
+   ul converted from host byte order to big-endian.  If the
+   host is big endian, just returns ul.
+
+
+=======================================================================
+
+std_strlprintf()
+
+Description:
+
+   The functions std_strlprintf() and std_vstrlprintf() write formatted
+   output to a string.  These functions guarantee NUL-termination of
+   the output buffer when its size is greater than zero.
+
+   A format string is copied to the output buffer, except for conversion
+   specifiers contained within the format string.  Conversion specifiers
+   begin with a "%" and specify some action that consumes an argument from
+   the argument list.
+
+   Conversion specifiers have the following form:
+===pre>
+       %[FLAGS] [WIDTH] [.PRECISION] [TYPE] CONV
+===/pre>
+
+   CONV is the only required field.  It is always a single character,
+   and determines the action to be taken.  Supported values are:
+
+===pre>
+    CONV | Description
+   ======|=======================================================
+     c   | Output a single character.
+         |
+     s   | Output a NUL-terminated single-byte character string.
+         |
+    d, i | Ouptut a signed decimal integer.
+         |
+     u   | Output an unsigned decimal integer.
+         |
+     o   | Output an unsigned octal integer.
+         |
+     x   | Output an unsigned hexadecimal integer, using
+         | lower case digits.
+         |
+     X   | Output an unsigned hexadecimal integer, using
+         | upper case digits.
+         |
+     p   | Output a pointer value as eight hexadecimal digits,
+         | using upper case digits.
+===/pre>
+
+   The next argument from the argument list supplies the value to be
+   formatted and output.
+
+   FLAGS, WIDTH, and PRECISION can modify the formatting of the value.
+
+   FLAGS consists of one or more of the following characters:
+
+===pre>
+   Flag | Meaning
+   =====|=================================================================
+     +  | Prefix positive numbers with "+" (%d and %i only).
+   -----|-----------------------------------------------------------------
+     -  | When padding to meet WIDTH, pad on the right.
+   -----|-----------------------------------------------------------------
+     0  | Pad with '0' characters when padding on the left to meet WIDTH.
+   -----|-----------------------------------------------------------------
+   blank| Prefix positive numbers with " " (%d and %i only).
+   space|
+   -----|-----------------------------------------------------------------
+     #  | With %x or %X: prefixes non-zero values with "0x"/"0X".
+        | With %o, ensure the value begins with "0" (increasing PRECISION
+        |    if necessary).
+        | Ignored for all other CONV specifiers.
+   -----|-----------------------------------------------------------------
+===/pre>
+
+   WIDTH is an unsigned decimal integer or the character "*".
+
+   WIDTH gives the minimum number of characters to be written.  The
+   formatted value will be padded with spaces until the minimum size is
+   met; it never causes a value to be truncated The sign of the WIDTH
+   integer selects between left and right padding.  Padding will be on
+   the left unless the "-" flag is specified.
+
+   When "*" is used, an 'int' argument is consumed from the argument
+   list and used as the WIDTH.  A negative argument specifies padding on
+   the right, and its absolute value gives the amount of padding.
+
+   If the "0" flags is specified, any padding on the left will consist
+   of "0" characters.  An exception to this rule is that the "0" flag is
+   ignored when precision is specified for a numeric value.
+
+   PRECISION is a non-negative decimal integer or "*" preceded by ".".
+
+   When PRECISION accompanies any of the numeric conversions, it
+   specifies the minimum number of digits to output.  Values are padded
+   on the left with '0' to meet the specified size.  PRECISION defaults
+   to 1 for numbers.
+
+   When PRECISION accompanies other conversions, it specifies the
+   maximum number of characters from the value to output.  The value
+   will be truncated to ensure that at most PRECISION characters are
+   output.
+
+   TYPE provides information about the type of arguments.  This is used
+   to determine the size of integer arguments. Values larger than 'int'
+   can be properly obtained from the argument list.  Their behavior
+   should be considered undefined for CONV operations other than integer
+   formatting.
+
+===pre>
+    TYPE  | Meaning
+   =======|=====================
+     hh   | sizeof(char)
+   -------|---------------------
+      h   | sizeof(short)
+   -------|---------------------
+      l   | sizeof(long)
+   -------|---------------------
+    L, ll | sizeof(long long)
+   -------|---------------------
+      j   | sizeof(int64)
+   -------|---------------------
+      z   | sizeof(size_t)
+   -------|---------------------
+===/pre>
+
+   For 64-bit integers, "ll" may be the most widely-supported type
+   specifier in other printf implementation, but "j" has been introduced
+   in ISO C99. This implementation supports both.
+
+   Note that arguments to variadic functions are promoted to 'int' when
+   smaller than 'int', so 'h' and 'hh' have no observable effect.
+   Static analysis tools that understand standard format string syntax
+   may use this information for other purposes.
+
+Prototype:
+
+   int std_strlprintf(char *pszDest, int nDestSize,
+                      const char *pszFmt, ...);
+Parameters:
+   pszDest [out]: output buffer, where output will be placed
+   nDestSize:     size of pszDest in bytes
+   pszFmt:        format string
+
+Return Value:
+
+   The size required to hold the entire untruncated output, NOT
+   including NUL-termination.
+
+Comments:
+
+   Notable omissions from std_strlprintf() are lack of support for
+   floating point and lack of support for "%n".
+
+Side Effects:
+   None
+
+See Also:
+   None
+
+=======================================================================
+
+std_vstrlprintf()
+
+Description:
+
+  The std_vstrlprintf() is documented with std_strlprintf(), it's the
+  vector form of std_strlprintf().  See std_strlprintf() for a
+  more complete description.
+
+Prototype:
+   int std_vstrlprintf(char *pszDest, int nDestSize,
+                       const char *pszFmt, AEEVaList args);
+
+Parameters:
+   pszDest [out]: output buffer, where output will be placed
+   nDestSize:     size of pszDest in bytes
+   pszFmt:        format string
+   args:          arguments
+
+
+=======================================================================
+
+std_snprintf()
+
+Description:
+
+   The functions std_snprintf() and std_vsnprintf() are similar to
+   std_strlprintf and std_vstrlprintf that write formatted output to a
+   string. Unlike std_strlprintf, std_snprintf also support the floating
+   point conversion specifiers. These functions guarantee NUL-termination
+   of the output buffer when its size is greater than zero.
+
+   A format string is copied to the output buffer, except for conversion
+   specifiers contained within the format string.  Conversion specifiers
+   begin with a "%" and specify some action that consumes an argument from
+   the argument list.
+
+   Conversion specifiers have the following form:
+===pre>
+       %[FLAGS] [WIDTH] [.PRECISION] [TYPE] CONV
+===/pre>
+
+   CONV is the only required field.  It is always a single character,
+   and determines the action to be taken.  For a detailed description of
+   conversion sepcifiers, please refer to the documentation of
+   std_strlprintf(). Here. we only provide description of these fields
+   as it applies to the additional CONV values supported by
+   std_snprintf().
+
+   In addition to the values for CONV supported by std_strlprintf, this
+   function supports the following values:
+
+===pre>
+    CONV | Description
+   ======|=======================================================
+    e, E | Outputs a double value representing a floating point
+         | number in the style [-]d.ddd e±dd, where there is one
+         | digit (which is nonzero if the argument is nonzero)
+         | before the decimal-point character and the number of
+         | digits after it is equal to the precision. If the
+         | precision is missing, it is taken as 6. If the precision
+         | is zero and the # flag is not specified, no decimal-point
+         | character appears. The value is rounded to the appropriate
+         | number of digits. The E conversion specifier produces a
+         | number with E instead of e introducing the exponent. The
+         | exponent always contains at least two digits, and only as
+         | many more digits as necessary to represent the exponent.
+         | If the value is zero, the exponent is zero.
+         |
+    f, F | Outputs a double value representing a floating point
+         | number in the style [-]ddd.ddd, where the number of
+         | digits after the decimal-point character is equal to the
+         | precision specification. If the precision is missing, it
+         | is taken as 6. If the precision is zero and the # flag is
+         | not specified, no decimal-point character appears. If a
+         | decimal-point character appears, at least one digit
+         | appears before it. The value is rounded to the appropriate
+         | number of digits.
+         |
+    g, G | Outputs a double value representing a floating point
+         | number in the style f or e (or in style F or E in the case
+         | of a G conversion specifier), with the precision specifying
+         | the number of significant digits. If the precision is zero,
+         | it is taken as 1. The style used depends on the value
+         | converted. Style e (or E) is used only if the exponent
+         | resulting from such a conversion is less than -4 or greater
+         | than or equal to the precision. Trailing zeros are removed
+         | from the fractional portion of the result unless the # flag
+         | is specified; a decimal-point character appears only if it
+         | is followed by a digit.
+         |
+    a, A | Outputs a double value representing a floating point
+         | number in the style [-]0xh.hhhh p±d, where there is one
+         | non-zero hexadecimal digit before the decimal-point
+         | character and the number of hexadecimal digits after it is
+         | equal to the precision. If the precision is missing then
+         | the precision is assumed to be sufficient for an exact
+         | representation of the value, except that trailing zeros
+         | may be omitted. If the precision is zero and the # flag is
+         | not specified, no decimal point character appears. The
+         | letters 'abcdef' are used for '%a' conversion and the
+         | letters ABCDEF for '%A' conversion. The '%A' conversion
+         | specifier produces a number with 'X' and 'P' instead of 'x'
+         | and 'p'. The exponent always contains at least one digit,
+         | and only as many more digits as necessary to represent the
+         | decimal exponent of 2. If the value is zero, the exponent
+         | is zero.
+         |
+===/pre>
+
+   For 'e', 'f', 'g' and 'a' convervsion specifiers, a double argument
+   representing an infinity is converted in to the style '[-]inf' and
+   a double argument representing a NaN is converted in to the stlye
+   'nan'. The 'E', 'F', 'G' and 'A' conversion specifiers result in
+   'INF' or 'NAN' instead of 'inf' or 'nan', respectively.
+
+Prototype:
+
+   int std_snprintf(char *pszDest, int nDestSize,
+                    const char *pszFmt, ...);
+Parameters:
+   pszDest [out]: output buffer, where output will be placed
+   nDestSize:     size of pszDest in bytes
+   pszFmt:        format string
+
+Return Value:
+
+   The size required to hold the entire untruncated output, NOT
+   including NUL-termination.
+
+Comments:
+
+   Notable omissions from std_strlprintf() lack of support for "%n".
+
+Side Effects:
+   None
+
+See Also:
+   std_strlprintf()
+
+=======================================================================
+
+std_vsnprintf()
+
+Description:
+
+  The std_vsnprintf() is documented with std_snprintf(), it's the
+  vector form of std_snprintf(). See std_snprintf() for a more complete
+  description.
+
+Prototype:
+   int std_vsnprintf(char *pszDest, int nDestSize,
+                     const char *pszFmt, AEEVaList args);
+
+Parameters:
+   pszDest [out]: output buffer, where output will be placed
+   nDestSize:     size of pszDest in bytes
+   pszFmt:        format string
+   args:          arguments
+
+
+=======================================================================
+
+std_scanul()
+
+Description:
+
+    The std_scanul() converts an ASCII representation of a number to an unsigned
+    long.  It expects strings that match the following pattern:
+===pre>
+         spaces [+|-] digits
+===/pre>
+
+    'Spaces' is zero or more ASCII space or tab characters.
+
+    'Digits' is any number of digits valid in the radix.  Letters 'A' through
+    'Z' are treated as digits with values 10 through 35.  'Digits' may begin
+    with "0x" when a radix of 0 or 16 is specified.
+
+    Upper and lower case letters can be used interchangeably.
+
+
+Prototype:
+
+    uint32 std_scanul( const char *pchBuf, int nRadix, const char **ppchEnd,
+                       int *pnError)
+
+Parameters:
+
+    pchBuf [in] : the start of the string to scan.
+
+    nRadix [in] : the numeric radix (or base) of the number.  Valid values are
+                  2 through 36 or zero, which implies auto-detection.
+                  Auto-detection examines the digits field.  If it begins with
+                  "0x", radix 16 is selected.  Otherwise, if it begins with
+                  "0" radix 8 is selected.  Otherwise, radix 10 is selected.
+
+    ppchEnd [out] : if ppchEnd is not NULL, *ppchEnd points to the first
+                    character that did not match the expected pattern shown
+                    above, except on STD_BADPARAM and STD_OVERFLOW when it is
+                    set to the start of the string.
+
+    pnError [out] : If pnError is not NULL, *pnError holds the error code,
+                    which is one of the following:
+~
+        0 : Numeric value is from 0 to MAX_UINT32.
+
+        STD_NEGATIVE : The scanned value was negative and its absolute value was
+                       from 1 to MAX_UINT32.  The result is the negated value
+                       (cast to a uint32).
+
+        STD_NODIGITS : No digits were found.  The result is zero.
+
+        STD_OVERFLOW : The absolute value exceeded MAX_UINT32.  The result
+                       is set to MAX_UINT32 and *ppchEnd is set to pchBuf.
+
+        STD_BADPARAM : An improper value for nRadix was received.  The result
+                       is set to zero, and *ppchEnd is set to pchBuf.
+*
+
+Return Value:
+
+    The converted numeric result.
+
+Comments:
+
+   The std_scanul() is similar to ANSI C's strtoul() but differs in the following
+   respects:
+
+     1. It returns an error/success code.  strtoul() results are ambiguous
+        unless the caller sets errno to zero before calling it.
+
+     2. std_scanul() is free of references to current locale and errno.  Some
+        strtoul() implementations use locale; some don't.
+
+     3. It provides more complete reporting of range underflow.  strtoul()
+        does not distinguish between "-1" and "0xFFFFFFFF", and underflow is
+        poorly defined.
+
+     4. std_scanul() reports a "no digits" error code to distinguish "0" from
+        whitespace, "+", etc..
+
+See Also:
+
+   std_scanull()
+
+=======================================================================
+
+std_scanull()
+
+Description:
+
+    The std_scanull() converts an ASCII representation of a number to an
+    unsigned long long.  It expects strings that match the following pattern:
+===pre>
+         spaces [+|-] digits
+===/pre>
+
+    'Spaces' is zero or more ASCII space or tab characters.
+
+    'Digits' is any number of digits valid in the radix.  Letters 'A' through
+    'Z' are treated as digits with values 10 through 35.  'Digits' may begin
+    with "0x" when a radix of 0 or 16 is specified.
+
+    Upper and lower case letters can be used interchangeably.
+
+
+Prototype:
+
+    uint64 std_scanull(const char *pchBuf, int nRadix, const char **ppchEnd,
+                       int *pnError)
+
+Parameters:
+
+    pchBuf [in] : the start of the string to scan.
+
+    nRadix [in] : the numeric radix (or base) of the number.  Valid values are
+                  2 through 36 or zero, which implies auto-detection.
+                  Auto-detection examines the digits field.  If it begins with
+                  "0x", radix 16 is selected.  Otherwise, if it begins with
+                  "0" radix 8 is selected.  Otherwise, radix 10 is selected.
+
+    ppchEnd [out] : if ppchEnd is not NULL, *ppchEnd points to the first
+                    character that did not match the expected pattern shown
+                    above, except on STD_BADPARAM and STD_OVERFLOW when it is
+                    set to the start of the string.
+
+    pnError [out] : If pnError is not NULL, *pnError holds the error code,
+                    which is one of the following:
+~
+        0 : Numeric value is from 0 to MAX_UINT64.
+
+        STD_NEGATIVE : The scanned value was negative and its absolute value was
+                       from 1 to MAX_UINT64.  The result is the negated value
+                       (cast to a uint64).
+
+        STD_NODIGITS : No digits were found.  The result is zero.
+
+        STD_OVERFLOW : The absolute value exceeded MAX_UINT64.  The result
+                       is set to MAX_UINT64 and *ppchEnd is set to pchBuf.
+
+        STD_BADPARAM : An improper value for nRadix was received.  The result
+                       is set to zero, and *ppchEnd is set to pchBuf.
+*
+
+Return Value:
+
+    The converted numeric result.
+
+Comments:
+
+   The std_scanull() is similar to ANSI C's strtoull() but differs in the following
+   respects:
+
+     1. It returns an error/success code.  strtoull() results are ambiguous
+        unless the caller sets errno to zero before calling it.
+
+     2. std_scanull() is free of references to current locale and errno.  Some
+        strtoull() implementations use locale; some don't.
+
+     3. It provides more complete reporting of range underflow.  strtoul()
+        does not distinguish between "-1" and "0xFFFFFFFFFFFFFFFF", and underflow
+        is poorly defined.
+
+     4. std_scanull() reports a "no digits" error code to distinguish "0" from
+        whitespace, "+", etc..
+
+See Also:
+
+   std_scanul()
+
+=======================================================================
+
+std_qsort()
+
+Description:
+
+  An implementation of the quicksort algorithm, a massively recursive,
+  in-place sorting algorithm for an array.
+
+  The contents of the array are sorted in ascending order according to
+  the comparison function pointed to by pfnCompare.
+
+  pfnCompare must return a value less than, equal to, or
+  greater than zero if the first argument is considered to be
+  less than, equal to, or greater than the second, respectively.
+
+  std_qsort() is not a stable sort.
+
+Prototype:
+   void std_qsort(void* pElems, int nNumElems, int nElemWidth,
+                  int (*pfnCompare)(void*, const void*, const void*),
+                  void* pCompareCx);
+
+
+Parameters:
+   pElems: array of elements to be sorted in place.  It's size
+           must be nNumElems * nElemWidth in bytes.
+   nNumElems: number of elements in pElems
+   nElemWidth: the width, in bytes of each element of pElems
+   pfnCompare: callback comparison function, should return 0, less than
+               zero or greater than zero if the left comparand is equal to, less
+               than, or greater than, the right comparand, respectively.
+   pCompareCx: the context passed as the first parameter by pfnCompare
+
+Return Value:
+   None
+
+Comments:
+   If nElemWidth is 2, 4, or 8, pElems is accessed internally as
+   integer values for the purposes of reading and writing elements.
+   Therefore, pElems must be aligned on a memory boundary compatible
+   with integer access of the array elements.  I.e. if you pass 4 as
+   nElemWidth, *(int*)pElems must succeed.
+
+=======================================================================
+
+std_bisect()
+
+Description:
+
+   Find an element in a sorted array of elements.  Uses a binary
+   search.
+
+Prototype:
+   int std_bisect(const void* pElems, int nNumElems, int nElemWidth,
+                  const void* pElemFind,
+                  int (*pfnCompare)(void*, const void*, const void*),
+                  void* pCompareCx);
+
+Parameters:
+   pElems: array of elements to be searched.  It's size
+           must be nNumElems * nElemWidth in bytes.
+   nNumElems: number of elements in pElems
+   nElemWidth: the width, in bytes of each element of pElems
+   pElemFind: the element value to find in the array
+   pfnCompare: callback comparison function, should return 0, less than
+               zero or greater than zero if the left comparand is equal to, less
+               than, or greater than, the right comparand, respectively.
+   pCompareCx: the context passed as the first parameter by pfnCompare
+
+Return Value:
+   index of the element such that pElems[index] <= elem < pElems[index + 1]
+   nNumElems if elem is greater than all the elements in the list
+   0 if the elem is less than or equal to the all the elements in the list
+
+=======================================================================
+
+std_merge()
+
+Description:
+
+   Merge two sorted arrays into another array.
+
+Prototype:
+   void std_merge(void* vpDst, int nDst,
+                  const void* vpA, int nA,
+                  const void* vpB, int nB,
+                  int nElemWidth,
+                  int (*pfnCompare)(void*, const void*, const void*),
+                  void* pCompareCx);
+
+Parameters:
+   vpDst: destination array.  It's size must be nDst * nElemWidth in bytes.
+   nDst: number of elements that vpDst can accomodate
+   vpA: array of elements to be merged,  it's size must be nA * nElemWidth
+         in bytes.
+   nA: number of elements in vpA
+   vpB: array of elements to be merged,  it's size must be nB * nElemWidth
+         in bytes.
+   nB: number of elements in vpB
+   nElemWidth: the width, in bytes of each element of pElems
+   pfnCompare: callback comparison function, should return 0, less than
+               zero or greater than zero if the left comparand is equal to, less
+               than, or greater than, the right comparand, respectively.
+   pCompareCx: the context passed as the first parameter by pfnCompare
+
+Return Value:
+  none
+
+=======================================================================
+
+std_uniq()
+
+Description:
+   Removes duplicate entries from a sorted array.
+
+Prototype:
+   int std_uniq(void* vpElems, int nNumElems, int nElemWidth,
+                int (*pfnCompare)(void*, const void*, const void*),
+                void* pCompareCx);
+
+Parameters:
+   pElems: array of elements to be searched.  It's size
+           must be nNumElems * nElemWidth in bytes.
+   nNumElems: number of elements in pElems
+   nElemWidth: the width, in bytes of each element of pElems
+   pfnCompare: callback comparison function, should return 0, less than
+               zero or greater than zero if the left comparand is equal to, less
+               than, or greater than, the right comparand, respectively.
+   pCompareCx: the context passed as the first parameter by pfnCompare
+
+Return Value:
+   the number of uniq elements left in vpElems
+
+=======================================================================
+
+std_scand()
+
+Description:
+
+   The std_scand() converts the initial portion of an input ASCII string
+   to it's corresponding floating point value. It expects the input
+   string to match the following pattern:
+===pre>
+         <Spaces><Subject String><Rest Of The String>
+===/pre>
+
+   'Spaces' - is zero or more ASCII space or tab characters.
+   'Subject String' - is the part of the input string that represents a
+                      valid floating point constant.
+   'Rest Of The String' - is the remaining sequence of one or more
+                          characters including the terminating null
+                          character of the input string.
+
+   A valid subject string can be one of the following:
+      -- <NAN>, ignoring case. This is interpreted as a quiet NAN.
+      -- [+|-]<INF|INFINITY>, ignoring case. This is interpreted as an
+         infinity.
+      -- [+|-]<Valid Floating Point Number>
+
+   In general, a valid floating poing number can either be a decimal
+   number or an hexadecimal number, and has the following form:
+      <Integral Part>[.[<Fractional Part>]][<Exponent>]
+   where the intergral, fractional and the exponent part may consist of
+   sequence of valid decimal or hexadecimal digits. More specifically:
+
+   For a decimal floating point number:
+      'Integral Part' - <Decimal Digits>
+      'Fractional Part' - <Decimal Digits>
+      'Exponent' - <e|E><Decimal Digits>
+   For a hexadecimal floating point number:
+      'Integral Part' - <Hexadecimal Digits>
+      'Fractional Part' - <Hexadecimal Digits>
+      'Exponent' - <p|P><Decimal Digits>
+
+   where:
+      'Decimal Digits' - is any number of digits in the range [0,10].
+      'Hexadecimal Digits' - is any number of digits in the range [0,10]
+                             or the alphabets A through F.
+      'e','E','p','P' - represent the exponent characters
+
+Prototype:
+
+    double std_scand(const char *pchBuf, const char **ppchEnd);
+
+Parameters:
+
+    pchBuf [in] : the start of the string to scan.
+
+    ppchEnd [out] : if ppchEnd is not NULL, *ppchEnd points to the first
+                    character after the parsed number.
+
+Return Value:
+
+    This function returns the converted numeric result. If the string
+    does not contain a valid floating point number then the function
+    returns zero. If the converted value is outside the range of
+    representable values (overflow), [-]INFINITY is
+    returned. In case of an underflow, the function returns zero.
+
+=======================================================================*/
+
+#endif // AEESTD_H
+
+
diff --git a/inc/HAP_debug.h b/inc/HAP_debug.h
new file mode 100644
index 0000000..c4c2b8c
--- /dev/null
+++ b/inc/HAP_debug.h
@@ -0,0 +1,102 @@
+#ifndef HAP_DEBUG_H
+#define HAP_DEBUG_H
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include "AEEStdDef.h"
+#include <stdarg.h>
+#include <stdio.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#define HAP_LEVEL_LOW       0
+#define HAP_LEVEL_MEDIUM    1
+#define HAP_LEVEL_HIGH      2
+#define HAP_LEVEL_ERROR     3
+#define HAP_LEVEL_FATAL     4
+
+#define HAP_LEVEL_RUNTIME   (1 << 5)
+
+//Add a weak reference so shared objects work with older images
+#pragma weak HAP_debug_v2
+
+//Add a weak reference so runtime FARFs are ignored on older images
+#pragma weak HAP_debug_runtime
+
+/**************************************************************************
+    These HAP_debug* functions are not meant to be called directly.
+    Please use the FARF() macros to call them instead
+**************************************************************************/
+void HAP_debug_v2(int level, const char* file, int line, const char* format, ...);
+void HAP_debug_runtime(int level, const char* file, int line, const char* format, ...);
+int HAP_setFARFRuntimeLoggingParams(unsigned int mask, const char* files[],
+                                    unsigned short numberOfFiles);
+
+// Keep these around to support older shared objects and older images
+void HAP_debug(const char *msg, int level, const char *filename, int line);
+
+static __inline void _HAP_debug_v2(int level, const char* file, int line,
+                          const char* format, ...){
+   char buf[256];
+   va_list args;
+   va_start(args, format);
+   vsnprintf(buf, sizeof(buf), format, args);
+   va_end(args);
+   HAP_debug(buf, level, file, line);
+}
+
+/*!
+This function is called to log an accumlated log entry. If logging is
+enabled for the entry by the external device, then the entry is copied
+into the diag allocation manager and commited.
+
+    [in] log_code_type    ID of the event to be reported
+    [in] *data            data points to the log which is to be submitted
+    [in] dataLen          The length of the data to be logged.
+
+Returns
+    TRUE if log is submitted successfully into diag buffers
+    FALSE if there is no space left in the buffers.
+
+*/
+boolean HAP_log_data_packet(unsigned short log_code_type, unsigned int dataLen,
+                    byte* data);
+
+#define HAP_DEBUG_TRACEME 0
+
+long HAP_debug_ptrace(int req, unsigned int pid, void* addr, void* data);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // HAP_DEBUG_H
+
diff --git a/inc/HAP_farf.h b/inc/HAP_farf.h
new file mode 100644
index 0000000..48e123a
--- /dev/null
+++ b/inc/HAP_farf.h
@@ -0,0 +1,226 @@
+#ifndef HAP_FARF_H
+#define HAP_FARF_H
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include "AEEStdDef.h"
+#include "HAP_debug.h"
+
+/**
+ * FARF macro used for logging
+ *
+ * Compile time logging options
+ * -----------------------------
+ *
+ * Logging is controlled via conditional compilation. A FARF
+ * level should be defined to 1 for FARF macros to be compiled
+ * in. For example:
+ *
+ *    #define FARF_LOW 1
+ *    #include "HAP_farf.h"
+ *
+ *    FARF(LOW, "something happened: %s", (const char*)string);
+ *
+ * If FARF_LOW is defined to 0, as it is by default, the above
+ * FARF string will not be compiled in, if it is defined to 1 it
+ * will be compiled in.  Users can also define their own custom
+ * levels. For example:
+ *
+ *    #include "HAP_farf.h"
+ *    #define FARF_MYTRACE 1
+ *    #define FARF_MYTRACE_LEVEL HAP_LEVEL_LOW
+ *
+ *    FARF(MYTRACE, "custom trace in file %s on line %d", __FILE__, __LINE__);
+ *
+ * The LEVEL define tells FARF what logging level to
+ * use.  These are  mapped to their diag level counterparts, in
+ * the above example the message will be logged to diag's LOW
+ * level.
+ *
+ * Messages logged with ALWAYS level are always compiled in and logged
+ *                      ------
+ *
+ * When building the Debug variant or builds defining _DEBUG the
+ * following FARF levels will be enabled:
+ *
+ *    HIGH
+ *    ERROR
+ *    FATAL
+ *
+ *
+ *
+ * Run time logging options
+ * --------------------------
+ *
+ * In order to enable run-time logging (logging that can be enabled / disabled
+ * at run-time), the FARF_RUNTIME_* macros should be used.
+ *
+ * Log messages sent with these macros are compiled in by default. However by
+ * these messages WILL NOT be logged by default. In order to enable logging,
+ * the FASTRPC process will need to either call the
+ * HAP_SetFARFRuntimeLoggingParams() API, or by adding a <process_name>.farf
+ * file to the HLOS file system with the appropriate contents.
+ *
+ *      #include "HAP_farf.h"
+ *      FARF(RUNTIME_HIGH, "something happened: %s", (const char*)string);
+ *
+ */
+
+
+ /*
+ * @param x, the FARF level defined to either 0 to disable compilation or 1 to enable.
+ * @param ..., format string and arguments.
+ */
+#define FARF(x, ...) _FARF_PASTE(_FARF_,_FARF_VAL(FARF_##x))(x, ##__VA_ARGS__)
+
+/* by default _DEBUG turns on ALWAYS, HIGH, ERROR, FATAL
+ *
+ */
+#ifdef _DEBUG
+#ifndef FARF_HIGH
+#define FARF_HIGH 1
+#endif
+#ifndef FARF_ERROR
+#define FARF_ERROR 1
+#endif
+#ifndef FARF_FATAL
+#define FARF_FATAL 1
+#endif
+#endif
+
+/*  Compile time macros. Set these to 1 to enable logging at that
+    level. Setting them to 0 will cause them to be COMPILED out .
+
+    Example Usage:
+    #define FARF_HIGH 1
+    FARF(HIGH,"Log message");
+
+    Defining _DEBUG will automatically enable compiled log messages with
+    priority higher than HIGH.
+
+    The ALWAYS macro will cause log messages to be ALWAYS compiled in.
+    FARF(ALWAYS,"Log message")
+*/
+
+#ifndef FARF_ALWAYS
+#define FARF_ALWAYS        1    /* 0 turns me off */
+#endif
+#define FARF_ALWAYS_LEVEL  HAP_LEVEL_HIGH
+
+#ifndef FARF_LOW
+#define FARF_LOW           0    /* 0 turns me off */
+#endif
+#define FARF_LOW_LEVEL     HAP_LEVEL_LOW
+
+#ifndef FARF_MEDIUM
+#define FARF_MEDIUM        0    /* 0 turns me off */
+#endif
+#define FARF_MEDIUM_LEVEL  HAP_LEVEL_MEDIUM
+
+#ifndef FARF_HIGH
+#define FARF_HIGH          0    /* 0 turns me off */
+#endif
+#define FARF_HIGH_LEVEL    HAP_LEVEL_HIGH
+
+#ifndef FARF_ERROR
+#define FARF_ERROR         0    /* 0 turns me off */
+#endif
+#define FARF_ERROR_LEVEL   HAP_LEVEL_ERROR
+
+#ifndef FARF_FATAL
+#define FARF_FATAL         0    /* 0 turns me off */
+#endif
+#define FARF_FATAL_LEVEL   HAP_LEVEL_FATAL
+
+/* Runtime FARF macros. FARFs with these levels can be enabled at runtime.
+   They are turned OFF by default.
+
+    Example Usage:
+
+    FARF(RUNTIME_HIGH,"Log message");
+*/
+#ifndef FARF_RUNTIME_LOW
+#define FARF_RUNTIME_LOW           1    /* 0 turns me off */
+#endif
+#define FARF_RUNTIME_LOW_LEVEL     (HAP_LEVEL_RUNTIME | HAP_LEVEL_LOW)
+
+#ifndef FARF_RUNTIME_MEDIUM
+#define FARF_RUNTIME_MEDIUM        1    /* 0 turns me off */
+#endif
+#define FARF_RUNTIME_MEDIUM_LEVEL  (HAP_LEVEL_RUNTIME | HAP_LEVEL_MEDIUM)
+
+#ifndef FARF_RUNTIME_HIGH
+#define FARF_RUNTIME_HIGH          1    /* 0 turns me off */
+#endif
+#define FARF_RUNTIME_HIGH_LEVEL    (HAP_LEVEL_RUNTIME | HAP_LEVEL_HIGH)
+
+#ifndef FARF_RUNTIME_ERROR
+#define FARF_RUNTIME_ERROR         1    /* 0 turns me off */
+#endif
+#define FARF_RUNTIME_ERROR_LEVEL   (HAP_LEVEL_RUNTIME | HAP_LEVEL_ERROR)
+
+#ifndef FARF_RUNTIME_FATAL
+#define FARF_RUNTIME_FATAL         1    /* 0 turns me off */
+#endif
+#define FARF_RUNTIME_FATAL_LEVEL   (HAP_LEVEL_RUNTIME | HAP_LEVEL_FATAL)
+
+//internal macros
+#define _FARF_PASTE(a,b) _FARF_PASTE_(a,b)
+#define _FARF_PASTE_(a,b) a##b
+#define _FARF_VAL(a) a
+
+//internal macro
+//this one is used when farfs are not compiled in
+#define _FARF_0(x, ...)
+
+#ifndef __FILENAME__
+#define __FILENAME__ __FILE__
+#endif
+
+//lint -emacro(506,FARF) Constant Boolean Value
+//lint -emacro(774,FARF) Boolean within always evaluates to True
+//this one is used when farfs are compiled in
+#define _FARF_1(x, ...) \
+    do { \
+            if(0 == (HAP_debug_v2)) { \
+                _HAP_debug_v2(FARF_##x##_LEVEL, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+            } else { \
+                if (FARF_##x##_LEVEL & HAP_LEVEL_RUNTIME) { \
+                    if (0 != HAP_debug_runtime) { \
+                        HAP_debug_runtime(FARF_##x##_LEVEL ^ HAP_LEVEL_RUNTIME , __FILENAME__, __LINE__, ##__VA_ARGS__); \
+                    } else { \
+                        break; \
+                    } \
+                } else { \
+                    HAP_debug_v2(FARF_##x##_LEVEL, __FILENAME__, __LINE__, ##__VA_ARGS__); \
+                } \
+            } \
+        } while (0)
+
+#endif /* #ifndef HAP_FARF_H */
diff --git a/inc/HAP_pls.h b/inc/HAP_pls.h
new file mode 100644
index 0000000..23d7ddd
--- /dev/null
+++ b/inc/HAP_pls.h
@@ -0,0 +1,129 @@
+#ifndef HAP_PLS_H
+#define HAP_PLS_H
+
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * Process local storage is local storage for the hlos process context.
+ *
+ * Warning, this API should only be called from within a thread started by FastRPC, and not from
+ * any user created threads via the qurt apis.
+ *
+ * When used from within a FastRPC started thread this will attach
+ * desturctors to the lifetime of the HLOS process that is making the
+ * rpc calls.  Users can use this to store context for the lifetime of
+ * the calling process on the hlos.
+ *
+ * Recovering instances
+ * --------------------
+ *
+ * To maintain the same instance structure for a caller from the HLOS users
+ * can use the HAP_pls_add_lookup api, which will lookup the key, and add it
+ * if its not already present.
+ * For example:
+ *
+ *    static int my_instance(struct my_struct* me)  {
+ *       return HAP_pls_add_lookup((uintptr_t)my_ctor,   //type, some unique static address
+ *                                  0,                //key, for different type instances
+ *                                  sizeof(*me),      //size of our struture
+ *                                  my_ctor,          //structure ctor
+ *                                  0,                //aditional user context for ctor
+ *                                  my_dtor,          //desturctor
+ *                                  &me);             //result
+ *    }
+ *
+ * First call to my_instance will initialize the structure by allocating it and calling my_ctor.
+ * Second call to my_instance will return the created instance.
+ * This API is thread safe, but when two threads try to intialize the structure the first
+ * time they may both create an instance, but only 1 will be returned.
+ * The destructor will be called when the HLOS process exits.
+ *
+ * See HAP_pls_add and HAP_pls_add_lookup.
+ *
+ * Exit Hooks
+ * ----------
+ *
+ * Users can use either HAP_pls_add_lookup or HAP_pls_add to add a destructor that will be
+ * called when the HLOS process exits.  The main difference between the two functions is that
+ * HAP_pls_add will always add, and the last instance added will be the one returned by
+ * HAP_pls_lookup.
+ *
+ *
+ */
+
+/**
+ * adds a new type/key to the local storage, overriding
+ * any previous value at the key.  Overriding the key
+ * does not cause the destructor to run.  Destructors are
+ * run when the HLOS process exits.
+ *
+ * @param type, type part of the key to be used for lookup,
+ *        these should be static addresses, like the address of a function.
+ * @param key, the key to be used for lookup
+ * @param size, the size of the data
+ * @param ctor, constructor that takes a context and memory of size
+ * @param ctx, constructor context passed as the first argument to ctor
+ * @param dtor, destructor to run at pls shutdown
+ * @param ppo, output data
+ * @retval, 0 for success
+ */
+int HAP_pls_add(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo);
+
+/**
+ * Like add, but will only add 1 item, and return the same item on the
+ * next add.  If two threads try to call this function at teh same time
+ * they will both receive the same value as a result, but the constructors
+ * may be called twice.
+ * item if its already there, otherwise tries to add.
+ * ctor may be called twice
+ * callers should avoid calling pls_add for the same type/key which will override the singleton
+ */
+int HAP_pls_add_lookup(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo);
+
+/**
+ * finds the last data pointer added for key to the local storage
+ *
+ * @param key, the key to be used for lookup
+ * @param ppo, output data
+ * @retval, 0 for success
+ */
+int HAP_pls_lookup(uintptr_t type, uintptr_t key, void** ppo);
+
+
+#ifdef __cplusplus
+}
+#endif
+#endif //HAP_PLS_H
diff --git a/inc/adsp_current_process.h b/inc/adsp_current_process.h
new file mode 100644
index 0000000..a9bf630
--- /dev/null
+++ b/inc/adsp_current_process.h
@@ -0,0 +1,74 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_CURRENT_PROCESS_H
+#define _ADSP_CURRENT_PROCESS_H
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if !defined(__QAIC_STRING1_OBJECT_DEFINED__) && !defined(__STRING1_OBJECT__)
+#define __QAIC_STRING1_OBJECT_DEFINED__
+#define __STRING1_OBJECT__
+typedef struct _cstring1_s {
+   char* data;
+   int dataLen;
+} _cstring1_t;
+
+#endif /* __QAIC_STRING1_OBJECT_DEFINED__ */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process_exit)(void) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process_thread_exit)(void) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process_set_logging_params)(unsigned short mask, const _cstring1_t* filesToLog, int filesToLogLen) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process_getASID)(unsigned int* asid) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_CURRENT_PROCESS_H
diff --git a/inc/adsp_current_process1.h b/inc/adsp_current_process1.h
new file mode 100644
index 0000000..67ab15d
--- /dev/null
+++ b/inc/adsp_current_process1.h
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_CURRENT_PROCESS1_H
+#define _ADSP_CURRENT_PROCESS1_H
+#include "remote.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if !defined(__QAIC_STRING1_OBJECT_DEFINED__) && !defined(__STRING1_OBJECT__)
+#define __QAIC_STRING1_OBJECT_DEFINED__
+#define __STRING1_OBJECT__
+typedef struct _cstring1_s {
+   char* data;
+   int dataLen;
+} _cstring1_t;
+
+#endif /* __QAIC_STRING1_OBJECT_DEFINED__ */
+#define _const_adsp_current_process1_handle 4
+/**
+    * Opens the handle in the specified domain.  If this is the first
+    * handle, this creates the session.  Typically this means opening
+    * the device, aka open("/dev/adsprpc-smd"), then calling ioctl
+    * device APIs to create a PD on the DSP to execute our code in,
+    * then asking that PD to dlopen the .so and dlsym the skel function.
+    *
+    * @param uri, <interface>_URI"&_dom=aDSP"
+    *    <interface>_URI is a QAIC generated uri, or
+    *    "file:///<sofilename>?<interface>_skel_handle_invoke&_modver=1.0"
+    *    If the _dom parameter is not present, _dom=DEFAULT is assumed
+    *    but not forwarded.
+    *    Reserved uri keys:
+    *      [0]: first unamed argument is the skel invoke function
+    *      _dom: execution domain name, _dom=mDSP/aDSP/DEFAULT
+    *      _modver: module version, _modver=1.0
+    *      _*: any other key name starting with an _ is reserved
+    *    Unknown uri keys/values are forwarded as is.
+    * @param h, resulting handle
+    * @retval, 0 on success
+    */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process1_open)(const char* uri, remote_handle64* h) __QAIC_HEADER_ATTRIBUTE;
+/** 
+    * Closes a handle.  If this is the last handle to close, the session
+    * is closed as well, releasing all the allocated resources.
+
+    * @param h, the handle to close
+    * @retval, 0 on success, should always succeed
+    */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process1_close)(remote_handle64 h) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process1_exit)(remote_handle64 _h) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process1_thread_exit)(remote_handle64 _h) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process1_set_logging_params)(remote_handle64 _h, unsigned short mask, const _cstring1_t* filesToLog, int filesToLogLen) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_current_process1_getASID)(remote_handle64 _h, unsigned int* asid) __QAIC_HEADER_ATTRIBUTE;
+#ifndef adsp_current_process1_URI
+#define adsp_current_process1_URI "file:///libadsp_current_process1_skel.so?adsp_current_process1_skel_handle_invoke&_modver=1.0"
+#endif /*adsp_current_process1_URI*/
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_CURRENT_PROCESS1_H
diff --git a/inc/adsp_default_listener.h b/inc/adsp_default_listener.h
new file mode 100644
index 0000000..e4353d1
--- /dev/null
+++ b/inc/adsp_default_listener.h
@@ -0,0 +1,62 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_DEFAULT_LISTENER_H
+#define _ADSP_DEFAULT_LISTENER_H
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_default_listener_register)(void) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_DEFAULT_LISTENER_H
diff --git a/inc/adsp_listener.h b/inc/adsp_listener.h
new file mode 100644
index 0000000..dd05eec
--- /dev/null
+++ b/inc/adsp_listener.h
@@ -0,0 +1,77 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_LISTENER_H
+#define _ADSP_LISTENER_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define _const_adsp_listener_handle 3
+typedef struct _adsp_listener_buffer__seq_uint8 _adsp_listener_buffer__seq_uint8;
+typedef _adsp_listener_buffer__seq_uint8 adsp_listener_buffer;
+struct _adsp_listener_buffer__seq_uint8 {
+   uint8* data;
+   int dataLen;
+};
+typedef uint32 adsp_listener_remote_handle;
+typedef uint32 adsp_listener_invoke_ctx;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_listener_next_invoke)(adsp_listener_invoke_ctx prevCtx, int prevResult, const adsp_listener_buffer* outBufs, int outBufsLen, adsp_listener_invoke_ctx* ctx, adsp_listener_remote_handle* handle, uint32* sc, adsp_listener_buffer* inBuffers, int inBuffersLen, int* inBufLenReq, int inBufLenReqLen, int* routBufLenReq, int routBufLenReqLen) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_listener_invoke_get_in_bufs)(adsp_listener_invoke_ctx ctx, adsp_listener_buffer* inBuffers, int inBuffersLen) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_listener_init)(void) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_listener_init2)(void) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_listener_next2)(adsp_listener_invoke_ctx prevCtx, int prevResult, const uint8* prevbufs, int prevbufsLen, adsp_listener_invoke_ctx* ctx, adsp_listener_remote_handle* handle, uint32* sc, uint8* bufs, int bufsLen, int* bufsLenReq) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_listener_get_in_bufs2)(adsp_listener_invoke_ctx ctx, int offset, uint8* bufs, int bufsLen, int* bufsLenReq) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_LISTENER_H
diff --git a/inc/adsp_perf.h b/inc/adsp_perf.h
new file mode 100644
index 0000000..d2ce8a0
--- /dev/null
+++ b/inc/adsp_perf.h
@@ -0,0 +1,109 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_PERF_H
+#define _ADSP_PERF_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * Interface for querying the adsp for counter data
+ * For example, to enable all the perf numbers:
+ * 
+ *     int perf_on(void) {
+ *       int nErr = 0;
+ *       int numKeys = 0, maxLen = 0, ii;
+ *       char keys[512];
+ *       char* buf = &keys[0];
+ *       VERIFY(0 == adsp_perf_get_keys(keys, 512, &maxLen, &numKeys)); 
+ *       assert(maxLen < 512);
+ *       for(ii = 0; ii < numKeys; ++ii) {
+ *          char* name = buf;
+ *          buf += strlen(name) + 1;
+ *          printf("perf on: %s\n", name);
+ *          VERIFY(0 == adsp_perf_enable(ii));
+ *       }
+ *    bail:
+ *       return nErr;
+ *    }
+ *
+ * To read all the results:
+ *
+ *    int rpcperf_perf_result(void) {
+ *       int nErr = 0;
+ *       int numKeys, maxLen, ii;
+ *       char keys[512];
+ *       char* buf = &keys[0];
+ *       long long usecs[16];
+ *       VERIFY(0 == adsp_perf_get_keys(keys, 512, &maxLen, &numKeys)); 
+ *       printf("perf keys: %d\n", numKeys);
+ *       VERIFY(0 == adsp_perf_get_usecs(usecs, 16));
+ *       assert(maxLen < 512);
+ *       assert(numKeys < 16);
+ *       for(ii = 0; ii < numKeys; ++ii) {
+ *          char* name = buf;
+ *          buf += strlen(name) + 1;
+ *          printf("perf result: %s %lld\n", name, usecs[ii]);
+ *       }
+ *    bail:
+ *       return nErr;
+ *    }
+ */
+#define _const_adsp_perf_handle 6
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_perf_enable)(int ix) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_perf_get_usecs)(int64* dst, int dstLen) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adsp_perf_get_keys)(char* keys, int keysLen, int* maxLen, int* numKeys) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_PERF_H
diff --git a/inc/adsp_pls.h b/inc/adsp_pls.h
new file mode 100644
index 0000000..e21679d
--- /dev/null
+++ b/inc/adsp_pls.h
@@ -0,0 +1,98 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 ADSP_PLS_H
+#define ADSP_PLS_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+/**
+ * internal header
+ */
+
+/**
+ * adsp process local storage is local storage for the fastrpc hlos
+ * process context.
+
+ * When used from within a fastrpc started thread this will attach
+ * desturctors to the lifetime of the hlos process that is making the
+ * rpc calls.  Users can use this to store context for the lifetime of
+ * the calling process on the hlos.
+ */
+
+/**
+ * adds a new key to the local storage, overriding
+ * any previous value at the key.  Overriding the key
+ * does not cause the destructor to run.
+ *
+ * @param type, type part of the key to be used for lookup,
+ *        these should be static addresses, like the address of a function.
+ * @param key, the key to be used for lookup
+ * @param size, the size of the data
+ * @param ctor, constructor that takes a context and memory of size
+ * @param ctx, constructor context passed as the first argument to ctor
+ * @param dtor, destructor to run at pls shutdown
+ * @param ppo, output data
+ * @retval, 0 for success
+ */
+int adsp_pls_add(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo);
+
+/**
+ * Like add, but will only add 1 item, and return the same item on the
+ * next add.  If two threads try to call this function at teh same time
+ * they will both receive the same value as a result, but the constructors
+ * may be called twice.
+ * item if its already there, otherwise tries to add.
+ * ctor may be called twice
+ * callers should avoid calling pls_add which will override the singleton
+ */
+int adsp_pls_add_lookup(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo);
+
+/**
+ * finds the last data pointer added for key to the local storage
+ *
+ * @param key, the key to be used for lookup
+ * @param ppo, output data
+ * @retval, 0 for success
+ */
+int adsp_pls_lookup(uintptr_t type, uintptr_t key, void** ppo);
+
+/**
+ * force init/deinit
+ */
+int gpls_init(void);
+void gpls_deinit(void);
+
+#ifdef __cplusplus
+}
+#endif
+#endif //ADSP_PLS_H
diff --git a/inc/adspmsgd_adsp.h b/inc/adspmsgd_adsp.h
new file mode 100644
index 0000000..b9094bd
--- /dev/null
+++ b/inc/adspmsgd_adsp.h
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSPMSGD_ADSP_H
+#define _ADSPMSGD_ADSP_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_adsp_init)(int heapid, uint32 ion_flags, uint32 filter, uint32 buf_size, int* buff_addr) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_adsp_init2)(void) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_adsp_deinit)(void) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSPMSGD_ADSP_H
diff --git a/inc/adspmsgd_adsp1.h b/inc/adspmsgd_adsp1.h
new file mode 100644
index 0000000..1166004
--- /dev/null
+++ b/inc/adspmsgd_adsp1.h
@@ -0,0 +1,99 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSPMSGD_ADSP1_H
+#define _ADSPMSGD_ADSP1_H
+#include "AEEStdDef.h"
+#include "remote.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+#define _const_adspmsgd_adsp1_handle 5
+/**
+    * Opens the handle in the specified domain.  If this is the first
+    * handle, this creates the session.  Typically this means opening
+    * the device, aka open("/dev/adsprpc-smd"), then calling ioctl
+    * device APIs to create a PD on the DSP to execute our code in,
+    * then asking that PD to dlopen the .so and dlsym the skel function.
+    *
+    * @param uri, <interface>_URI"&_dom=aDSP"
+    *    <interface>_URI is a QAIC generated uri, or
+    *    "file:///<sofilename>?<interface>_skel_handle_invoke&_modver=1.0"
+    *    If the _dom parameter is not present, _dom=DEFAULT is assumed
+    *    but not forwarded.
+    *    Reserved uri keys:
+    *      [0]: first unamed argument is the skel invoke function
+    *      _dom: execution domain name, _dom=mDSP/aDSP/DEFAULT
+    *      _modver: module version, _modver=1.0
+    *      _*: any other key name starting with an _ is reserved
+    *    Unknown uri keys/values are forwarded as is.
+    * @param h, resulting handle
+    * @retval, 0 on success
+    */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_adsp1_open)(const char* uri, remote_handle64* h) __QAIC_HEADER_ATTRIBUTE;
+/** 
+    * Closes a handle.  If this is the last handle to close, the session
+    * is closed as well, releasing all the allocated resources.
+
+    * @param h, the handle to close
+    * @retval, 0 on success, should always succeed
+    */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_adsp1_close)(remote_handle64 h) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_adsp1_init2)(remote_handle64 _h) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_adsp1_deinit)(remote_handle64 _h) __QAIC_HEADER_ATTRIBUTE;
+#ifndef adspmsgd_adsp1_URI
+#define adspmsgd_adsp1_URI "file:///libadspmsgd_adsp1_skel.so?adspmsgd_adsp1_skel_handle_invoke&_modver=1.0"
+#endif /*adspmsgd_adsp1_URI*/
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSPMSGD_ADSP1_H
diff --git a/inc/adspmsgd_apps.h b/inc/adspmsgd_apps.h
new file mode 100644
index 0000000..64db95d
--- /dev/null
+++ b/inc/adspmsgd_apps.h
@@ -0,0 +1,78 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSPMSGD_APPS_H
+#define _ADSPMSGD_APPS_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+enum adspmsgd_apps_Level {
+   LOW,
+   MEDIUM,
+   HIGH,
+   ERROR,
+   FATAL,
+   _32BIT_PLACEHOLDER_adspmsgd_apps_Level = 0x7fffffff
+};
+typedef enum adspmsgd_apps_Level adspmsgd_apps_Level;
+typedef struct _adspmsgd_apps_octetSeq__seq_octet _adspmsgd_apps_octetSeq__seq_octet;
+typedef _adspmsgd_apps_octetSeq__seq_octet adspmsgd_apps_octetSeq;
+struct _adspmsgd_apps_octetSeq__seq_octet {
+   unsigned char* data;
+   int dataLen;
+};
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(adspmsgd_apps_log)(const unsigned char* log_message_buffer, int log_message_bufferLen) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSPMSGD_APPS_H
diff --git a/inc/apps_mem.h b/inc/apps_mem.h
new file mode 100644
index 0000000..12f7001
--- /dev/null
+++ b/inc/apps_mem.h
@@ -0,0 +1,68 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _APPS_MEM_H
+#define _APPS_MEM_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_mem_request_map)(int heapid, uint32 ion_flags, uint32 rflags, uint32 vin, int32 len, uint32* vapps, uint32* vadsp) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_mem_request_unmap)(uint32 vadsp, int32 len) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_mem_request_map64)(int heapid, uint32 ion_flags, uint32 rflags, uint64 vin, int64 len, uint64* vapps, uint64* vadsp) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_mem_request_unmap64)(uint64 vadsp, int64 len) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_mem_share_map)(int fd, int size, uint64* vapps, uint64* vadsp) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_mem_share_unmap)(uint64 vadsp, int size) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_APPS_MEM_H
diff --git a/inc/apps_remotectl.h b/inc/apps_remotectl.h
new file mode 100644
index 0000000..34f1692
--- /dev/null
+++ b/inc/apps_remotectl.h
@@ -0,0 +1,73 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _APPS_REMOTECTL_H
+#define _APPS_REMOTECTL_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if !defined(__QAIC_STRING1_OBJECT_DEFINED__) && !defined(__STRING1_OBJECT__)
+#define __QAIC_STRING1_OBJECT_DEFINED__
+#define __STRING1_OBJECT__
+typedef struct _cstring1_s {
+   char* data;
+   int dataLen;
+} _cstring1_t;
+
+#endif /* __QAIC_STRING1_OBJECT_DEFINED__ */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_remotectl_open)(const char* name, int* handle, char* dlerror, int dlerrorLen, int* nErr) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_remotectl_close)(int handle, char* dlerror, int dlerrorLen, int* nErr) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_APPS_REMOTECTL_H
diff --git a/inc/apps_std.h b/inc/apps_std.h
new file mode 100644
index 0000000..e68a24b
--- /dev/null
+++ b/inc/apps_std.h
@@ -0,0 +1,208 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _APPS_STD_H
+#define _APPS_STD_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if !defined(__QAIC_STRING1_OBJECT_DEFINED__) && !defined(__STRING1_OBJECT__)
+#define __QAIC_STRING1_OBJECT_DEFINED__
+#define __STRING1_OBJECT__
+typedef struct _cstring1_s {
+   char* data;
+   int dataLen;
+} _cstring1_t;
+
+#endif /* __QAIC_STRING1_OBJECT_DEFINED__ */
+/**
+    * standard library functions remoted from the apps to the dsp
+    */
+typedef int apps_std_FILE;
+enum apps_std_SEEK {
+   APPS_STD_SEEK_SET,
+   APPS_STD_SEEK_CUR,
+   APPS_STD_SEEK_END,
+   _32BIT_PLACEHOLDER_apps_std_SEEK = 0x7fffffff
+};
+typedef enum apps_std_SEEK apps_std_SEEK;
+typedef struct apps_std_DIR apps_std_DIR;
+struct apps_std_DIR {
+   uint64 handle;
+};
+typedef struct apps_std_DIRENT apps_std_DIRENT;
+struct apps_std_DIRENT {
+   int ino;
+   char name[255];
+};
+typedef struct apps_std_STAT apps_std_STAT;
+struct apps_std_STAT {
+   uint64 tsz;
+   uint64 dev;
+   uint64 ino;
+   uint32 mode;
+   uint32 nlink;
+   uint64 rdev;
+   uint64 size;
+   int64 atime;
+   int64 atimensec;
+   int64 mtime;
+   int64 mtimensec;
+   int64 ctime;
+   int64 ctimensec;
+};
+/**
+       * @retval, if operation fails errno is returned
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fopen)(const char* name, const char* mode, apps_std_FILE* psout) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_freopen)(apps_std_FILE sin, const char* name, const char* mode, apps_std_FILE* psout) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fflush)(apps_std_FILE sin) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fclose)(apps_std_FILE sin) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * @param,  bEOF, if read or write bytes <= bufLen bytes then feof() is called
+       *          and the result is returned in bEOF, otherwise bEOF is set to 0.
+       * @retval, if read or write return 0 for non zero length buffers, ferror is checked
+       *          and a non zero value is returned in case of error with no rout parameters
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fread)(apps_std_FILE sin, byte* buf, int bufLen, int* bytesRead, int* bEOF) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fwrite)(apps_std_FILE sin, const byte* buf, int bufLen, int* bytesWritten, int* bEOF) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * @param, pos, this buffer is filled up to MIN(posLen, sizeof(fpos_t))
+       * @param, posLenReq, returns sizeof(fpos_t)
+       * @retval, if operation fails errno is returned
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fgetpos)(apps_std_FILE sin, byte* pos, int posLen, int* posLenReq) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * @param, if size of pos doesn't match the system size an error is returned.
+       *         fgetpos can be used to query the size of fpos_t
+       * @retval, if operation fails errno is returned
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fsetpos)(apps_std_FILE sin, const byte* pos, int posLen) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * @retval, if operation fails errno is returned
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_ftell)(apps_std_FILE sin, int* pos) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fseek)(apps_std_FILE sin, int offset, apps_std_SEEK whence) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_flen)(apps_std_FILE sin, uint64* len) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * @retval, only fails if transport fails
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_rewind)(apps_std_FILE sin) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_feof)(apps_std_FILE sin, int* bEOF) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_ferror)(apps_std_FILE sin, int* err) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_clearerr)(apps_std_FILE sin) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_print_string)(const char* str) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * @param val, must contain space for NULL
+       * @param valLenReq, length required with NULL
+       * @retval, if fails errno is returned
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_getenv)(const char* name, char* val, int valLen, int* valLenReq) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * @retval, if fails errno is returned
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_setenv)(const char* name, const char* val, int override) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_unsetenv)(const char* name) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * This function will try to open a file given directories in envvarname separated by
+       * delim.
+       * so given environment variable FOO_PATH=/foo;/bar
+       *    fopen_wth_env("FOO_PATH", ";", "path/to/file", "rw", &out);
+       * will try to open /foo/path/to/file, /bar/path/to/file
+       * if the variable is unset, it will open the file directly
+       *
+       * @param envvarname, name of the environment variable containing the path
+       * @param delim, delimiator string, such as ";"
+       * @param name, name of the file
+       * @param mode, mode
+       * @param psout, output handle
+       * @retval, 0 on success errno or -1 on failure
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fopen_with_env)(const char* envvarname, const char* delim, const char* name, const char* mode, apps_std_FILE* psout) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fgets)(apps_std_FILE sin, byte* buf, int bufLen, int* bEOF) __QAIC_HEADER_ATTRIBUTE;
+/**
+       * This method will return the paths that are searched when looking for a file.
+       *  The paths are defined by the environment variable (separated by delimiters)
+       *  that is passed to the method.
+       *
+       * @param envvarname, name of the environment variable containing the path
+       * @param delim, delimiator string, such as ";"
+       * @param name, name of the file
+       * @param paths, Search paths
+       * @param numPaths, Actual number of paths found
+       * @param maxPathLen, The max path length
+       * @retval, 0 on success errno or -1 on failure
+       *
+       */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_get_search_paths_with_env)(const char* envvarname, const char* delim, _cstring1_t* paths, int pathsLen, uint32* numPaths, uint16* maxPathLen) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fileExists)(const char* path, boolean* exists) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fsync)(apps_std_FILE sin) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fremove)(const char* name) __QAIC_HEADER_ATTRIBUTE;
+/**
+        * This function decrypts the file using the provided open file descriptor, closes the
+        * original descriptor and return a new file descriptor.
+        * @retval, if operation fails errno is returned
+        */
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fdopen_decrypt)(apps_std_FILE sin, apps_std_FILE* psout) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_opendir)(const char* name, apps_std_DIR* dir) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_closedir)(const apps_std_DIR* dir) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_readdir)(const apps_std_DIR* dir, apps_std_DIRENT* dirent, int* bEOF) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_mkdir)(const char* name, int mode) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_rmdir)(const char* name) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_stat)(const char* name, apps_std_STAT* stat) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_ftrunc)(apps_std_FILE sin, int offset) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_frename)(const char* oldname, const char* newname) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_APPS_STD_H
diff --git a/inc/fastrpc_apps_user.h b/inc/fastrpc_apps_user.h
new file mode 100644
index 0000000..46c5614
--- /dev/null
+++ b/inc/fastrpc_apps_user.h
@@ -0,0 +1,65 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 FASTRPC_ANDROID_USER_H
+#define FASTRPC_ANDROID_USER_H
+
+#include <assert.h>
+#include <fcntl.h>
+#include <asm/ioctl.h>
+#include <errno.h>
+
+/*
+ * API to check if kernel supports remote memory allocation
+ * Returns 0 if NOT supported
+ *
+ */
+int is_kernel_alloc_supported(int dev, int domain);
+
+/*
+ * API to allocate ION memory for internal purposes
+ * Returns NULL if allocation fails
+ *
+ */
+void* rpcmem_alloc_internal(int heapid, uint32 flags, int size);
+
+/*
+ * API to free internally allocated ION memory
+ *
+ */
+void rpcmem_free_internal(void* po);
+
+/*
+ * API to get fd of internally allocated ION buffer
+ * Returns valid fd on success and -1 on failure
+ *
+ */
+int rpcmem_to_fd_internal(void *po);
+
+#endif //FASTRPC_ANDROID_USER_H
diff --git a/inc/fastrpc_internal.h b/inc/fastrpc_internal.h
new file mode 100644
index 0000000..8cb57a2
--- /dev/null
+++ b/inc/fastrpc_internal.h
@@ -0,0 +1,308 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 FASTRPC_INTERNAL_H
+#define FASTRPC_INTERNAL_H
+
+#include <linux/types.h>
+#include "remote64.h"
+#include "verify.h"
+#include "AEEstd.h"
+
+#define FASTRPC_IOCTL_ALLOC_DMA_BUFF 	_IOWR('R', 1, struct fastrpc_alloc_dma_buf)
+#define FASTRPC_IOCTL_FREE_DMA_BUFF 	_IOWR('R', 2, uint32_t)
+#define FASTRPC_IOCTL_INVOKE        	_IOWR('R', 3, struct fastrpc_invoke)
+#define FASTRPC_IOCTL_INIT_ATTACH 		_IO('R', 4)
+#define FASTRPC_IOCTL_INIT_CREATE 		_IOWR('R', 5, struct fastrpc_init_create)
+#define FASTRPC_IOCTL_MMAP				_IOWR('R', 6, struct fastrpc_ioctl_mmap)
+#define FASTRPC_IOCTL_MUNMAP			_IOWR('R', 7, struct fastrpc_ioctl_munmap)
+
+
+#define DEVICE_NAME "adsprpc-smd"
+
+#if !(defined __qdsp6__) && !(defined __hexagon__)
+static __inline uint32 Q6_R_cl0_R(uint32 num) {
+   int ii;
+   for(ii = 31; ii >= 0; --ii) {
+      if(num & (1 << ii)) {
+         return 31 - ii;
+      }
+   }
+   return 0;
+}
+#else
+#include "hexagon_protos.h"
+#include <types.h>
+#endif
+
+#define FASTRPC_INFO_SMMU   (1 << 0)
+
+/* struct fastrpc_invoke_args {
+	__u64 ptr;
+	__u64 length;
+	__s32 fd;
+	__u32 attrs;
+	__u32 crc;
+}; */
+
+struct fastrpc_invoke_args {
+	__u64 ptr;
+	__u64 length;
+	__s32 fd;
+	__u32 reserved;
+};
+
+struct fastrpc_invoke {
+	__u32 handle;
+	__u32 sc;
+	__u64 args;
+};
+
+#define FASTRPC_ATTR_NOVA (1)
+#define FASTRPC_ATTR_NOMAP (16)
+
+#define GUEST_OS   			0
+#define USER_PD   			-1
+#define STATIC_USER_PD  	1
+#define ATTACH_SENSORS_PD  	2
+#define GUEST_OS_SHARED  	3
+
+struct fastrpc_init_create {
+	__u32 filelen;	/* elf file length */
+	__s32 filefd;	/* fd for the file */
+	__u32 attrs;
+	__u32 siglen;
+	__u64 file;	/* pointer to elf file */
+};
+
+#define FASTRPC_ATTR_DEBUG_PROCESS (1)
+
+struct fastrpc_alloc_dma_buf {
+	__s32 fd;	/* fd */
+	__u32 flags;	/* flags to map with */
+	__u64 size;	/* size */
+};
+
+struct fastrpc_ioctl_mmap {
+	__s32 fd;	/* fd */
+	__u32 flags;	/* flags for dsp to map with */
+	__u64 vaddrin;	/* optional virtual address */
+	__u64 size;	/* size */
+	__u64 vaddrout;	/* dsps virtual address */
+};
+
+struct fastrpc_ioctl_munmap {
+	__u64 vaddrout;	/* address to unmap */
+	__u64 size;	/* size */
+};
+
+#define FASTRPC_CONTROL_LATENCY	(1)
+struct fastrpc_ctrl_latency {
+	uint32_t enable;	//!latency control enable
+	uint32_t level;		//!level of control
+};
+#define FASTRPC_CONTROL_SMMU	(2)
+struct fastrpc_ctrl_smmu {
+	uint32_t sharedcb;
+};
+
+#define FASTRPC_CONTROL_KALLOC	(3)
+struct fastrpc_ctrl_kalloc {
+	uint32_t kalloc_support;
+};
+
+struct fastrpc_ioctl_control {
+	uint32_t req;
+	union {
+		struct fastrpc_ctrl_latency lp;
+		struct fastrpc_ctrl_smmu smmu;
+		struct fastrpc_ctrl_kalloc kalloc;
+	};
+};
+
+#define FASTRPC_SMD_GUID "fastrpcsmd-apps-dsp"
+
+struct smq_null_invoke32 {
+   uint32_t ctx;         //! invoke caller context
+   remote_handle handle; //! handle to invoke
+   uint32_t sc;          //! scalars structure describing the rest of the data
+};
+
+struct smq_null_invoke {
+   uint64_t ctx;         //! invoke caller context
+   remote_handle handle; //! handle to invoke
+   uint32_t sc;          //! scalars structure describing the rest of the data
+};
+
+typedef uint32_t smq_invoke_buf_phy_addr;
+
+struct smq_phy_page {
+   uint64_t addr; //! physical address
+   int64_t size;  //! size
+};
+
+struct smq_phy_page32 {
+   uint32_t addr; //! physical address
+   uint32_t size; //! size
+};
+
+struct smq_invoke_buf {
+   int num;
+   int pgidx;
+};
+
+struct smq_invoke32 {
+   struct smq_null_invoke32 header;
+   struct smq_phy_page32 page;   //! remote arg and list of pages address
+};
+
+struct smq_invoke {
+   struct smq_null_invoke header;
+   struct smq_phy_page page;     //! remote arg and list of pages address
+};
+
+struct smq_msg32 {
+   uint32_t pid;
+   uint32_t tid;
+   struct smq_invoke32 invoke;
+};
+
+struct smq_msg {
+   uint32_t pid;
+   uint32_t tid;
+   struct smq_invoke invoke;
+};
+
+struct smq_msg_u {
+   union {
+      struct smq_msg32 msg32;
+      struct smq_msg msg64;
+   } msg;
+   int size;
+};
+
+struct smq_invoke_rsp32 {
+   uint32_t ctx;                 //! invoke caller context
+   int nRetVal;                  //! invoke return value
+};
+
+struct smq_invoke_rsp {
+   uint64_t ctx;                 //! invoke caller context
+   int nRetVal;                  //! invoke return value
+};
+
+struct smq_invoke_rsp_u {
+   union {
+      struct smq_invoke_rsp32 rsp32;
+      struct smq_invoke_rsp rsp64;
+   } rsp;
+   int size;
+};
+
+static __inline void to_smq_msg(uint32 mode, struct smq_msg_u* msg, struct smq_msg* msg64) {
+   if(0 == mode) {
+      msg64->pid = msg->msg.msg32.pid;
+      msg64->tid = msg->msg.msg32.tid;
+      msg64->invoke.header.ctx = msg->msg.msg32.invoke.header.ctx;
+      msg64->invoke.header.handle = msg->msg.msg32.invoke.header.handle;
+      msg64->invoke.header.sc = msg->msg.msg32.invoke.header.sc;
+      msg64->invoke.page.addr = msg->msg.msg32.invoke.page.addr;
+      msg64->invoke.page.size = msg->msg.msg32.invoke.page.size;
+   } else {
+      std_memmove(msg64, &msg->msg.msg64, sizeof(*msg64));
+   }
+}
+
+static __inline void to_smq_invoke_rsp(uint32 mode, uint64 ctx, int nRetVal, struct smq_invoke_rsp_u* rsp) {
+   if (0 == mode) {
+      rsp->rsp.rsp32.ctx = (uint32)ctx;
+      rsp->rsp.rsp32.nRetVal = nRetVal;
+      rsp->size = sizeof(rsp->rsp.rsp32);
+   } else {
+      rsp->rsp.rsp64.ctx = ctx;
+      rsp->rsp.rsp64.nRetVal = nRetVal;
+      rsp->size = sizeof(rsp->rsp.rsp64);
+   }
+}
+
+static __inline struct smq_invoke_buf* to_smq_invoke_buf_start(uint32 mode, void* virt, uint32 sc) {
+   struct smq_invoke_buf* buf;
+   int len = REMOTE_SCALARS_LENGTH(sc);
+   if(0 == mode) {
+      remote_arg* pra = (remote_arg*)virt;
+      buf = (struct smq_invoke_buf*)(&pra[len]);
+   } else {
+      remote_arg64* pra = (remote_arg64*)virt;
+      buf = (struct smq_invoke_buf*)(&pra[len]);
+   }
+   return buf;
+}
+
+static __inline struct smq_invoke_buf* smq_invoke_buf_start(remote_arg64 *pra, uint32 sc) {
+   int len = REMOTE_SCALARS_LENGTH(sc);
+   return (struct smq_invoke_buf*)(&pra[len]);
+}
+
+static __inline struct smq_phy_page* smq_phy_page_start(uint32 sc, struct smq_invoke_buf* buf) {
+   int nTotal =  REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc);
+   return (struct smq_phy_page*)(&buf[nTotal]);
+}
+
+//! size of the out of band data
+static __inline int smq_data_size(uint32 sc, int nPages) {
+   struct smq_invoke_buf* buf = smq_invoke_buf_start(0, sc);
+   struct smq_phy_page* page = smq_phy_page_start(sc, buf);
+   return (int)(uintptr_t)(&(page[nPages]));
+}
+
+static __inline void to_smq_data(uint32 mode, uint32 sc, int nPages, void* pv, remote_arg64* rpra) {
+   if(0 == mode) {
+      struct smq_phy_page* page;
+      struct smq_phy_page32* page32;
+      remote_arg *pra = (remote_arg*)pv;
+      int ii, len;
+      len = REMOTE_SCALARS_LENGTH(sc);
+      for(ii = 0; ii < len; ++ii) {
+         rpra[ii].buf.pv = (uint64)(uintptr_t)pra[ii].buf.pv;
+         rpra[ii].buf.nLen = pra[ii].buf.nLen;
+      }
+      len = REMOTE_SCALARS_INBUFS(sc) + REMOTE_SCALARS_OUTBUFS(sc);
+      std_memmove(&rpra[ii], &pra[ii], len * sizeof(struct smq_invoke_buf));
+      page = (struct smq_phy_page*)((struct smq_invoke_buf*)&rpra[ii] + len);
+      page32 = (struct smq_phy_page32*)((struct smq_invoke_buf*)&pra[ii] + len);
+      for(ii = 0; ii < nPages; ++ii) {
+         page[ii].addr = page32[ii].addr;
+         page[ii].size = page32[ii].size;
+      }
+   } else {
+      std_memmove(rpra, pv, smq_data_size(sc, nPages));
+   }
+}
+
+#endif // FASTRPC_INTERNAL_H
diff --git a/inc/fastrpc_perf.h b/inc/fastrpc_perf.h
new file mode 100644
index 0000000..ab0deaa
--- /dev/null
+++ b/inc/fastrpc_perf.h
@@ -0,0 +1,60 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 FASTRPC_PERF_H
+#define FASTRPC_PERF_H
+
+#include "remote.h"
+#ifdef __ANDROID__
+#include "cutils/properties.h"
+#else
+#define PROPERTY_VALUE_MAX	32
+#endif
+
+#if (defined LE_ENABLE)
+#define FASTRPC_PROPERTY_GET_INT32(key, defvalue) ((int)0)
+#define FASTRPC_PROPERTY_GET_STR(key, buffer, defvalue)     ((int)0)
+#else
+#if  (defined __ANDROID__)
+#define FASTRPC_PROPERTY_GET_INT32(key, defvalue) ((int)property_get_int32((key), (defvalue)))
+#define FASTRPC_PROPERTY_GET_STR(key, buffer, defvalue)     ((int)property_get((key), (buffer), (defvalue)))
+#else
+#define FASTRPC_PROPERTY_GET_INT32(key, defvalue) ((int)0)
+#define FASTRPC_PROPERTY_GET_STR(key, buffer, defvalue)     ((int)0)
+#endif
+#endif
+
+#define FASTRPC_MAX_STATIC_HANDLE (10)
+#define IS_STATIC_HANDLE(handle) ((handle) >= 0 && (handle) <= FASTRPC_MAX_STATIC_HANDLE)
+extern int fastrpc_perf_init(int dev);
+extern void fastrpc_perf_update(int dev, remote_handle handle, uint32_t sc);
+extern void fastrpc_perf_deinit(void);
+
+#endif //FASTRPC_PERF_H
diff --git a/inc/listener_android.h b/inc/listener_android.h
new file mode 100644
index 0000000..bd76984
--- /dev/null
+++ b/inc/listener_android.h
@@ -0,0 +1,49 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 LISTENER_ANDROID_H
+#define LISTENER_ANDROID_H
+
+#include <pthread.h>
+#include <dlfcn.h>
+#include "pthread_rw_mutex.h"
+
+#define   MSG(a, b, c)              printf(__FILE_LINE__ ":" c )
+#define   MSG_1(a, b, c, d)         printf(__FILE_LINE__ ":" c , d)
+#define   MSG_2(a, b, c, d, e)      printf(__FILE_LINE__ ":" c , d, e)
+#define   MSG_3(a, b, c, d, e, f)   printf(__FILE_LINE__ ":" c , d, e, f)
+#define   MSG_4(a, b, c, d, e, f,g) printf(__FILE_LINE__ ":" c , d, e, f, g)
+
+#define DLW_RTLD_NOW RTLD_NOW
+#define dlw_Open dlopen
+#define dlw_Sym dlsym
+#define dlw_Close dlclose
+#define dlw_Error dlerror
+
+#endif
diff --git a/inc/listener_buf.h b/inc/listener_buf.h
new file mode 100644
index 0000000..ee95b1d
--- /dev/null
+++ b/inc/listener_buf.h
@@ -0,0 +1,124 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 LISTENER_BUF_H
+#define LISTENER_BUF_H
+
+#include "sbuf.h"
+#include "remote.h"
+#include "verify.h"
+
+static __inline void pack_in_bufs(struct sbuf* buf, remote_arg* pra, int nBufs) {
+   int ii;
+   uint32_t len;
+   C_ASSERT(sizeof(len) == 4);
+   for(ii = 0; ii < nBufs; ++ii) {
+      len = (uint32_t)pra[ii].buf.nLen;
+      sbuf_write(buf, (uint8*)&len, 4);
+      if(len) {
+         sbuf_align(buf, 8);
+         sbuf_write(buf, pra[ii].buf.pv, len);
+      }
+   }
+}
+
+static __inline void pack_out_lens(struct sbuf* buf, remote_arg* pra, int nBufs) {
+   int ii;
+   uint32_t len;
+   C_ASSERT(sizeof(len) == 4);
+   for(ii = 0; ii < nBufs; ++ii) {
+      len = (uint32_t)pra[ii].buf.nLen;
+      sbuf_write(buf, (uint8*)&len, 4);
+   }
+}
+
+static __inline void unpack_in_bufs(struct sbuf* buf, remote_arg* pra, int nBufs) {
+   int ii;
+   uint32_t len=0;
+   C_ASSERT(sizeof(len) == 4);
+   for(ii = 0; ii < nBufs; ++ii) {
+      sbuf_read(buf, (uint8*)&len, 4);
+      pra[ii].buf.nLen = len;
+      if(pra[ii].buf.nLen) {
+         sbuf_align(buf, 8);
+         if((int)pra[ii].buf.nLen <= sbuf_left(buf)) {
+            pra[ii].buf.pv = sbuf_head(buf);
+         }
+         sbuf_advance(buf, pra[ii].buf.nLen);
+      }
+   }
+}
+
+static __inline void unpack_out_lens(struct sbuf* buf, remote_arg* pra, int nBufs) {
+   int ii;
+   uint32_t len=0;
+   C_ASSERT(sizeof(len) == 4);
+   for(ii = 0; ii < nBufs; ++ii) {
+      sbuf_read(buf, (uint8*)&len, 4);
+      pra[ii].buf.nLen = len;
+   }
+}
+
+//map out buffers on the hlos side to the remote_arg array
+//dst is the space required for buffers we coun't map from the adsp
+static __inline void pack_out_bufs(struct sbuf* buf, remote_arg* pra, int nBufs) {
+   int ii;
+   uint32_t len;
+   C_ASSERT(sizeof(len) == 4);
+   for(ii = 0; ii < nBufs; ++ii) {
+      len = (uint32_t)pra[ii].buf.nLen;
+      sbuf_write(buf, (uint8*)&len, 4);
+      if(pra[ii].buf.nLen) {
+         sbuf_align(buf, 8);
+         if((int)pra[ii].buf.nLen <= sbuf_left(buf)) {
+            pra[ii].buf.pv = sbuf_head(buf);
+         }
+         sbuf_advance(buf, pra[ii].buf.nLen);
+      }
+   }
+}
+
+//on the aDSP copy the data from buffers we had to copy to the local remote_arg structure
+static __inline int unpack_out_bufs(struct sbuf* buf, remote_arg* pra, int nBufs) {
+   int ii, nErr = 0;
+   uint32_t len;
+   C_ASSERT(sizeof(len) == 4);
+   for(ii = 0; ii < nBufs; ++ii) {
+      sbuf_read(buf, (uint8*)&len, 4);
+      VERIFY(len == pra[ii].buf.nLen);
+      if(pra[ii].buf.nLen) {
+         sbuf_align(buf, 8);
+         sbuf_read(buf, pra[ii].buf.pv, pra[ii].buf.nLen);
+      }
+   }
+bail:
+   return nErr;
+}
+
+#endif
diff --git a/inc/mod_table.h b/inc/mod_table.h
new file mode 100644
index 0000000..9e4e219
--- /dev/null
+++ b/inc/mod_table.h
@@ -0,0 +1,138 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 MOD_TABLE_H
+#define MOD_TABLE_H
+
+#include "remote64.h"
+#include "AEEStdDef.h"
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+/**
+ * multi-domain support
+ *
+ * multi domain modules return remote_handl64 on open/close, but mod_table
+ * creates uint32 handles as the "remote" facing handle.  These fit nicely
+ * into the transport layer.
+ *
+ */
+
+/**
+  * register a static component for invocations
+  * this can be called at any time including from a static constructor
+  *
+  * name, name of the interface to register
+  * pfn, function pointer to the skel invoke function
+  *
+  * for example:
+  *   __attribute__((constructor)) static void my_module_ctor(void) {
+  *      mod_table_register_static("my_module", my_module_skel_invoke);
+  *   }
+  *
+  */
+int mod_table_register_static(const char* name, int (*pfn)(uint32 sc, remote_arg* pra));
+
+/**
+  * same as register_static, but module with user defined handle lifetimes.
+  */
+int mod_table_register_static1(const char* uri, int (*pfn)(remote_handle64 h,uint32 sc, remote_arg* pra));
+
+/**
+  * register a static component for invocations
+  * this can be called at any time including from a static constructor
+  *
+  * overrides will be tried first, then dynamic modules, then regular
+  * static modules.  This api should only be use by system components
+  * that will never be upgradable.
+  *
+  * name, name of the interface to register
+  * pfn, function pointer to the skel invoke function
+  *
+  * for example:
+  *   __attribute__((constructor)) static void my_module_ctor(void) {
+  *      mod_table_register_static("my_module", my_module_skel_invoke);
+  *   }
+  *
+  */
+int mod_table_register_static_override(const char* name, int(*pfn)(uint32 sc, remote_arg* pra));
+
+/**
+  * same as register_static, but module with user defined handle lifetimes.
+  */
+int mod_table_register_static_override1(const char* uri, int(*pfn)(remote_handle64,uint32 sc, remote_arg* pra));
+
+/**
+ * Open a module and get a handle to it
+ *
+ * in_name, name of module to open
+ * handle, Output handle
+ * dlerr, Error String (if an error occurs)
+ * dlerrorLen, Length of error String (if an error occurs)
+ * pdlErr, Error identifier
+ */
+int mod_table_open(const char* in_name, remote_handle* handle, char* dlerr, int dlerrorLen, int* pdlErr);
+
+/**
+ * invoke a handle in the mod table
+ *
+ * handle, handle to invoke
+ * sc, scalars, see remote.h for documentation.
+ * pra, args, see remote.h for documentation.
+ */
+int mod_table_invoke(remote_handle handle, uint32 sc, remote_arg* pra);
+
+/**
+ * Closes a handle in the mod table
+ *
+ * handle, handle to close
+ * errStr, Error String (if an error occurs)
+ * errStrLen, Length of error String (if an error occurs)
+ * pdlErr, Error identifier
+ */
+int mod_table_close(remote_handle handle, char* errStr, int errStrLen, int* pdlErr);
+
+/**
+ * internal use only
+ */
+int mod_table_register_const_handle(remote_handle handle, const char* in_name, int (*pfn)(uint32 sc, remote_arg* pra));
+/**
+ * @param remote, the handle we should expect from the transport layer
+ * @param local, the local handle that will be passed to pfn
+ */
+int mod_table_register_const_handle1(remote_handle remote, remote_handle64 local, const char* uri, int (*pfn)(remote_handle64 h, uint32 sc, remote_arg* pra));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // MOD_TABLE_H
diff --git a/inc/mutex.h b/inc/mutex.h
new file mode 100644
index 0000000..a318c44
--- /dev/null
+++ b/inc/mutex.h
@@ -0,0 +1,105 @@
+#ifndef MUTEX_H
+#define MUTEX_H
+
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#if (defined __qdsp6__) || (defined __hexagon__)
+#include "qurt_mutex.h"
+
+#define RW_MUTEX_T                  qurt_mutex_t
+#define RW_MUTEX_CTOR(mut)          qurt_mutex_init(& (mut))
+#define RW_MUTEX_LOCK_READ(mut)     qurt_mutex_lock(& (mut))
+#define RW_MUTEX_UNLOCK_READ(mut)   qurt_mutex_unlock(& (mut))
+#define RW_MUTEX_LOCK_WRITE(mut)    qurt_mutex_lock(& (mut))
+#define RW_MUTEX_UNLOCK_WRITE(mut)  qurt_mutex_unlock(& (mut))
+#define RW_MUTEX_DTOR(mut)          qurt_mutex_destroy(& (mut))
+
+#elif (1 == __linux) || (1 == __linux__) || (1 == __gnu_linux__) || (1 == linux)
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* asserts may be compiled out, this should always be present */
+#define ABORT_FAIL( ff ) \
+   do {\
+      if(! (ff) ) {\
+         fprintf(stderr, "assertion \"%s\" failed: file \"%s\", line %d\n", #ff, __FILE__, __LINE__);\
+         abort();\
+      }\
+   } while(0)
+
+#define RW_MUTEX_T                  pthread_rwlock_t
+#define RW_MUTEX_CTOR(mut)          ABORT_FAIL(0 == pthread_rwlock_init( & (mut), 0))
+#define RW_MUTEX_LOCK_READ(mut)     ABORT_FAIL(0 == pthread_rwlock_rdlock( & (mut)))
+#define RW_MUTEX_UNLOCK_READ(mut)   ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut)))
+#define RW_MUTEX_LOCK_WRITE(mut)    ABORT_FAIL(0 == pthread_rwlock_wrlock( & (mut)))
+#define RW_MUTEX_UNLOCK_WRITE(mut)  ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut)))
+#define RW_MUTEX_DTOR(mut)          ABORT_FAIL(0 == pthread_rwlock_destroy( & (mut)))
+
+
+#else
+
+#include "AEEstd.h"
+
+#define RW_MUTEX_T uint32
+#define RW_MUTEX_CTOR(mut) mut = 0
+#define RW_MUTEX_LOCK_READ(mut) \
+   do {\
+      assert(STD_BIT_TEST(&mut, 1) == 0); \
+      assert(STD_BIT_TEST(&mut, 2) == 0); \
+      STD_BIT_SET(&mut, 1); \
+   } while (0)
+
+#define RW_MUTEX_UNLOCK_READ(mut) \
+   do {\
+      assert(STD_BIT_TEST(&mut, 1)); \
+      assert(STD_BIT_TEST(&mut, 2) == 0); \
+      STD_BIT_CLEAR(&mut, 1); \
+   } while (0)
+
+#define RW_MUTEX_LOCK_WRITE(mut) \
+   do {\
+      assert(STD_BIT_TEST(&mut, 1) == 0); \
+      assert(STD_BIT_TEST(&mut, 2) == 0); \
+      STD_BIT_SET(&mut, 2); \
+   } while (0)
+
+#define RW_MUTEX_UNLOCK_WRITE(mut) \
+   do {\
+      assert(STD_BIT_TEST(&mut, 1) == 0); \
+      assert(STD_BIT_TEST(&mut, 2)); \
+      STD_BIT_CLEAR(&mut, 2); \
+   } while (0)
+
+#define RW_MUTEX_DTOR(mut) mut = 0
+
+#endif
+#endif //MUTEX_H
diff --git a/inc/platform_libs.h b/inc/platform_libs.h
new file mode 100644
index 0000000..fc6c751
--- /dev/null
+++ b/inc/platform_libs.h
@@ -0,0 +1,182 @@
+#ifndef PLATFORM_LIBS_H
+#define PLATFORM_LIBS_H
+
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+/*
+Platfrom Library Loader
+-----------------------
+
+proj/platform_libs is a library to help manage interdependencies between
+other libraries.
+
+
+to use you will need to add
+
+incs = { 'proj/platform_libs' }
+
+in source of the library implementation define the entry point
+
+#include "platform_libs.h"
+PL_DEFINE(svfs, svfs_init, svfs_deinit);
+
+Platfrom Library List
+---------------------
+
+This list contains top level libraries to be initialized at boot.  To make
+sure that this library is loaded you would need to call PLRegister or
+PLRegisterDefault in your scons build command.
+
+
+Handling Interdependencies and Order
+------------------------------------
+
+To make sure that library A is loaded before library B, library B's
+constructor and destructor should initialize and cleanup libraryB.
+
+#include "platform_libs.h"
+
+PL_DEP(libraryB)
+void libraryA_deinit(void) {
+ PL_DEINIT(libraryB);
+}
+
+int libraryA_init(void) {
+ int nErr = 0;
+ // my init code
+ VERIFY(0 == PL_INIT(libraryB));
+bail:
+ if(nErr) { libraryA_deinit() }
+ return nErr;
+}
+
+
+libraryB does not need to appear in the platform library list.
+*/
+
+#include <stdint.h>
+
+struct platform_lib {
+  const char* name;
+  uint32_t uRefs;
+  int nErr;
+  int (*init)(void);
+  void (*deinit)(void);
+};
+
+/**
+ * use this macro to pull in external dependencies
+ */
+#ifdef __cplusplus
+#define PL_DEP(name)\
+   extern "C" {\
+     extern struct platform_lib*  _pl_##name(void); \
+   }
+#else
+#define PL_DEP(name)\
+   extern struct platform_lib*  _pl_##name(void);
+#endif /* __cplusplus */
+
+/**
+ * should be declared in source in the library
+ * if constructor fails, destructor is not called
+ */
+#ifdef __cplusplus
+#define PL_DEFINE(name, init, deinit) \
+   extern "C" {\
+      struct platform_lib* _pl_##name(void) {\
+         static struct platform_lib  _gpl_##name = { #name, 0, -1, init, deinit };\
+         return &_gpl_##name;\
+      }\
+   }
+#else
+#define PL_DEFINE(name, init, deinit) \
+   struct platform_lib* _pl_##name(void) {\
+      static struct platform_lib  _gpl_##name = { #name, 0, -1, init, deinit };\
+      return &_gpl_##name;\
+   }
+#endif /* __cplusplus */
+
+/**
+ * should be added to platform_libs_list.c pl_list table
+ * for all top level modules
+ */
+#define PL_ENTRY(name) _pl_##name
+
+/**
+ * should be called within a constructor to ensure that a
+ * dependency has been initialized.  so if foo depends on bar
+ *
+ *    #include "bar.h"
+ *    int foo_init() {
+ *       return PL_INIT(bar);
+ *    }
+ */
+#define PL_INIT(name) pl_lib_init(PL_ENTRY(name))
+
+/**
+ * should be called within a destructor to ensure that a
+ * dependency has been cleaned up
+ */
+#define PL_DEINIT(name) pl_lib_deinit(PL_ENTRY(name))
+
+#ifdef __cplusplus
+extern "C" {
+#endif /* __cplusplus */
+
+/**
+ * initalize the static list of library constructors and destructors
+ * should be called from main()
+ *
+ * see platform_libs_list.h to add high level libraries
+ *
+ */
+int pl_init(void);
+
+/**
+ * calls all the destructors.
+ */
+void pl_deinit(void);
+
+/**
+ * initialize a single library.  called via PL_INIT
+ */
+int pl_lib_init(struct platform_lib* (*pl)(void));
+
+/**
+ * deinitialize a single library called via PL_DEINIT
+ */
+void pl_lib_deinit(struct platform_lib* (*pl)(void));
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif //PLATFORM_LIBS
diff --git a/inc/pls.h b/inc/pls.h
new file mode 100644
index 0000000..c832aa9
--- /dev/null
+++ b/inc/pls.h
@@ -0,0 +1,213 @@
+#ifndef PLS_H
+#define PLS_H
+
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include <stdlib.h>
+#include "AEEStdDef.h"
+#include "AEEatomic.h"
+#include "verify.h"
+#include "HAP_farf.h"
+
+struct PLS;
+
+struct plskey {
+   uintptr_t type;
+   uintptr_t key;
+};
+
+struct PLS {
+   struct PLS* next;
+   struct plskey key;
+   void (*dtor)(void* data);
+   uint64_t data[1];
+};
+
+
+struct pls_table {
+   struct PLS* lst;
+   uint32_t uRefs;
+   uint32_t primThread;
+};
+
+/**
+ * initialize on every thread and stick the pls_thread_deinit
+ * function into the threads tls
+ */
+static __inline int pls_thread_init(struct pls_table* me, uintptr_t tid) {
+   if(tid == me->primThread) {
+      return 0;
+   }
+   if(0 == atomic_CompareOrAdd(&me->uRefs, 0, 1)) {
+      return -1;
+   }
+   return 0;
+}
+
+/* call this constructor before the first thread creation with the
+ * first threads id
+ */
+static __inline void pls_ctor(struct pls_table* me, uintptr_t primThread) {
+   me->uRefs = 1;
+   me->primThread = primThread;
+}
+
+static __inline struct pls_table* pls_thread_deinit(struct pls_table* me) {
+   if(me && 0 != me->uRefs && 0 == atomic_Add(&me->uRefs, -1)) {
+      struct PLS* lst, *next;
+      lst = me->lst;
+      me->lst = 0;
+      while(lst) {
+         next = lst->next;
+         if(lst->dtor) {
+            FARF(HIGH, "pls dtor %p", lst->dtor);
+            lst->dtor((void*)lst->data);
+         }
+         free(lst);
+         lst = next;
+      }
+      return me;
+   }
+   return 0;
+}
+
+/**
+ * adds a new key to the local storage, overriding
+ * any previous value at the key.  Overriding the key
+ * does not cause the destructor to run.
+ *
+ * @param type, type part of the key to be used for lookup,
+          these should be static addresses.
+ * @param key, the key to be used for lookup
+ * @param size, the size of the data
+ * @param ctor, constructor that takes a context and memory of size
+ * @param ctx, constructor context passed as the first argument to ctor
+ * @param dtor, destructor to run at pls shutdown
+ * @param ppo, output data
+ * @retval, 0 for success
+ */
+
+static __inline int pls_add(struct pls_table* me, uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* data), void** ppo) {
+   int nErr = 0;
+   struct PLS* pls = 0;
+   struct PLS* prev;
+   VERIFY(me->uRefs != 0);
+   VERIFY(0 != (pls = (struct PLS*)calloc(1, size + sizeof(*pls) - sizeof(pls->data))));
+   if(ctor) {
+      VERIFY(0 == ctor(ctx, (void*)pls->data));
+   }
+   pls->dtor = dtor;
+   pls->key.type = type;
+   pls->key.key = key;
+   do {
+      pls->next = me->lst;
+      prev = (struct PLS*)atomic_CompareAndExchangeUP((uintptr_t*)&me->lst, (uintptr_t)pls, (uintptr_t)pls->next);
+   } while(prev != pls->next);
+   if(ppo) {
+      *ppo = (void*)pls->data;
+   }
+   FARF(HIGH, "pls added %p", dtor);
+bail:
+   if(nErr && pls) {
+      free(pls);
+   }
+   return nErr;
+}
+
+static __inline int pls_lookup(struct pls_table* me, uintptr_t type, uintptr_t key, void** ppo);
+
+/**
+ * like add, but will only add 1 item if two threads try to add at the same time.  returns
+ * item if its already there, otherwise tries to add.
+ * ctor may be called twice
+ * callers should avoid calling pls_add which will override the singleton
+ */
+static __inline int pls_add_lookup_singleton(struct pls_table* me, uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* data), void** ppo) {
+   int nErr = 0;
+   struct PLS* pls = 0;
+   struct PLS* prev;
+   if(0 == pls_lookup(me, type, key, ppo)) {
+      return 0;
+   }
+   VERIFY(me->uRefs != 0);
+   VERIFY(0 != (pls = (struct PLS*)calloc(1, size + sizeof(*pls) - sizeof(pls->data))));
+   if(ctor) {
+      VERIFY(0 == ctor(ctx, (void*)pls->data));
+   }
+   pls->dtor = dtor;
+   pls->key.type = type;
+   pls->key.key = key;
+   do {
+      pls->next = me->lst;
+      if(0 == pls_lookup(me, type, key, ppo)) {
+         if(pls->dtor) {
+            pls->dtor((void*)pls->data);
+         }
+         free(pls);
+         return 0;
+      }
+      prev = (struct PLS*)atomic_CompareAndExchangeUP((uintptr_t*)&me->lst, (uintptr_t)pls, (uintptr_t)pls->next);
+   } while(prev != pls->next);
+   if(ppo) {
+      *ppo = (void*)pls->data;
+   }
+   FARF(HIGH, "pls added %p", dtor);
+bail:
+   if(nErr && pls) {
+      free(pls);
+   }
+   return nErr;
+}
+
+
+/**
+ * finds the last data pointer added for key to the local storage
+ *
+ * @param key, the key to be used for lookup
+ * @param ppo, output data
+ * @retval, 0 for success
+ */
+
+static __inline int pls_lookup(struct pls_table* me, uintptr_t type, uintptr_t key, void** ppo) {
+   struct PLS* lst;
+   for(lst = me->lst; me->uRefs != 0 && lst != 0; lst = lst->next) {
+      if(lst->key.type == type && lst->key.key == key) {
+         if(ppo) {
+            *ppo = lst->data;
+         }
+         return 0;
+      }
+   }
+   return -1;
+}
+
+#endif //PLS_H
+
+
diff --git a/inc/pthread_rw_mutex.h b/inc/pthread_rw_mutex.h
new file mode 100644
index 0000000..61e6278
--- /dev/null
+++ b/inc/pthread_rw_mutex.h
@@ -0,0 +1,59 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 PTHREAD_RW_MUTEX_H
+#define PTHREAD_RW_MUTEX_H
+
+#include <pthread.h>
+#include <stdlib.h>
+#include <stdio.h>
+
+/* asserts may be compiled out, this should always be present */
+#define ABORT_FAIL( ff ) \
+   do {\
+      if(! (ff) ) {\
+         fprintf(stderr, "assertion \"%s\" failed: file \"%s\", line %d\n", #ff, __FILE__, __LINE__);\
+         abort();\
+      }\
+   } while(0)
+
+#define RW_MUTEX_T                  pthread_rwlock_t
+#define RW_MUTEX_CTOR(mut)          ABORT_FAIL(0 == pthread_rwlock_init( & (mut), 0))
+#define RW_MUTEX_LOCK_READ(mut)     ABORT_FAIL(0 == pthread_rwlock_rdlock( & (mut)))
+
+#define RW_MUTEX_UNLOCK_READ(mut)   ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut)))
+
+#define RW_MUTEX_LOCK_WRITE(mut)    ABORT_FAIL(0 == pthread_rwlock_wrlock( & (mut)))
+
+#define RW_MUTEX_UNLOCK_WRITE(mut)  ABORT_FAIL(0 == pthread_rwlock_unlock( & (mut)))
+
+#define RW_MUTEX_DTOR(mut)          ABORT_FAIL(0 == pthread_rwlock_destroy( & (mut)))
+
+
+#endif //PTHREAD_RW_MUTEX_H
diff --git a/inc/remote.h b/inc/remote.h
new file mode 100644
index 0000000..8125c2b
--- /dev/null
+++ b/inc/remote.h
@@ -0,0 +1,318 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 REMOTE_H
+#define REMOTE_H
+
+#include <stdint.h>
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef uint32_t remote_handle;
+typedef uint64_t remote_handle64; //! used by multi domain modules
+                                  //! 64 bit handles are translated to 32 bit values
+                                  //! by the transport layer
+
+typedef struct {
+   void *pv;
+   size_t nLen;
+} remote_buf;
+
+typedef struct {
+   int32_t fd;
+   uint32_t offset;
+} remote_dma_handle;
+
+typedef union {
+   remote_buf     buf;
+   remote_handle    h;
+   remote_handle64 h64; //! used by multi domain modules
+   remote_dma_handle dma;
+} remote_arg;
+
+/*Retrives method attribute from the scalars parameter*/
+#define REMOTE_SCALARS_METHOD_ATTR(dwScalars)   (((dwScalars) >> 29) & 0x7)
+
+/*Retrives method index from the scalars parameter*/
+#define REMOTE_SCALARS_METHOD(dwScalars)        (((dwScalars) >> 24) & 0x1f)
+
+/*Retrives number of input buffers from the scalars parameter*/
+#define REMOTE_SCALARS_INBUFS(dwScalars)        (((dwScalars) >> 16) & 0x0ff)
+
+/*Retrives number of output buffers from the scalars parameter*/
+#define REMOTE_SCALARS_OUTBUFS(dwScalars)       (((dwScalars) >> 8) & 0x0ff)
+
+/*Retrives number of input handles from the scalars parameter*/
+#define REMOTE_SCALARS_INHANDLES(dwScalars)     (((dwScalars) >> 4) & 0x0f)
+
+/*Retrives number of output handles from the scalars parameter*/
+#define REMOTE_SCALARS_OUTHANDLES(dwScalars)    ((dwScalars) & 0x0f)
+
+#define REMOTE_SCALARS_MAKEX(nAttr,nMethod,nIn,nOut,noIn,noOut) \
+          ((((uint32_t)   (nAttr) &  0x7) << 29) | \
+           (((uint32_t) (nMethod) & 0x1f) << 24) | \
+           (((uint32_t)     (nIn) & 0xff) << 16) | \
+           (((uint32_t)    (nOut) & 0xff) <<  8) | \
+           (((uint32_t)    (noIn) & 0x0f) <<  4) | \
+            ((uint32_t)   (noOut) & 0x0f))
+
+#define REMOTE_SCALARS_MAKE(nMethod,nIn,nOut)  REMOTE_SCALARS_MAKEX(0,nMethod,nIn,nOut,0,0)
+
+#define REMOTE_SCALARS_LENGTH(sc) (REMOTE_SCALARS_INBUFS(sc) +\
+                                   REMOTE_SCALARS_OUTBUFS(sc) +\
+                                   REMOTE_SCALARS_INHANDLES(sc) +\
+                                   REMOTE_SCALARS_OUTHANDLES(sc))
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_REMOTE_EXPORT
+#ifdef _WIN32
+#define __QAIC_REMOTE_EXPORT __declspec(dllexport)
+#else //_WIN32
+#define __QAIC_REMOTE_EXPORT
+#endif //_WIN32
+#endif //__QAIC_REMOTE_EXPORT
+
+#ifndef __QAIC_REMOTE_ATTRIBUTE
+#define __QAIC_REMOTE_ATTRIBUTE
+#endif
+
+#define NUM_DOMAINS 4
+#define NUM_SESSIONS 2
+#define DOMAIN_ID_MASK 3
+
+#ifndef DEFAULT_DOMAIN_ID
+#define DEFAULT_DOMAIN_ID 0
+#endif
+
+#define ADSP_DOMAIN_ID    0
+#define MDSP_DOMAIN_ID    1
+#define SDSP_DOMAIN_ID    2
+#define CDSP_DOMAIN_ID    3
+
+#define ADSP_DOMAIN "&_dom=adsp"
+#define MDSP_DOMAIN "&_dom=mdsp"
+#define SDSP_DOMAIN "&_dom=sdsp"
+#define CDSP_DOMAIN "&_dom=cdsp"
+
+/* All other values are reserved */
+
+/* opens a remote_handle "name"
+ * returns 0 on success
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle_open)(const char* name, remote_handle *ph) __QAIC_REMOTE_ATTRIBUTE;
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle64_open)(const char* name, remote_handle64 *ph) __QAIC_REMOTE_ATTRIBUTE;
+
+/* invokes the remote handle
+ * see retrive macro's on dwScalars format
+ * pra, contains the arguments in the following order, inbufs, outbufs, inhandles, outhandles.
+ * implementors should ignore and pass values asis that the transport doesn't understand.
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle_invoke)(remote_handle h, uint32_t dwScalars, remote_arg *pra) __QAIC_REMOTE_ATTRIBUTE;
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle64_invoke)(remote_handle64 h, uint32_t dwScalars, remote_arg *pra) __QAIC_REMOTE_ATTRIBUTE;
+
+/* closes the remote handle
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle_close)(remote_handle h) __QAIC_REMOTE_ATTRIBUTE;
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle64_close)(remote_handle64 h) __QAIC_REMOTE_ATTRIBUTE;
+
+/* remote handle control interface
+ */
+/* request ID for fastrpc latency control */
+#define DSPRPC_CONTROL_LATENCY    (1)
+struct remote_rpc_control_latency {
+   uint32_t enable;	// enable auto control of rpc latency
+   uint32_t latency;	// latency: reserved
+};
+
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle_control)(uint32_t req, void* data, uint32_t datalen) __QAIC_REMOTE_ATTRIBUTE;
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_handle64_control)(remote_handle64 h, uint32_t req, void* data, uint32_t datalen) __QAIC_REMOTE_ATTRIBUTE;
+
+/* remote session control interface
+ */
+/* request ID for setting DSP user thread params */
+#define FASTRPC_THREAD_PARAMS    (1)
+struct remote_rpc_thread_params {
+	int domain;			// Remote subsystem domain ID, pass -1 to set params for all domains
+	int prio;			// user thread priority (1 to 255), pass -1 to use default
+	int stack_size;		// user thread stack size, pass -1 to use default
+};
+
+/* request ID for fastrpc unsigned module */
+#define DSPRPC_CONTROL_UNSIGNED_MODULE    (2)
+struct remote_rpc_control_unsigned_module {
+   int domain;				// Remote subsystem domain ID, -1 to set params for all domains
+   int enable; 				// enable unsigned module loading
+};
+
+/* Set remote session parameters
+ *
+ * @param req, request ID
+ * @param data, address of structure with parameters
+ * @param datalen, length of data
+ * @retval, 0 on success
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_session_control)(uint32_t req, void *data, uint32_t datalen) __QAIC_REMOTE_ATTRIBUTE;
+
+/* map memory to the remote domain
+ *
+ * @param fd, fd assosciated with this memory
+ * @param flags, flags to be used for the mapping
+ * @param vaddrin, input address
+ * @param size, size of buffer
+ * @param vaddrout, output address
+ * @retval, 0 on success
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_mmap)(int fd, uint32_t flags, uint32_t vaddrin, int size, uint32_t* vaddrout) __QAIC_REMOTE_ATTRIBUTE;
+
+/* unmap memory from the remote domain
+ *
+ * @param vaddrout, remote address mapped
+ * @param size, size to unmap.  Unmapping a range partially may  not be supported.
+ * @retval, 0 on success, may fail if memory is still mapped
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_munmap)(uint32_t vaddrout, int size) __QAIC_REMOTE_ATTRIBUTE;
+
+/*
+ * Attribute to map a buffer as dma non-coherent
+ * Driver perform cache maintenance.
+ */
+#define FASTRPC_ATTR_NON_COHERENT  (2)
+
+/*
+ * Attribute to map a buffer as dma coherent
+ * Driver skips cache maintenenace
+ * It will be ignored if a device is marked as dma-coherent in device tree.
+ */
+#define FASTRPC_ATTR_COHERENT  (4)
+
+/* Attribute to keep the buffer persistant
+ * until unmap is called explicitly
+ */
+#define FASTRPC_ATTR_KEEP_MAP  (8)
+
+/*
+ * Attribute for secure buffers to skip
+ * smmu mapping in fastrpc driver
+ */
+#define FASTRPC_ATTR_NOMAP  (16)
+
+/* Register a file descriptor for a buffer.  This is only valid on
+ * android with ION allocated memory.  Users of fastrpc should register
+ * a buffer allocated with ION to enable sharing that buffer to the
+ * dsp via the smmu.  Some versions of libadsprpc.so lack this
+ * function, so users should set this symbol as weak.
+ *
+ * #pragma weak  remote_register_buf
+ * #pragma weak  remote_register_buf_attr
+ *
+ * @param buf, virtual address of the buffer
+ * @param size, size of the buffer
+ * @fd, the file descriptor, callers can use -1 to deregister.
+ * @attr, map buffer as coherent or non-coherent
+ */
+__QAIC_REMOTE_EXPORT void __QAIC_REMOTE(remote_register_buf)(void* buf, int size, int fd) __QAIC_REMOTE_ATTRIBUTE;
+__QAIC_REMOTE_EXPORT void __QAIC_REMOTE(remote_register_buf_attr)(void* buf, int size, int fd, int attr) __QAIC_REMOTE_ATTRIBUTE;
+
+/* Register a dma handle with fastrpc.  This is only valid on
+ * android with ION allocated memory.  Users of fastrpc should register
+ * a file descriptor allocated with ION to enable sharing that memory to the
+ * dsp via the smmu.  Some versions of libadsprpc.so lack this
+ * function, so users should set this symbol as weak.
+ *
+ * #pragma weak  remote_register_dma_handle
+ * #pragma weak  remote_register_dma_handle_attr
+ *
+ * @fd, the file descriptor, callers can use -1 to deregister.
+ * @param len, size of the buffer
+ * @attr, map buffer as coherent or non-coherent or no-map
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_register_dma_handle)(int fd, uint32_t len) __QAIC_REMOTE_ATTRIBUTE;
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_register_dma_handle_attr)(int fd, uint32_t len, uint32_t attr) __QAIC_REMOTE_ATTRIBUTE;
+
+/*
+ * This is the default mode for the driver.  While the driver is in parallel
+ * mode it will try to invalidate output buffers after it transfers control
+ * to the dsp.  This allows the invalidate operations to overlap with the
+ * dsp processing the call.  This mode should be used when output buffers
+ * are only read on the application processor and only written on the aDSP.
+ */
+#define REMOTE_MODE_PARALLEL  0
+
+/*
+ * When operating in SERIAL mode the driver will invalidate output buffers
+ * before calling into the dsp.  This mode should be used when output
+ * buffers have been written to somewhere besides the aDSP.
+ */
+#define REMOTE_MODE_SERIAL    1
+
+/*
+ * Internal transport prefix
+ */
+#define ITRANSPORT_PREFIX "'\":;./\\"
+
+/*
+ * Set the mode of operation.
+ *
+ * Some versions of libadsprpc.so lack this function, so users should set
+ * this symbol as weak.
+ *
+ * #pragma weak  remote_set_mode
+ *
+ * @param mode, the mode
+ * @retval, 0 on success
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_set_mode)(uint32_t mode) __QAIC_REMOTE_ATTRIBUTE;
+
+/* Register a file descriptor.  This can be used when users do not have
+ * a mapping to pass to the RPC layer.  The generated address is a mapping
+ * with PROT_NONE, any access to this memory will fail, so it should only
+ * be used as an ID to identify this file descriptor to the RPC layer.
+ *
+ * To deregister use remote_register_buf(addr, size, -1).
+ *
+ * #pragma weak  remote_register_fd
+ *
+ * @param fd, the file descriptor.
+ * @param size, size to of the buffer
+ * @retval, (void*)-1 on failure, address on success.
+ * 
+ */
+__QAIC_REMOTE_EXPORT void *__QAIC_REMOTE(remote_register_fd)(int fd, int size) __QAIC_REMOTE_ATTRIBUTE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // REMOTE_H
diff --git a/inc/remote64.h b/inc/remote64.h
new file mode 100644
index 0000000..341b2ca
--- /dev/null
+++ b/inc/remote64.h
@@ -0,0 +1,96 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 REMOTE64_H
+#define REMOTE64_H
+
+#include "remote.h"
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct {
+   uint64_t pv;
+   int64_t nLen;
+} remote_buf64;
+
+typedef struct {
+   int32_t fd;
+   uint32_t offset;
+   uint32_t len;
+} remote_dma_handle64;
+
+typedef union {
+   remote_buf64	 buf;
+   remote_handle     h;
+   remote_handle64 h64; //! used by multi domain modules
+   remote_dma_handle64 dma;
+} remote_arg64;
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_REMOTE_EXPORT
+#ifdef _WIN32
+#define __QAIC_REMOTE_EXPORT __declspec(dllexport)
+#else //_WIN32
+#define __QAIC_REMOTE_EXPORT
+#endif //_WIN32
+#endif //__QAIC_REMOTE_EXPORT
+
+#ifndef __QAIC_REMOTE_ATTRIBUTE
+#define __QAIC_REMOTE_ATTRIBUTE
+#endif
+
+/* map memory to the remote domain
+ *
+ * @param fd, fd associated with this memory
+ * @param flags, flags to be used for the mapping
+ * @param vaddrin, input address
+ * @param size, size of buffer
+ * @param vaddrout, output address
+ * @retval, 0 on success
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_mmap64)(int fd, uint32_t flags, uint64_t vaddrin, int64_t size, uint64_t *vaddrout) __QAIC_REMOTE_ATTRIBUTE;
+
+/* unmap memory from the remote domain
+ *
+ * @param vaddrout, remote address mapped
+ * @param size, size to unmap.  Unmapping a range partially may  not be supported.
+ * @retval, 0 on success, may fail if memory is still mapped
+ */
+__QAIC_REMOTE_EXPORT int __QAIC_REMOTE(remote_munmap64)(uint64_t vaddrout, int64_t size) __QAIC_REMOTE_ATTRIBUTE;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif // REMOTE64_H
diff --git a/inc/remotectl.h b/inc/remotectl.h
new file mode 100644
index 0000000..3302a46
--- /dev/null
+++ b/inc/remotectl.h
@@ -0,0 +1,76 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _REMOTECTL_H
+#define _REMOTECTL_H
+#include "AEEStdDef.h"
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+#ifdef __cplusplus
+extern "C" {
+#endif
+#if !defined(__QAIC_STRING1_OBJECT_DEFINED__) && !defined(__STRING1_OBJECT__)
+#define __QAIC_STRING1_OBJECT_DEFINED__
+#define __STRING1_OBJECT__
+typedef struct _cstring1_s {
+   char* data;
+   int dataLen;
+} _cstring1_t;
+
+#endif /* __QAIC_STRING1_OBJECT_DEFINED__ */
+#define _const_remotectl_handle 0
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(remotectl_open)(const char* name, int* handle, char* dlerror, int dlerrorLen, int* nErr) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(remotectl_close)(int handle, char* dlerror, int dlerrorLen, int* nErr) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(remotectl_grow_heap)(uint32 phyAddr, uint32 nSize) __QAIC_HEADER_ATTRIBUTE;
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(remotectl_set_param)(int reqID, const uint32* params, int paramsLen) __QAIC_HEADER_ATTRIBUTE;
+#ifdef __cplusplus
+}
+#endif
+#endif //_REMOTECTL_H
diff --git a/inc/rpcmem.h b/inc/rpcmem.h
new file mode 100644
index 0000000..28f3a77
--- /dev/null
+++ b/inc/rpcmem.h
@@ -0,0 +1,140 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 RPCMEM_H
+#define RPCMEM_H
+
+#include "AEEStdDef.h"
+
+/**
+ * RPCMEM_DEFAULT_HEAP
+ * Dynamicaly select the heap to use.  This should be ok for most usecases.
+ */
+#define RPCMEM_DEFAULT_HEAP -1
+
+
+/**
+ * RPCMEM_DEFAULT_FLAGS should allocate memory with the same properties
+ * as the ION_FLAG_CACHED flag
+ */
+#ifdef ION_FLAG_CACHED
+#define RPCMEM_DEFAULT_FLAGS ION_FLAG_CACHED
+#else
+#define RPCMEM_DEFAULT_FLAGS 1
+#endif
+
+/**
+ * RPCMEM_FLAG_UNCACHED
+ * ION_FLAG_CACHED should be defined as 1
+ */
+#define RPCMEM_FLAG_UNCACHED 0
+#define RPCMEM_FLAG_CACHED RPCMEM_DEFAULT_FLAGS
+
+/**
+ * examples:
+ *
+ * heap 22, uncached, 1kb
+ *    rpcmem_alloc(22, 0, 1024);
+ *    rpcmem_alloc(22, RPCMEM_FLAG_UNCACHED, 1024);
+ *
+ * heap 21, cached, 2kb
+ *    rpcmem_alloc(21, RPCMEM_FLAG_CACHED, 2048);
+ *    #include <ion.h>
+ *    rpcmem_alloc(21, ION_FLAG_CACHED, 2048);
+ *
+ * just give me the defaults, 2kb
+ *    rpcmem_alloc(RPCMEM_DEFAULT_HEAP, RPCMEM_DEFAULT_FLAGS, 2048);
+ *    rpcmem_alloc_def(2048);
+ *
+ * give me the default flags, but from heap 18, 4kb
+ *    rpcmem_alloc(18, RPCMEM_DEFAULT_FLAGS, 4096);
+ *
+ */
+#define ION_SECURE_FLAGS    ((1 << 31) | (1 << 19))
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/**
+ * call once to initialize the library
+ * Note: should not call this if rpcmem is linked from libadsprpc.so
+ * /libcdsprpc.so/libmdsprpc.so/libsdsprpc.so
+ */
+void rpcmem_init(void);
+/**
+ * call once for cleanup
+ * Note: should not call this if rpcmem is linked from libadsprpc.so
+ * /libcdsprpc.so/libmdsprpc.so/libsdsprpc.so
+ */
+void rpcmem_deinit(void);
+
+/**
+ * Allocate via ION a buffer of size
+ * @heapid, the heap id to use
+ * @flags, ion flags to use to when allocating
+ * @size, the buffer size to allocate
+ * @retval, 0 on failure, pointer to buffer on success
+ *
+ * For example:
+ *    buf = rpcmem_alloc(RPCMEM_DEFAULT_HEAP, RPCMEM_DEFAULT_FLAGS, size);
+ */
+
+void* rpcmem_alloc(int heapid, uint32 flags, int size);
+
+/**
+ * allocate with default settings
+ */
+ #if !defined(WINNT) && !defined (_WIN32_WINNT)
+__attribute__((unused))
+#endif
+static __inline void* rpcmem_alloc_def(int size) {
+   return rpcmem_alloc(RPCMEM_DEFAULT_HEAP, RPCMEM_DEFAULT_FLAGS, size);
+}
+
+/**
+ * free buffer, ignores invalid buffers
+ */
+void rpcmem_free(void* po);
+
+/**
+ * returns associated fd
+ */
+int rpcmem_to_fd(void* po);
+
+#ifdef __cplusplus
+}
+#endif
+
+#define RPCMEM_HEAP_DEFAULT     0x80000000
+#define RPCMEM_HEAP_NOREG       0x40000000
+#define RPCMEM_HEAP_UNCACHED    0x20000000
+#define RPCMEM_HEAP_NOVA        0x10000000
+#define RPCMEM_HEAP_NONCOHERENT 0x08000000
+
+#endif //RPCMEM_H
diff --git a/inc/sbuf.h b/inc/sbuf.h
new file mode 100644
index 0000000..96775c8
--- /dev/null
+++ b/inc/sbuf.h
@@ -0,0 +1,175 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 SBUF_H
+#define SBUF_H
+
+#include <string.h>
+#include <stdint.h>
+#include "AEEstd.h"
+
+/**
+ * lightweight serialize/deserialize buffer.
+
+   For example
+
+   struct sbuf;
+   //initialize empty buffer;
+   sbuf_init(&sbuf, 0, 0, 0);
+
+   //fill it with data
+   sbuf_align(&sbuf, 8);
+   sbuf_write(&sbuf, ptr1, 10);
+   sbuf_align(&sbuf, 8);
+   sbuf_write(&sbuf, ptr2, 20);
+
+   //allocate the memory needed
+   mem = malloc(sbuf_needed(&sbuf));
+
+   //initialize with the data
+   sbuf_init(&sbuf, 0, mem, sbuf_needed(&sbuf));
+
+   //fill it with data, since it has memory, it will actually copy
+   sbuf_align(&sbuf, 8);
+   sbuf_write(&sbuf, ptr1, 10);
+   sbuf_align(&sbuf, 8);
+   sbuf_write(&sbuf, ptr2, 20);
+
+   See sbuf_q.c for more examples
+ */
+
+
+struct sbuf {
+   uintptr_t buf;      //! start of valid memory
+   uintptr_t bufEnd;   //! end of valid memory
+   uintptr_t bufStart; //! start with optinal offset from valid mem
+   uintptr_t bufCur;   //! current position, could be outside of valid range
+};
+
+/**
+ * @param buf, the buffer structure instance
+ * @param offset, this value indicates how far ahead the data buffer is
+ *                start = data - offset
+ * @param data, the valid memory
+ * @param dataLen, the length ov valid memory
+ */
+static __inline void sbuf_init(struct sbuf* buf, int offset, void* data, int dataLen) {
+   buf->buf = (uintptr_t)data;
+   buf->bufStart = buf->bufCur = (uintptr_t)data - offset;
+   buf->bufEnd = (uintptr_t)data + dataLen;
+}
+
+//! move the current pointer by len
+static __inline void sbuf_advance(struct sbuf* buf, int len) {
+   buf->bufCur += len;
+}
+
+/**
+ * @retval, the amount of memory needed for everything from the start (with the offset)
+ * to the current position of the buffer
+ */
+static __inline int sbuf_needed(struct sbuf* buf) {
+   return buf->bufCur - buf->bufStart;
+}
+/**
+ * @retval, the space left in the buffer. A negative value indicates overflow.
+ *          A positive value includes the offset.
+ */
+static __inline int sbuf_left(struct sbuf* buf) {
+   return buf->bufEnd - buf->bufCur;
+}
+
+//! @retval the current head pointer
+static __inline void* sbuf_head(struct sbuf* buf) {
+   return (void*)buf->bufCur;
+}
+
+//! @retval true if the current pointer is valid
+static __inline int sbuf_valid(struct sbuf* buf) {
+   return buf->bufCur >= buf->buf && buf->bufCur < buf->bufEnd;
+}
+
+//! advance the head pointer so the "needed" is aligned to the align value
+#define _SBUF_ALIGN(x, y) (((x) + ((y)-1)) & ~((y)-1))
+static __inline void sbuf_align(struct sbuf* buf, uint32_t align) {
+   sbuf_advance(buf, _SBUF_ALIGN(sbuf_needed(buf), align) - sbuf_needed(buf));
+}
+
+/**
+ * Write to the buffer.
+ * @param src, the memory to read from.  Will write srcLen bytes to buf from src
+ *             from the buf's current position.  Only the valid portion of data will
+ *             be written.
+ * @param srcLen, the length of src.  The buffer will be advanced by srcLen.
+ */
+static __inline void sbuf_write(struct sbuf* buf, void *psrc, int srcLen) {
+   uintptr_t src = (uintptr_t)psrc;
+   if(buf->bufCur + srcLen > buf->buf) {
+      int writeLen;
+      if(buf->bufCur < buf->buf) {
+         int len = buf->buf - buf->bufCur;
+         srcLen -= len;
+         src += len;
+         sbuf_advance(buf, len);
+      }
+      writeLen = STD_MIN(srcLen, sbuf_left(buf));
+      if(writeLen > 0) {
+         std_memsmove((void*)buf->bufCur, buf->bufEnd - buf->bufCur, (void*)src, writeLen);
+      }
+   }
+   sbuf_advance(buf, srcLen);
+}
+
+/**
+ * Read from the buffer into dst.
+ * @param dst, the data to write to. Will write dstLen to dst from buf
+ *             from the current position of buf.  Only valid memory
+ *             will be written to dst.  Invalid overlapping memory will
+ *             remain untouched.
+ * @param dstLen, the length of dst.  buf will be advanced by dstLen
+ */
+static __inline void sbuf_read(struct sbuf* buf, void *pdst, int dstLen) {
+   uintptr_t dst = (uintptr_t)pdst;
+   if(buf->bufCur + dstLen > buf->buf) {
+      int readLen;
+      if(buf->bufCur < buf->buf) {
+         int len = buf->buf - buf->bufCur;
+         dstLen -= len;
+         dst += len;
+         sbuf_advance(buf, len);
+      }
+      readLen = STD_MIN(dstLen, sbuf_left(buf));
+      if(readLen > 0) {
+         std_memsmove((void*)dst, dstLen, (void*)buf->bufCur, readLen);
+      }
+   }
+   sbuf_advance(buf, dstLen);
+}
+
+#endif
diff --git a/inc/sbuf_parser.h b/inc/sbuf_parser.h
new file mode 100644
index 0000000..b4e0b28
--- /dev/null
+++ b/inc/sbuf_parser.h
@@ -0,0 +1,266 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 SBUF_PARSER_H
+#define SBUF_PARSER_H
+
+#include "sbuf.h"
+
+/**
+ * Greedy Recursive Descent Parser in C
+ *
+ * Stop using strstr or regular expressions.  This simple Recursive Descent Parser can be
+ * used to handle complex grammars.
+ *
+ * For example:
+ *   parsing a query string form a uri
+ *   input: "file:///foo/bar_far.so.1?_blah1&_bar=barval5&_barfar"
+ *   expected output:
+ *      parsed query: _blah1 =
+ *      parsed query: _bar = barval5
+ *      parsed query: _barfar =
+ *
+ *   static int qmark(struct sbuf *buf) {
+ *      return sbuf_char(buf, '?');
+ *   }
+ *   static int notandoreq(struct sbuf *buf) {
+ *      return sbuf_notchars(buf, "&=");
+ *   }
+ *   static int notand(struct sbuf *buf) {
+ *      return sbuf_notchar(buf, '&');
+ *   }
+ *
+ *   const char *name;
+ *   int nameLen;
+ *   const char *value;
+ *   int valueLen;
+ *   const char *data = "file:///foo/bar_far.so.1?_blah1&_bar=barval5&_barfar";
+ *
+ *   //initialize
+ *   sbuf_parser_init(&buf, data, strlen(data));
+ *
+ *   //parse until question mark
+ *   assert(sbuf_until(&buf, sbuf_any, qmark));
+ *
+ *   //parse each query
+ *   while(!sbuf_end(&buf)) {
+ *      //record where the name starts
+ *      name = sbuf_cur(&buf);
+ *
+ *      //name is valid until '=' or '&'
+ *      assert(sbuf_many1(&buf, notandoreq));
+ *      nameLen = sbuf_cur(&buf) - name;
+ *
+ *      value = 0;
+ *      valueLen = 0;
+ *      //if the next char is a '=' then we also get a value
+ *      if(sbuf_char(&buf, '=')) {
+ *         value = sbuf_cur(&buf);
+ *
+ *         //value is until the next query that starts with '&'
+ *         assert(sbuf_many1(&buf, notand));
+ *         valueLen = sbuf_cur(&buf) - value;
+ *      }
+ *      //expect '&' or end
+ *      sbuf_char(&buf, '&');
+ *      printf("parsed query: %.*s = %.*s\n", nameLen, name, valueLen, value);
+ *   }
+ *
+ */
+
+//! init
+static __inline void sbuf_parser_init(struct sbuf* buf, const char *data, int dataLen) {
+   sbuf_init(buf, 0, (void*)data, dataLen);
+}
+
+//! current postiion
+static __inline char *sbuf_cur(struct sbuf* buf) {
+   return (char*)sbuf_head(buf);
+}
+
+//! look at the next character if the buffer is still valid
+static __inline int sbuf_peek(struct sbuf* buf, char* c) {
+   if(!sbuf_valid(buf)) {
+      return 0;
+   }
+   *c = *sbuf_cur(buf);
+   return 1;
+}
+
+//! returns true if the buffer is ended
+static __inline int sbuf_end(struct sbuf* buf) {
+   return sbuf_left(buf) == 0;
+}
+
+//! consume 1 char if its in string chars
+static __inline int sbuf_chars(struct sbuf *buf, const char *chars) {
+   int i = 0;
+   char c;
+   if(!sbuf_peek(buf, &c)) {
+      return 0;
+   }
+   for(i = 0; chars[i] != 0; ++i) {
+      if(c == chars[i]) {
+         sbuf_advance(buf, 1);
+         return 1;
+      }
+   }
+   return 0;
+}
+
+//! consume 1 char only if its not in string chars
+static __inline int sbuf_notchars(struct sbuf *buf, const char *chars) {
+   int i = 0;
+   char c;
+   if(!sbuf_peek(buf, &c)) {
+      return 0;
+   }
+   for(i = 0; chars[i] != 0; ++i) {
+      if(c == chars[i]) {
+         return 0;
+      }
+   }
+   sbuf_advance(buf, 1);
+   return 1;
+}
+
+//! consume only char t
+static __inline int sbuf_char(struct sbuf *buf, const char t) {
+   char str[2] = {t, 0};
+   return sbuf_chars(buf, str);
+}
+
+//! consume any char except for t
+static __inline int sbuf_notchar(struct sbuf *buf, const char t) {
+   char str[2] = {t, 0};
+   return sbuf_notchars(buf, str);
+}
+
+/**
+ * consume any char
+ */
+static __inline int sbuf_any(struct sbuf* buf) {
+   return sbuf_notchars(buf, "");
+}
+
+
+/**
+ * range is pairs of characters
+ *
+ * pairs are inclusive, start must be less then or equal then the end
+ *
+ * for example: AZaz09--..
+ *   matches uppercase and lowercase letters, numbers, dashes and dots
+ *
+ */
+static __inline int sbuf_range(struct sbuf *buf, const char *chars) {
+   int i, j;
+   char c;
+   if(!sbuf_peek(buf, &c)) {
+      return 0;
+   }
+   for(i = 0, j = 1; chars[i] != 0 && chars[j] != 0; i+=2,j+=2) {
+      if(c >= chars[i] && c <= chars[j]) {
+         sbuf_advance(buf, 1);
+         return 1;
+      }
+   }
+   return 0;
+}
+
+
+/**
+ * greedly consume and match the entire string
+ * empty string always succeeds without consuming any data
+ */
+static __inline int sbuf_string(struct sbuf *buf, const char *str) {
+   int i = 0;
+   for(i = 0; str[i] != 0; ++i) {
+      if(!sbuf_char(buf, str[i])) {
+         return 0;
+      }
+   }
+   return 1;
+}
+
+/**
+ * consumes until fails
+ */
+static __inline int sbuf_many(struct sbuf *buf,
+                              int(*consume)(struct sbuf *buf))
+{
+   if(!sbuf_valid(buf)) {
+      return 0;
+   }
+   while(consume(buf)) {;}
+   return 1;
+}
+/**
+ * consumes until fails, must consume at least 1
+ */
+static __inline int sbuf_many1(struct sbuf *buf,
+                               int(*consume)(struct sbuf *buf))
+{
+   if(!consume(buf)) {
+      return 0;
+   }
+   sbuf_many(buf, consume);
+   return 1;
+}
+/**
+ * runs 'consume' until 'stop' succeeds
+ * 'stop' must fail in such a way that it doesn't consume any data
+ */
+static __inline int sbuf_until(struct sbuf *buf,
+                               int(*consume)(struct sbuf *buf),
+                               int(*stop)(struct sbuf *buf))
+{
+   while(!stop(buf)) {
+      if(!consume(buf))  {
+         return 0;
+      }
+   }
+   return 1;
+}
+
+/**
+ * allows for backtracking,
+ * @param parser, runs parser and only consume if it succeeds
+ */
+static __inline int sbuf_try(struct sbuf *buf, int(*parser)(struct sbuf *buf))
+{
+   struct sbuf tryp;
+   sbuf_parser_init(&tryp, sbuf_cur(buf), sbuf_left(buf));
+   if(parser(&tryp)) {
+      sbuf_advance(buf, sbuf_cur(&tryp) - sbuf_cur(buf));
+      return 1;
+   }
+   return 0;
+}
+#endif // SBUF_PARSER_H
diff --git a/inc/shared.h b/inc/shared.h
new file mode 100644
index 0000000..14c4f19
--- /dev/null
+++ b/inc/shared.h
@@ -0,0 +1,81 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 SHARED_H
+#define SHARED_H
+
+#if defined(__NIX)
+// TODO these sections not supported?
+//static __so_func *__autostart[] __attribute__((section (".CRT$XIU"))) = { (__so_func*)__so_ctor };
+//static __so_func *__autoexit[] __attribute__((section (".CRT$XPU"))) = { (__so_func*)__so_dtor };
+
+#define SHARED_OBJECT_API_ENTRY(ctor, dtor)
+
+#elif defined(_WIN32)
+#include <windows.h>
+
+typedef int __so_cb(void);
+static __so_cb *__so_get_ctor();
+static __so_cb *__so_get_dtor();
+
+typedef void __so_func(void);
+static void __so_ctor() {
+   (void)(__so_get_ctor())();
+}
+
+static void __so_dtor() {
+   (void)(__so_get_dtor())();
+}
+
+#pragma data_seg(".CRT$XIU")
+   static __so_func *__autostart[] = { (__so_func*)__so_ctor };
+#pragma data_seg(".CRT$XPU")
+   static __so_func *__autoexit[] = { (__so_func*)__so_dtor };
+#pragma data_seg()
+
+#define SHARED_OBJECT_API_ENTRY(ctor, dtor)\
+   static __so_cb *__so_get_ctor() { return (__so_cb*)ctor; }\
+   static __so_cb *__so_get_dtor() { return (__so_cb*)dtor; }
+
+#else //better be gcc
+
+#define SHARED_OBJECT_API_ENTRY(ctor, dtor)\
+__attribute__((constructor)) \
+static void __ctor__##ctor(void) {\
+   (void)ctor();\
+}\
+\
+__attribute__((destructor))\
+static void  __dtor__##dtor(void) {\
+   (void)dtor();\
+}
+
+#endif //ifdef _WIN32
+
+#endif // SHARED_H
diff --git a/inc/uthash.h b/inc/uthash.h
new file mode 100644
index 0000000..dfee1c8
--- /dev/null
+++ b/inc/uthash.h
@@ -0,0 +1,920 @@
+/*
+Copyright (c) 2003-2011, Troy D. Hanson     http://uthash.sourceforge.net
+All rights reserved.
+
+Redistribution and use in source and binary forms, with or without
+modification, are permitted provided that the following conditions are met:
+
+    * Redistributions of source code must retain the above copyright
+      notice, this list of conditions and the following disclaimer.
+
+THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "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 THE COPYRIGHT OWNER
+OR CONTRIBUTORS 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 UTHASH_H
+#define UTHASH_H
+
+#include <string.h>   /* memcmp,strlen */
+#include <stddef.h>   /* ptrdiff_t */
+#include <stdlib.h>   /* exit() */
+
+/* These macros use decltype or the earlier __typeof GNU extension.
+   As decltype is only available in newer compilers (VS2010 or gcc 4.3+
+   when compiling c++ source) this code uses whatever method is needed
+   or, for VS2008 where neither is available, uses casting workarounds. */
+#ifdef _MSC_VER         /* MS compiler */
+#if _MSC_VER >= 1600 && defined(__cplusplus)  /* VS2010 or newer in C++ mode */
+#define DECLTYPE(x) (decltype(x))
+#else                   /* VS2008 or older (or VS2010 in C mode) */
+#define NO_DECLTYPE
+#define DECLTYPE(x)
+#endif
+#else                   /* GNU, Sun and other compilers */
+#define DECLTYPE(x) (__typeof(x))
+#endif
+
+#ifdef NO_DECLTYPE
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  char **_da_dst = (char**)(&(dst));                                             \
+  *_da_dst = (char*)(src);                                                       \
+} while(0)
+#else
+#define DECLTYPE_ASSIGN(dst,src)                                                 \
+do {                                                                             \
+  (dst) = DECLTYPE(dst)(src);                                                    \
+} while(0)
+#endif
+
+/* a number of the hash function use uint32_t which isn't defined on win32 */
+#ifdef _MSC_VER
+typedef unsigned int uint32_t;
+typedef unsigned char uint8_t;
+#else
+#include <inttypes.h>   /* uint32_t */
+#endif
+
+#define UTHASH_VERSION 1.9.4
+
+#ifndef UTHASH_MALLOC
+#define UTHASH_MALLOC malloc
+#endif
+
+#ifndef UTHASH_FREE
+#define UTHASH_FREE free
+#endif
+
+#define uthash_fatal(msg) exit(-1)        /* fatal error (out of memory,etc) */
+#define uthash_malloc(sz) UTHASH_MALLOC(sz)      /* malloc fcn                      */
+#define uthash_free(ptr,sz) UTHASH_FREE(ptr)     /* free fcn                        */
+
+#define uthash_noexpand_fyi(tbl)          /* can be defined to log noexpand  */
+#define uthash_expand_fyi(tbl)            /* can be defined to log expands   */
+
+/* initial number of buckets */
+#define HASH_INITIAL_NUM_BUCKETS 32      /* initial number of buckets        */
+#define HASH_INITIAL_NUM_BUCKETS_LOG2 5  /* lg2 of initial number of buckets */
+#define HASH_BKT_CAPACITY_THRESH 10      /* expand when bucket count reaches */
+
+/* calculate the element whose hash handle address is hhe */
+#define ELMT_FROM_HH(tbl,hhp) ((void*)(((char*)(hhp)) - ((tbl)->hho)))
+
+#define HASH_FIND(hh,head,keyptr,keylen,out)                                     \
+do {                                                                             \
+  unsigned _hf_bkt,_hf_hashv;                                                    \
+  out=NULL;                                                                      \
+  if (head) {                                                                    \
+     HASH_FCN(keyptr,keylen, (head)->hh.tbl->num_buckets, _hf_hashv, _hf_bkt);   \
+     if (HASH_BLOOM_TEST((head)->hh.tbl, _hf_hashv)) {                           \
+       HASH_FIND_IN_BKT((head)->hh.tbl, hh, (head)->hh.tbl->buckets[ _hf_bkt ],  \
+                        keyptr,keylen,out);                                      \
+     }                                                                           \
+  }                                                                              \
+} while (0)
+
+#ifdef HASH_BLOOM
+#define HASH_BLOOM_BITLEN (1ULL << HASH_BLOOM)
+#define HASH_BLOOM_BYTELEN (HASH_BLOOM_BITLEN/8) + ((HASH_BLOOM_BITLEN%8) ? 1:0)
+#define HASH_BLOOM_MAKE(tbl)                                                     \
+do {                                                                             \
+  (tbl)->bloom_nbits = HASH_BLOOM;                                               \
+  (tbl)->bloom_bv = (uint8_t*)uthash_malloc(HASH_BLOOM_BYTELEN);                 \
+  if (!((tbl)->bloom_bv))  { uthash_fatal( "out of memory"); }                   \
+  memset((tbl)->bloom_bv, 0, HASH_BLOOM_BYTELEN);                                \
+  (tbl)->bloom_sig = HASH_BLOOM_SIGNATURE;                                       \
+} while (0);
+
+#define HASH_BLOOM_FREE(tbl)                                                     \
+do {                                                                             \
+  uthash_free((tbl)->bloom_bv, HASH_BLOOM_BYTELEN);                              \
+} while (0);
+
+#define HASH_BLOOM_BITSET(bv,idx) (bv[(idx)/8] |= (1U << ((idx)%8)))
+#define HASH_BLOOM_BITTEST(bv,idx) (bv[(idx)/8] & (1U << ((idx)%8)))
+
+#define HASH_BLOOM_ADD(tbl,hashv)                                                \
+  HASH_BLOOM_BITSET((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#define HASH_BLOOM_TEST(tbl,hashv)                                               \
+  HASH_BLOOM_BITTEST((tbl)->bloom_bv, (hashv & (uint32_t)((1ULL << (tbl)->bloom_nbits) - 1)))
+
+#else
+#define HASH_BLOOM_MAKE(tbl)
+#define HASH_BLOOM_FREE(tbl)
+#define HASH_BLOOM_ADD(tbl,hashv)
+#define HASH_BLOOM_TEST(tbl,hashv) (1)
+#endif
+
+#define HASH_MAKE_TABLE(hh,head)                                                 \
+do {                                                                             \
+  (head)->hh.tbl = (UT_hash_table*)uthash_malloc(                                \
+                  sizeof(UT_hash_table));                                        \
+  if (!((head)->hh.tbl))  { uthash_fatal( "out of memory"); }                    \
+  memset((head)->hh.tbl, 0, sizeof(UT_hash_table));                              \
+  (head)->hh.tbl->tail = &((head)->hh);                                          \
+  (head)->hh.tbl->num_buckets = HASH_INITIAL_NUM_BUCKETS;                        \
+  (head)->hh.tbl->log2_num_buckets = HASH_INITIAL_NUM_BUCKETS_LOG2;              \
+  (head)->hh.tbl->hho = (char*)(&(head)->hh) - (char*)(head);                    \
+  (head)->hh.tbl->buckets = (UT_hash_bucket*)uthash_malloc(                      \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  if (! (head)->hh.tbl->buckets) { uthash_fatal( "out of memory"); }             \
+  memset((head)->hh.tbl->buckets, 0,                                             \
+          HASH_INITIAL_NUM_BUCKETS*sizeof(struct UT_hash_bucket));               \
+  HASH_BLOOM_MAKE((head)->hh.tbl);                                               \
+  (head)->hh.tbl->signature = HASH_SIGNATURE;                                    \
+} while(0)
+
+#define HASH_ADD(hh,head,fieldname,keylen_in,add)                                \
+        HASH_ADD_KEYPTR(hh,head,&add->fieldname,keylen_in,add)
+
+#define HASH_ADD_KEYPTR(hh,head,keyptr,keylen_in,add)                            \
+do {                                                                             \
+ unsigned _ha_bkt;                                                               \
+ (add)->hh.next = NULL;                                                          \
+ (add)->hh.key = (char*)keyptr;                                                  \
+ (add)->hh.keylen = keylen_in;                                                   \
+ if (!(head)) {                                                                  \
+    head = (add);                                                                \
+    (head)->hh.prev = NULL;                                                      \
+    HASH_MAKE_TABLE(hh,head);                                                    \
+ } else {                                                                        \
+    (head)->hh.tbl->tail->next = (add);                                          \
+    (add)->hh.prev = ELMT_FROM_HH((head)->hh.tbl, (head)->hh.tbl->tail);         \
+    (head)->hh.tbl->tail = &((add)->hh);                                         \
+ }                                                                               \
+ (head)->hh.tbl->num_items++;                                                    \
+ (add)->hh.tbl = (head)->hh.tbl;                                                 \
+ HASH_FCN(keyptr,keylen_in, (head)->hh.tbl->num_buckets,                         \
+         (add)->hh.hashv, _ha_bkt);                                              \
+ HASH_ADD_TO_BKT((head)->hh.tbl->buckets[_ha_bkt],&(add)->hh);                   \
+ HASH_BLOOM_ADD((head)->hh.tbl,(add)->hh.hashv);                                 \
+ HASH_EMIT_KEY(hh,head,keyptr,keylen_in);                                        \
+ HASH_FSCK(hh,head);                                                             \
+} while(0)
+
+#define HASH_TO_BKT( hashv, num_bkts, bkt )                                      \
+do {                                                                             \
+  bkt = ((hashv) & ((num_bkts) - 1));                                            \
+} while(0)
+
+/* delete "delptr" from the hash table.
+ * "the usual" patch-up process for the app-order doubly-linked-list.
+ * The use of _hd_hh_del below deserves special explanation.
+ * These used to be expressed using (delptr) but that led to a bug
+ * if someone used the same symbol for the head and deletee, like
+ *  HASH_DELETE(hh,users,users);
+ * We want that to work, but by changing the head (users) below
+ * we were forfeiting our ability to further refer to the deletee (users)
+ * in the patch-up process. Solution: use scratch space to
+ * copy the deletee pointer, then the latter references are via that
+ * scratch pointer rather than through the repointed (users) symbol.
+ */
+#define HASH_DELETE(hh,head,delptr)                                              \
+do {                                                                             \
+    unsigned _hd_bkt;                                                            \
+    struct UT_hash_handle *_hd_hh_del;                                           \
+    if ( ((delptr)->hh.prev == NULL) && ((delptr)->hh.next == NULL) )  {         \
+        uthash_free((head)->hh.tbl->buckets,                                     \
+                    (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+        HASH_BLOOM_FREE((head)->hh.tbl);                                         \
+        uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                      \
+        head = NULL;                                                             \
+    } else {                                                                     \
+        _hd_hh_del = &((delptr)->hh);                                            \
+        if ((delptr) == ELMT_FROM_HH((head)->hh.tbl,(head)->hh.tbl->tail)) {     \
+            (head)->hh.tbl->tail =                                               \
+                (UT_hash_handle*)((char*)((delptr)->hh.prev) +                   \
+                (head)->hh.tbl->hho);                                            \
+        }                                                                        \
+        if ((delptr)->hh.prev) {                                                 \
+            ((UT_hash_handle*)((char*)((delptr)->hh.prev) +                      \
+                    (head)->hh.tbl->hho))->next = (delptr)->hh.next;             \
+        } else {                                                                 \
+            DECLTYPE_ASSIGN(head,(delptr)->hh.next);                             \
+        }                                                                        \
+        if (_hd_hh_del->next) {                                                  \
+            ((UT_hash_handle*)((char*)_hd_hh_del->next +                         \
+                    (head)->hh.tbl->hho))->prev =                                \
+                    _hd_hh_del->prev;                                            \
+        }                                                                        \
+        HASH_TO_BKT( _hd_hh_del->hashv, (head)->hh.tbl->num_buckets, _hd_bkt);   \
+        HASH_DEL_IN_BKT(hh,(head)->hh.tbl->buckets[_hd_bkt], _hd_hh_del);        \
+        (head)->hh.tbl->num_items--;                                             \
+    }                                                                            \
+    HASH_FSCK(hh,head);                                                          \
+} while (0)
+
+/* use this function to delete an item from a table only if its in that table */
+#define HASH_DELETE_IF(hh,group,ptr) \
+do {\
+   if(ptr && group && ptr->hh.tbl) { \
+      HASH_DELETE(hh,group,ptr); \
+      ptr->hh.tbl = 0;\
+   } \
+} while(0)
+
+/* convenience forms of HASH_FIND/HASH_ADD/HASH_DEL */
+#define HASH_FIND_STR(head,findstr,out)                                          \
+    HASH_FIND(hh,head,findstr,strlen(findstr),out)
+#define HASH_ADD_STR(head,strfield,add)                                          \
+    HASH_ADD(hh,head,strfield,strlen(add->strfield),add)
+#define HASH_FIND_INT(head,findint,out)                                          \
+    HASH_FIND(hh,head,findint,sizeof(int),out)
+#define HASH_ADD_INT(head,intfield,add)                                          \
+    HASH_ADD(hh,head,intfield,sizeof(int),add)
+#define HASH_FIND_PTR(head,findptr,out)                                          \
+    HASH_FIND(hh,head,findptr,sizeof(void *),out)
+#define HASH_ADD_PTR(head,ptrfield,add)                                          \
+    HASH_ADD(hh,head,ptrfield,sizeof(void *),add)
+#define HASH_DEL(head,delptr)                                                    \
+    HASH_DELETE(hh,head,delptr)
+
+/* HASH_FSCK checks hash integrity on every add/delete when HASH_DEBUG is defined.
+ * This is for uthash developer only; it compiles away if HASH_DEBUG isn't defined.
+ */
+#ifdef HASH_DEBUG
+#define HASH_OOPS(...) do { fprintf(stderr,__VA_ARGS__); exit(-1); } while (0)
+#define HASH_FSCK(hh,head)                                                       \
+do {                                                                             \
+    unsigned _bkt_i;                                                             \
+    unsigned _count, _bkt_count;                                                 \
+    char *_prev;                                                                 \
+    struct UT_hash_handle *_thh;                                                 \
+    if (head) {                                                                  \
+        _count = 0;                                                              \
+        for( _bkt_i = 0; _bkt_i < (head)->hh.tbl->num_buckets; _bkt_i++) {       \
+            _bkt_count = 0;                                                      \
+            _thh = (head)->hh.tbl->buckets[_bkt_i].hh_head;                      \
+            _prev = NULL;                                                        \
+            while (_thh) {                                                       \
+               if (_prev != (char*)(_thh->hh_prev)) {                            \
+                   HASH_OOPS("invalid hh_prev %p, actual %p\n",                  \
+                    _thh->hh_prev, _prev );                                      \
+               }                                                                 \
+               _bkt_count++;                                                     \
+               _prev = (char*)(_thh);                                            \
+               _thh = _thh->hh_next;                                             \
+            }                                                                    \
+            _count += _bkt_count;                                                \
+            if ((head)->hh.tbl->buckets[_bkt_i].count !=  _bkt_count) {          \
+               HASH_OOPS("invalid bucket count %d, actual %d\n",                 \
+                (head)->hh.tbl->buckets[_bkt_i].count, _bkt_count);              \
+            }                                                                    \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid hh item count %d, actual %d\n",                   \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+        /* traverse hh in app order; check next/prev integrity, count */         \
+        _count = 0;                                                              \
+        _prev = NULL;                                                            \
+        _thh =  &(head)->hh;                                                     \
+        while (_thh) {                                                           \
+           _count++;                                                             \
+           if (_prev !=(char*)(_thh->prev)) {                                    \
+              HASH_OOPS("invalid prev %p, actual %p\n",                          \
+                    _thh->prev, _prev );                                         \
+           }                                                                     \
+           _prev = (char*)ELMT_FROM_HH((head)->hh.tbl, _thh);                    \
+           _thh = ( _thh->next ?  (UT_hash_handle*)((char*)(_thh->next) +        \
+                                  (head)->hh.tbl->hho) : NULL );                 \
+        }                                                                        \
+        if (_count != (head)->hh.tbl->num_items) {                               \
+            HASH_OOPS("invalid app item count %d, actual %d\n",                  \
+                (head)->hh.tbl->num_items, _count );                             \
+        }                                                                        \
+    }                                                                            \
+} while (0)
+#else
+#define HASH_FSCK(hh,head)
+#endif
+
+/* When compiled with -DHASH_EMIT_KEYS, length-prefixed keys are emitted to
+ * the descriptor to which this macro is defined for tuning the hash function.
+ * The app can #include <unistd.h> to get the prototype for write(2). */
+#ifdef HASH_EMIT_KEYS
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)                                   \
+do {                                                                             \
+    unsigned _klen = fieldlen;                                                   \
+    write(HASH_EMIT_KEYS, &_klen, sizeof(_klen));                                \
+    write(HASH_EMIT_KEYS, keyptr, fieldlen);                                     \
+} while (0)
+#else
+#define HASH_EMIT_KEY(hh,head,keyptr,fieldlen)
+#endif
+
+/* default to Jenkin's hash unless overridden e.g. DHASH_FUNCTION=HASH_SAX */
+#ifdef HASH_FUNCTION
+#define HASH_FCN HASH_FUNCTION
+#else
+#define HASH_FCN HASH_JEN
+#endif
+
+/* The Bernstein hash function, used in Perl prior to v5.6 */
+#define HASH_BER(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hb_keylen=keylen;                                                    \
+  char *_hb_key=(char*)(key);                                                    \
+  (hashv) = 0;                                                                   \
+  while (_hb_keylen--)  { (hashv) = ((hashv) * 33) + *_hb_key++; }               \
+  bkt = (hashv) & (num_bkts-1);                                                  \
+} while (0)
+
+
+/* SAX/FNV/OAT/JEN hash functions are macro variants of those listed at
+ * http://eternallyconfuzzled.com/tuts/algorithms/jsw_tut_hashing.aspx */
+#define HASH_SAX(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _sx_i;                                                                \
+  char *_hs_key=(char*)(key);                                                    \
+  hashv = 0;                                                                     \
+  for(_sx_i=0; _sx_i < keylen; _sx_i++)                                          \
+      hashv ^= (hashv << 5) + (hashv >> 2) + _hs_key[_sx_i];                     \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while (0)
+
+#define HASH_FNV(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _fn_i;                                                                \
+  char *_hf_key=(char*)(key);                                                    \
+  hashv = 2166136261UL;                                                          \
+  for(_fn_i=0; _fn_i < keylen; _fn_i++)                                          \
+      hashv = (hashv * 16777619) ^ _hf_key[_fn_i];                               \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0);
+
+#define HASH_OAT(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _ho_i;                                                                \
+  char *_ho_key=(char*)(key);                                                    \
+  hashv = 0;                                                                     \
+  for(_ho_i=0; _ho_i < keylen; _ho_i++) {                                        \
+      hashv += _ho_key[_ho_i];                                                   \
+      hashv += (hashv << 10);                                                    \
+      hashv ^= (hashv >> 6);                                                     \
+  }                                                                              \
+  hashv += (hashv << 3);                                                         \
+  hashv ^= (hashv >> 11);                                                        \
+  hashv += (hashv << 15);                                                        \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0)
+
+#define HASH_JEN_MIX(a,b,c)                                                      \
+do {                                                                             \
+  a -= b; a -= c; a ^= ( c >> 13 );                                              \
+  b -= c; b -= a; b ^= ( a << 8 );                                               \
+  c -= a; c -= b; c ^= ( b >> 13 );                                              \
+  a -= b; a -= c; a ^= ( c >> 12 );                                              \
+  b -= c; b -= a; b ^= ( a << 16 );                                              \
+  c -= a; c -= b; c ^= ( b >> 5 );                                               \
+  a -= b; a -= c; a ^= ( c >> 3 );                                               \
+  b -= c; b -= a; b ^= ( a << 10 );                                              \
+  c -= a; c -= b; c ^= ( b >> 15 );                                              \
+} while (0)
+
+#define HASH_JEN(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  unsigned _hj_i,_hj_j,_hj_k;                                                    \
+  char *_hj_key=(char*)(key);                                                    \
+  hashv = 0xfeedbeef;                                                            \
+  _hj_i = _hj_j = 0x9e3779b9;                                                    \
+  _hj_k = keylen;                                                                \
+  while (_hj_k >= 12) {                                                          \
+    _hj_i +=    (_hj_key[0] + ( (unsigned)_hj_key[1] << 8 )                      \
+        + ( (unsigned)_hj_key[2] << 16 )                                         \
+        + ( (unsigned)_hj_key[3] << 24 ) );                                      \
+    _hj_j +=    (_hj_key[4] + ( (unsigned)_hj_key[5] << 8 )                      \
+        + ( (unsigned)_hj_key[6] << 16 )                                         \
+        + ( (unsigned)_hj_key[7] << 24 ) );                                      \
+    hashv += (_hj_key[8] + ( (unsigned)_hj_key[9] << 8 )                         \
+        + ( (unsigned)_hj_key[10] << 16 )                                        \
+        + ( (unsigned)_hj_key[11] << 24 ) );                                     \
+                                                                                 \
+     HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                          \
+                                                                                 \
+     _hj_key += 12;                                                              \
+     _hj_k -= 12;                                                                \
+  }                                                                              \
+  hashv += keylen;                                                               \
+  switch ( _hj_k ) {                                                             \
+     case 11: hashv += ( (unsigned)_hj_key[10] << 24 );                          \
+     case 10: hashv += ( (unsigned)_hj_key[9] << 16 );                           \
+     case 9:  hashv += ( (unsigned)_hj_key[8] << 8 );                            \
+     case 8:  _hj_j += ( (unsigned)_hj_key[7] << 24 );                           \
+     case 7:  _hj_j += ( (unsigned)_hj_key[6] << 16 );                           \
+     case 6:  _hj_j += ( (unsigned)_hj_key[5] << 8 );                            \
+     case 5:  _hj_j += _hj_key[4];                                               \
+     case 4:  _hj_i += ( (unsigned)_hj_key[3] << 24 );                           \
+     case 3:  _hj_i += ( (unsigned)_hj_key[2] << 16 );                           \
+     case 2:  _hj_i += ( (unsigned)_hj_key[1] << 8 );                            \
+     case 1:  _hj_i += _hj_key[0];                                               \
+  }                                                                              \
+  HASH_JEN_MIX(_hj_i, _hj_j, hashv);                                             \
+  bkt = hashv & (num_bkts-1);                                                    \
+} while(0)
+
+/* The Paul Hsieh hash function */
+#undef get16bits
+#if (defined(__GNUC__) && defined(__i386__)) || defined(__WATCOMC__)             \
+  || defined(_MSC_VER) || defined (__BORLANDC__) || defined (__TURBOC__)
+#define get16bits(d) (*((const uint16_t *) (d)))
+#endif
+
+#if !defined (get16bits)
+#define get16bits(d) ((((uint32_t)(((const uint8_t *)(d))[1])) << 8)             \
+                       +(uint32_t)(((const uint8_t *)(d))[0]) )
+#endif
+#define HASH_SFH(key,keylen,num_bkts,hashv,bkt)                                  \
+do {                                                                             \
+  char *_sfh_key=(char*)(key);                                                   \
+  uint32_t _sfh_tmp, _sfh_len = keylen;                                          \
+                                                                                 \
+  int _sfh_rem = _sfh_len & 3;                                                   \
+  _sfh_len >>= 2;                                                                \
+  hashv = 0xcafebabe;                                                            \
+                                                                                 \
+  /* Main loop */                                                                \
+  for (;_sfh_len > 0; _sfh_len--) {                                              \
+    hashv    += get16bits (_sfh_key);                                            \
+    _sfh_tmp       = (get16bits (_sfh_key+2) << 11) ^ hashv;                     \
+    hashv     = (hashv << 16) ^ _sfh_tmp;                                        \
+    _sfh_key += 2*sizeof (uint16_t);                                             \
+    hashv    += hashv >> 11;                                                     \
+  }                                                                              \
+                                                                                 \
+  /* Handle end cases */                                                         \
+  switch (_sfh_rem) {                                                            \
+    case 3: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 16;                                                \
+            hashv ^= _sfh_key[sizeof (uint16_t)] << 18;                          \
+            hashv += hashv >> 11;                                                \
+            break;                                                               \
+    case 2: hashv += get16bits (_sfh_key);                                       \
+            hashv ^= hashv << 11;                                                \
+            hashv += hashv >> 17;                                                \
+            break;                                                               \
+    case 1: hashv += *_sfh_key;                                                  \
+            hashv ^= hashv << 10;                                                \
+            hashv += hashv >> 1;                                                 \
+  }                                                                              \
+                                                                                 \
+    /* Force "avalanching" of final 127 bits */                                  \
+    hashv ^= hashv << 3;                                                         \
+    hashv += hashv >> 5;                                                         \
+    hashv ^= hashv << 4;                                                         \
+    hashv += hashv >> 17;                                                        \
+    hashv ^= hashv << 25;                                                        \
+    hashv += hashv >> 6;                                                         \
+    bkt = hashv & (num_bkts-1);                                                  \
+} while(0);
+
+#ifdef HASH_USING_NO_STRICT_ALIASING
+/* The MurmurHash exploits some CPU's (x86,x86_64) tolerance for unaligned reads.
+ * For other types of CPU's (e.g. Sparc) an unaligned read causes a bus error.
+ * MurmurHash uses the faster approach only on CPU's where we know it's safe.
+ *
+ * Note the preprocessor built-in defines can be emitted using:
+ *
+ *   gcc -m64 -dM -E - < /dev/null                  (on gcc)
+ *   cc -## a.c (where a.c is a simple test file)   (Sun Studio)
+ */
+#if (defined(__i386__) || defined(__x86_64__))
+#define MUR_GETBLOCK(p,i) p[i]
+#else /* non intel */
+#define MUR_PLUS0_ALIGNED(p) (((unsigned long)p & 0x3) == 0)
+#define MUR_PLUS1_ALIGNED(p) (((unsigned long)p & 0x3) == 1)
+#define MUR_PLUS2_ALIGNED(p) (((unsigned long)p & 0x3) == 2)
+#define MUR_PLUS3_ALIGNED(p) (((unsigned long)p & 0x3) == 3)
+#define WP(p) ((uint32_t*)((unsigned long)(p) & ~3UL))
+#if (defined(__BIG_ENDIAN__) || defined(SPARC) || defined(__ppc__) || defined(__ppc64__))
+#define MUR_THREE_ONE(p) ((((*WP(p))&0x00ffffff) << 8) | (((*(WP(p)+1))&0xff000000) >> 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0x0000ffff) <<16) | (((*(WP(p)+1))&0xffff0000) >> 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0x000000ff) <<24) | (((*(WP(p)+1))&0xffffff00) >>  8))
+#else /* assume little endian non-intel */
+#define MUR_THREE_ONE(p) ((((*WP(p))&0xffffff00) >> 8) | (((*(WP(p)+1))&0x000000ff) << 24))
+#define MUR_TWO_TWO(p)   ((((*WP(p))&0xffff0000) >>16) | (((*(WP(p)+1))&0x0000ffff) << 16))
+#define MUR_ONE_THREE(p) ((((*WP(p))&0xff000000) >>24) | (((*(WP(p)+1))&0x00ffffff) <<  8))
+#endif
+#define MUR_GETBLOCK(p,i) (MUR_PLUS0_ALIGNED(p) ? ((p)[i]) :           \
+                            (MUR_PLUS1_ALIGNED(p) ? MUR_THREE_ONE(p) : \
+                             (MUR_PLUS2_ALIGNED(p) ? MUR_TWO_TWO(p) :  \
+                                                      MUR_ONE_THREE(p))))
+#endif
+#define MUR_ROTL32(x,r) (((x) << (r)) | ((x) >> (32 - (r))))
+#define MUR_FMIX(_h) \
+do {                 \
+  _h ^= _h >> 16;    \
+  _h *= 0x85ebca6b;  \
+  _h ^= _h >> 13;    \
+  _h *= 0xc2b2ae35l; \
+  _h ^= _h >> 16;    \
+} while(0)
+
+#define HASH_MUR(key,keylen,num_bkts,hashv,bkt)                        \
+do {                                                                   \
+  const uint8_t *_mur_data = (const uint8_t*)(key);                    \
+  const int _mur_nblocks = (keylen) / 4;                               \
+  uint32_t _mur_h1 = 0xf88D5353;                                       \
+  uint32_t _mur_c1 = 0xcc9e2d51;                                       \
+  uint32_t _mur_c2 = 0x1b873593;                                       \
+  const uint32_t *_mur_blocks = (const uint32_t*)(_mur_data+_mur_nblocks*4); \
+  int _mur_i;                                                          \
+  for(_mur_i = -_mur_nblocks; _mur_i; _mur_i++) {                      \
+    uint32_t _mur_k1 = MUR_GETBLOCK(_mur_blocks,_mur_i);               \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+                                                                       \
+    _mur_h1 ^= _mur_k1;                                                \
+    _mur_h1 = MUR_ROTL32(_mur_h1,13);                                  \
+    _mur_h1 = _mur_h1*5+0xe6546b64;                                    \
+  }                                                                    \
+  const uint8_t *_mur_tail = (const uint8_t*)(_mur_data + _mur_nblocks*4); \
+  uint32_t _mur_k1=0;                                                  \
+  switch((keylen) & 3) {                                               \
+    case 3: _mur_k1 ^= _mur_tail[2] << 16;                             \
+    case 2: _mur_k1 ^= _mur_tail[1] << 8;                              \
+    case 1: _mur_k1 ^= _mur_tail[0];                                   \
+    _mur_k1 *= _mur_c1;                                                \
+    _mur_k1 = MUR_ROTL32(_mur_k1,15);                                  \
+    _mur_k1 *= _mur_c2;                                                \
+    _mur_h1 ^= _mur_k1;                                                \
+  }                                                                    \
+  _mur_h1 ^= (keylen);                                                 \
+  MUR_FMIX(_mur_h1);                                                   \
+  hashv = _mur_h1;                                                     \
+  bkt = hashv & (num_bkts-1);                                          \
+} while(0)
+#endif  /* HASH_USING_NO_STRICT_ALIASING */
+
+/* key comparison function; return 0 if keys equal */
+#define HASH_KEYCMP(a,b,len) memcmp(a,b,len)
+
+/* iterate over items in a known bucket to find desired item */
+#define HASH_FIND_IN_BKT(tbl,hh,head,keyptr,keylen_in,out)                       \
+do {                                                                             \
+ if (head.hh_head) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,head.hh_head));          \
+ else out=NULL;                                                                  \
+ while (out) {                                                                   \
+    if (out->hh.keylen == keylen_in) {                                           \
+        if ((HASH_KEYCMP(out->hh.key,keyptr,keylen_in)) == 0) break;             \
+    }                                                                            \
+    if (out->hh.hh_next) DECLTYPE_ASSIGN(out,ELMT_FROM_HH(tbl,out->hh.hh_next)); \
+    else out = NULL;                                                             \
+ }                                                                               \
+} while(0)
+
+/* add an item to a bucket  */
+#define HASH_ADD_TO_BKT(head,addhh)                                              \
+do {                                                                             \
+ head.count++;                                                                   \
+ (addhh)->hh_next = head.hh_head;                                                \
+ (addhh)->hh_prev = NULL;                                                        \
+ if (head.hh_head) { (head).hh_head->hh_prev = (addhh); }                        \
+ (head).hh_head=addhh;                                                           \
+ if (head.count >= ((head.expand_mult+1) * HASH_BKT_CAPACITY_THRESH)             \
+     && (addhh)->tbl->noexpand != 1) {                                           \
+       HASH_EXPAND_BUCKETS((addhh)->tbl);                                        \
+ }                                                                               \
+} while(0)
+
+/* remove an item from a given bucket */
+#define HASH_DEL_IN_BKT(hh,head,hh_del)                                          \
+    (head).count--;                                                              \
+    if ((head).hh_head == hh_del) {                                              \
+      (head).hh_head = hh_del->hh_next;                                          \
+    }                                                                            \
+    if (hh_del->hh_prev) {                                                       \
+        hh_del->hh_prev->hh_next = hh_del->hh_next;                              \
+    }                                                                            \
+    if (hh_del->hh_next) {                                                       \
+        hh_del->hh_next->hh_prev = hh_del->hh_prev;                              \
+    }
+
+/* Bucket expansion has the effect of doubling the number of buckets
+ * and redistributing the items into the new buckets. Ideally the
+ * items will distribute more or less evenly into the new buckets
+ * (the extent to which this is true is a measure of the quality of
+ * the hash function as it applies to the key domain).
+ *
+ * With the items distributed into more buckets, the chain length
+ * (item count) in each bucket is reduced. Thus by expanding buckets
+ * the hash keeps a bound on the chain length. This bounded chain
+ * length is the essence of how a hash provides constant time lookup.
+ *
+ * The calculation of tbl->ideal_chain_maxlen below deserves some
+ * explanation. First, keep in mind that we're calculating the ideal
+ * maximum chain length based on the *new* (doubled) bucket count.
+ * In fractions this is just n/b (n=number of items,b=new num buckets).
+ * Since the ideal chain length is an integer, we want to calculate
+ * ceil(n/b). We don't depend on floating point arithmetic in this
+ * hash, so to calculate ceil(n/b) with integers we could write
+ *
+ *      ceil(n/b) = (n/b) + ((n%b)?1:0)
+ *
+ * and in fact a previous version of this hash did just that.
+ * But now we have improved things a bit by recognizing that b is
+ * always a power of two. We keep its base 2 log handy (call it lb),
+ * so now we can write this with a bit shift and logical AND:
+ *
+ *      ceil(n/b) = (n>>lb) + ( (n & (b-1)) ? 1:0)
+ *
+ */
+#define HASH_EXPAND_BUCKETS(tbl)                                                 \
+do {                                                                             \
+    unsigned _he_bkt;                                                            \
+    unsigned _he_bkt_i;                                                          \
+    struct UT_hash_handle *_he_thh, *_he_hh_nxt;                                 \
+    UT_hash_bucket *_he_new_buckets, *_he_newbkt;                                \
+    _he_new_buckets = (UT_hash_bucket*)uthash_malloc(                            \
+             2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));              \
+    if (!_he_new_buckets) { uthash_fatal( "out of memory"); }                    \
+    memset(_he_new_buckets, 0,                                                   \
+            2 * tbl->num_buckets * sizeof(struct UT_hash_bucket));               \
+    tbl->ideal_chain_maxlen =                                                    \
+       (tbl->num_items >> (tbl->log2_num_buckets+1)) +                           \
+       ((tbl->num_items & ((tbl->num_buckets*2)-1)) ? 1 : 0);                    \
+    tbl->nonideal_items = 0;                                                     \
+    for(_he_bkt_i = 0; _he_bkt_i < tbl->num_buckets; _he_bkt_i++)                \
+    {                                                                            \
+        _he_thh = tbl->buckets[ _he_bkt_i ].hh_head;                             \
+        while (_he_thh) {                                                        \
+           _he_hh_nxt = _he_thh->hh_next;                                        \
+           HASH_TO_BKT( _he_thh->hashv, tbl->num_buckets*2, _he_bkt);            \
+           _he_newbkt = &(_he_new_buckets[ _he_bkt ]);                           \
+           if (++(_he_newbkt->count) > tbl->ideal_chain_maxlen) {                \
+             tbl->nonideal_items++;                                              \
+             _he_newbkt->expand_mult = _he_newbkt->count /                       \
+                                        tbl->ideal_chain_maxlen;                 \
+           }                                                                     \
+           _he_thh->hh_prev = NULL;                                              \
+           _he_thh->hh_next = _he_newbkt->hh_head;                               \
+           if (_he_newbkt->hh_head) _he_newbkt->hh_head->hh_prev =               \
+                _he_thh;                                                         \
+           _he_newbkt->hh_head = _he_thh;                                        \
+           _he_thh = _he_hh_nxt;                                                 \
+        }                                                                        \
+    }                                                                            \
+    uthash_free( tbl->buckets, tbl->num_buckets*sizeof(struct UT_hash_bucket) ); \
+    tbl->num_buckets *= 2;                                                       \
+    tbl->log2_num_buckets++;                                                     \
+    tbl->buckets = _he_new_buckets;                                              \
+    tbl->ineff_expands = (tbl->nonideal_items > (tbl->num_items >> 1)) ?         \
+        (tbl->ineff_expands+1) : 0;                                              \
+    if (tbl->ineff_expands > 1) {                                                \
+        tbl->noexpand=1;                                                         \
+        uthash_noexpand_fyi(tbl);                                                \
+    }                                                                            \
+    uthash_expand_fyi(tbl);                                                      \
+} while(0)
+
+
+/* This is an adaptation of Simon Tatham's O(n log(n)) mergesort */
+/* Note that HASH_SORT assumes the hash handle name to be hh.
+ * HASH_SRT was added to allow the hash handle name to be passed in. */
+#define HASH_SORT(head,cmpfcn) HASH_SRT(hh,head,cmpfcn)
+#define HASH_SRT(hh,head,cmpfcn)                                                 \
+do {                                                                             \
+  unsigned _hs_i;                                                                \
+  unsigned _hs_looping,_hs_nmerges,_hs_insize,_hs_psize,_hs_qsize;               \
+  struct UT_hash_handle *_hs_p, *_hs_q, *_hs_e, *_hs_list, *_hs_tail;            \
+  if (head) {                                                                    \
+      _hs_insize = 1;                                                            \
+      _hs_looping = 1;                                                           \
+      _hs_list = &((head)->hh);                                                  \
+      while (_hs_looping) {                                                      \
+          _hs_p = _hs_list;                                                      \
+          _hs_list = NULL;                                                       \
+          _hs_tail = NULL;                                                       \
+          _hs_nmerges = 0;                                                       \
+          while (_hs_p) {                                                        \
+              _hs_nmerges++;                                                     \
+              _hs_q = _hs_p;                                                     \
+              _hs_psize = 0;                                                     \
+              for ( _hs_i = 0; _hs_i  < _hs_insize; _hs_i++ ) {                  \
+                  _hs_psize++;                                                   \
+                  _hs_q = (UT_hash_handle*)((_hs_q->next) ?                      \
+                          ((void*)((char*)(_hs_q->next) +                        \
+                          (head)->hh.tbl->hho)) : NULL);                         \
+                  if (! (_hs_q) ) break;                                         \
+              }                                                                  \
+              _hs_qsize = _hs_insize;                                            \
+              while ((_hs_psize > 0) || ((_hs_qsize > 0) && _hs_q )) {           \
+                  if (_hs_psize == 0) {                                          \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  } else if ( (_hs_qsize == 0) || !(_hs_q) ) {                   \
+                      _hs_e = _hs_p;                                             \
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
+                              ((void*)((char*)(_hs_p->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_psize--;                                               \
+                  } else if ((                                                   \
+                      cmpfcn(DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_p)), \
+                             DECLTYPE(head)(ELMT_FROM_HH((head)->hh.tbl,_hs_q))) \
+                             ) <= 0) {                                           \
+                      _hs_e = _hs_p;                                             \
+                      _hs_p = (UT_hash_handle*)((_hs_p->next) ?                  \
+                              ((void*)((char*)(_hs_p->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_psize--;                                               \
+                  } else {                                                       \
+                      _hs_e = _hs_q;                                             \
+                      _hs_q = (UT_hash_handle*)((_hs_q->next) ?                  \
+                              ((void*)((char*)(_hs_q->next) +                    \
+                              (head)->hh.tbl->hho)) : NULL);                     \
+                      _hs_qsize--;                                               \
+                  }                                                              \
+                  if ( _hs_tail ) {                                              \
+                      _hs_tail->next = ((_hs_e) ?                                \
+                            ELMT_FROM_HH((head)->hh.tbl,_hs_e) : NULL);          \
+                  } else {                                                       \
+                      _hs_list = _hs_e;                                          \
+                  }                                                              \
+                  _hs_e->prev = ((_hs_tail) ?                                    \
+                     ELMT_FROM_HH((head)->hh.tbl,_hs_tail) : NULL);              \
+                  _hs_tail = _hs_e;                                              \
+              }                                                                  \
+              _hs_p = _hs_q;                                                     \
+          }                                                                      \
+          _hs_tail->next = NULL;                                                 \
+          if ( _hs_nmerges <= 1 ) {                                              \
+              _hs_looping=0;                                                     \
+              (head)->hh.tbl->tail = _hs_tail;                                   \
+              DECLTYPE_ASSIGN(head,ELMT_FROM_HH((head)->hh.tbl, _hs_list));      \
+          }                                                                      \
+          _hs_insize *= 2;                                                       \
+      }                                                                          \
+      HASH_FSCK(hh,head);                                                        \
+ }                                                                               \
+} while (0)
+
+/* This function selects items from one hash into another hash.
+ * The end result is that the selected items have dual presence
+ * in both hashes. There is no copy of the items made; rather
+ * they are added into the new hash through a secondary hash
+ * hash handle that must be present in the structure. */
+#define HASH_SELECT(hh_dst, dst, hh_src, src, cond)                              \
+do {                                                                             \
+  unsigned _src_bkt, _dst_bkt;                                                   \
+  void *_last_elt=NULL, *_elt;                                                   \
+  UT_hash_handle *_src_hh, *_dst_hh, *_last_elt_hh=NULL;                         \
+  ptrdiff_t _dst_hho = ((char*)(&(dst)->hh_dst) - (char*)(dst));                 \
+  if (src) {                                                                     \
+    for(_src_bkt=0; _src_bkt < (src)->hh_src.tbl->num_buckets; _src_bkt++) {     \
+      for(_src_hh = (src)->hh_src.tbl->buckets[_src_bkt].hh_head;                \
+          _src_hh;                                                               \
+          _src_hh = _src_hh->hh_next) {                                          \
+          _elt = ELMT_FROM_HH((src)->hh_src.tbl, _src_hh);                       \
+          if (cond(_elt)) {                                                      \
+            _dst_hh = (UT_hash_handle*)(((char*)_elt) + _dst_hho);               \
+            _dst_hh->key = _src_hh->key;                                         \
+            _dst_hh->keylen = _src_hh->keylen;                                   \
+            _dst_hh->hashv = _src_hh->hashv;                                     \
+            _dst_hh->prev = _last_elt;                                           \
+            _dst_hh->next = NULL;                                                \
+            if (_last_elt_hh) { _last_elt_hh->next = _elt; }                     \
+            if (!dst) {                                                          \
+              DECLTYPE_ASSIGN(dst,_elt);                                         \
+              HASH_MAKE_TABLE(hh_dst,dst);                                       \
+            } else {                                                             \
+              _dst_hh->tbl = (dst)->hh_dst.tbl;                                  \
+            }                                                                    \
+            HASH_TO_BKT(_dst_hh->hashv, _dst_hh->tbl->num_buckets, _dst_bkt);    \
+            HASH_ADD_TO_BKT(_dst_hh->tbl->buckets[_dst_bkt],_dst_hh);            \
+            (dst)->hh_dst.tbl->num_items++;                                      \
+            _last_elt = _elt;                                                    \
+            _last_elt_hh = _dst_hh;                                              \
+          }                                                                      \
+      }                                                                          \
+    }                                                                            \
+  }                                                                              \
+  HASH_FSCK(hh_dst,dst);                                                         \
+} while (0)
+
+#define HASH_CLEAR(hh,head)                                                      \
+do {                                                                             \
+  if (head) {                                                                    \
+    uthash_free((head)->hh.tbl->buckets,                                         \
+                (head)->hh.tbl->num_buckets*sizeof(struct UT_hash_bucket));      \
+    uthash_free((head)->hh.tbl, sizeof(UT_hash_table));                          \
+    (head)=NULL;                                                                 \
+  }                                                                              \
+} while(0)
+
+#ifdef NO_DECLTYPE
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for((el)=(head), (*(char**)(&(tmp)))=(char*)((head)?(head)->hh.next:NULL);       \
+  el; (el)=(tmp),(*(char**)(&(tmp)))=(char*)((tmp)?(tmp)->hh.next:NULL))
+#else
+#define HASH_ITER(hh,head,el,tmp)                                                \
+for((el)=(head),(tmp)=DECLTYPE(el)((head)?(head)->hh.next:NULL);                 \
+  el; (el)=(tmp),(tmp)=DECLTYPE(el)((tmp)?(tmp)->hh.next:NULL))
+#endif
+
+/* obtain a count of items in the hash */
+#define HASH_COUNT(head) HASH_CNT(hh,head)
+#define HASH_CNT(hh,head) ((head)?((head)->hh.tbl->num_items):0)
+
+typedef struct UT_hash_bucket {
+   struct UT_hash_handle *hh_head;
+   unsigned count;
+
+   /* expand_mult is normally set to 0. In this situation, the max chain length
+    * threshold is enforced at its default value, HASH_BKT_CAPACITY_THRESH. (If
+    * the bucket's chain exceeds this length, bucket expansion is triggered).
+    * However, setting expand_mult to a non-zero value delays bucket expansion
+    * (that would be triggered by additions to this particular bucket)
+    * until its chain length reaches a *multiple* of HASH_BKT_CAPACITY_THRESH.
+    * (The multiplier is simply expand_mult+1). The whole idea of this
+    * multiplier is to reduce bucket expansions, since they are expensive, in
+    * situations where we know that a particular bucket tends to be overused.
+    * It is better to let its chain length grow to a longer yet-still-bounded
+    * value, than to do an O(n) bucket expansion too often.
+    */
+   unsigned expand_mult;
+
+} UT_hash_bucket;
+
+/* random signature used only to find hash tables in external analysis */
+#define HASH_SIGNATURE 0xa0111fe1
+#define HASH_BLOOM_SIGNATURE 0xb12220f2
+
+typedef struct UT_hash_table {
+   UT_hash_bucket *buckets;
+   unsigned num_buckets, log2_num_buckets;
+   unsigned num_items;
+   struct UT_hash_handle *tail; /* tail hh in app order, for fast append    */
+   ptrdiff_t hho; /* hash handle offset (byte pos of hash handle in element */
+
+   /* in an ideal situation (all buckets used equally), no bucket would have
+    * more than ceil(#items/#buckets) items. that's the ideal chain length. */
+   unsigned ideal_chain_maxlen;
+
+   /* nonideal_items is the number of items in the hash whose chain position
+    * exceeds the ideal chain maxlen. these items pay the penalty for an uneven
+    * hash distribution; reaching them in a chain traversal takes >ideal steps */
+   unsigned nonideal_items;
+
+   /* ineffective expands occur when a bucket doubling was performed, but
+    * afterward, more than half the items in the hash had nonideal chain
+    * positions. If this happens on two consecutive expansions we inhibit any
+    * further expansion, as it's not helping; this happens when the hash
+    * function isn't a good fit for the key domain. When expansion is inhibited
+    * the hash will still work, albeit no longer in constant time. */
+   unsigned ineff_expands, noexpand;
+
+   uint32_t signature; /* used only to find hash tables in external analysis */
+#ifdef HASH_BLOOM
+   uint32_t bloom_sig; /* used only to test bloom exists in external analysis */
+   uint8_t *bloom_bv;
+   char bloom_nbits;
+#endif
+
+} UT_hash_table;
+
+typedef struct UT_hash_handle {
+   struct UT_hash_table *tbl;
+   void *prev;                       /* prev element in app order      */
+   void *next;                       /* next element in app order      */
+   struct UT_hash_handle *hh_prev;   /* previous hh in bucket order    */
+   struct UT_hash_handle *hh_next;   /* next hh in bucket order        */
+   void *key;                        /* ptr to enclosing struct's key  */
+   unsigned keylen;                  /* enclosing struct's key len     */
+   unsigned hashv;                   /* result of hash-fcn(key)        */
+} UT_hash_handle;
+
+#endif /* UTHASH_H */
diff --git a/inc/verify.h b/inc/verify.h
new file mode 100644
index 0000000..b5e5c21
--- /dev/null
+++ b/inc/verify.h
@@ -0,0 +1,150 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 VERIFY_H
+#define VERIFY_H
+
+#include "AEEstd.h"
+
+//#define VERIFY_PRINT_ERROR
+//#define VERIFY_PRINT_INFO
+
+
+#ifndef _WIN32
+#define C_ASSERT(test) \
+    switch(0) {\
+      case 0:\
+      case test:;\
+    }
+#endif // _WIN32
+
+#ifndef __V_STR__
+	#define __V_STR__(x) #x ":"
+#endif //__STR__
+#ifndef __V_TOSTR__
+	#define __V_TOSTR__(x) __V_STR__(x)
+#endif // __TOSTR__
+#ifndef __V_FILE_LINE__
+	#define __V_FILE_LINE__ __FILE__ ":" __V_TOSTR__(__LINE__)
+#endif /*__FILE_LINE__*/
+
+
+#ifdef __ANDROID__
+/*android */
+#if (defined VERIFY_PRINT_INFO) || (defined VERIFY_PRINT_ERROR)
+#include <android/log.h>
+#endif
+
+extern const char* __progname;
+#ifdef VERIFY_PRINT_INFO
+#define VERIFY_IPRINTF(format, ...) __android_log_print(ANDROID_LOG_DEBUG , __progname, __V_FILE_LINE__ format, ##__VA_ARGS__)
+#endif
+
+#ifdef VERIFY_PRINT_ERROR
+#define VERIFY_EPRINTF(format, ...) __android_log_print(ANDROID_LOG_ERROR , __progname, __V_FILE_LINE__ format, ##__VA_ARGS__)
+#endif
+
+/* end android */
+#elif (defined __hexagon__) || (defined __qdsp6__)
+/* q6 */
+
+#ifdef VERIFY_PRINT_INFO
+   #define FARF_VERIFY_LOW  1
+   #define FARF_VERIFY_LOW_LEVEL HAP_LEVEL_LOW
+   #define VERIFY_IPRINTF(args...) FARF(VERIFY_LOW, args)
+#endif
+
+#ifdef VERIFY_PRINT_ERROR
+   #define FARF_VERIFY_ERROR         1
+   #define FARF_VERIFY_ERROR_LEVEL HAP_LEVEL_ERROR
+   #define VERIFY_EPRINTF(args...) FARF(VERIFY_ERROR, args)
+#endif
+
+#if (defined VERIFY_PRINT_INFO) || (defined VERIFY_PRINT_ERROR)
+   #include "HAP_farf.h"
+#endif
+
+/* end q6 */
+#else
+/* generic */
+
+#if (defined VERIFY_PRINT_INFO) || (defined VERIFY_PRINT_ERROR)
+#include <stdio.h>
+#endif
+
+#ifdef VERIFY_PRINT_INFO
+#define VERIFY_IPRINTF(format, ...) printf(__V_FILE_LINE__ format, ##__VA_ARGS__)
+#endif
+
+#ifdef VERIFY_PRINT_ERROR
+#define VERIFY_EPRINTF(format, ...) printf(__V_FILE_LINE__ format, ##__VA_ARGS__)
+#endif
+
+/* end generic */
+#endif
+
+#ifndef VERIFY_PRINT_INFO
+#define VERIFY_IPRINTF(format, ...) (void)0
+#endif
+
+#ifndef VERIFY_PRINT_ERROR
+#define VERIFY_EPRINTF(format, ...) (void)0
+#endif
+
+#ifndef VERIFY
+	#define VERIFY(val) \
+	   do {\
+		  VERIFY_IPRINTF(":info: calling: " #val "\n");\
+		  if(0 == (val)) {\
+			 nErr = nErr == 0 ? -1 : nErr;\
+			 VERIFY_EPRINTF(":error: %d: " #val "\n", nErr);\
+			 goto bail;\
+		  } else {\
+			 VERIFY_IPRINTF(":info: passed: " #val "\n");\
+		  }\
+	   } while(0)
+#endif //VERIFY
+
+#ifndef VERIFYC
+        #define VERIFYC(val,err_code) \
+           do {\
+                  VERIFY_IPRINTF(":info: calling: " #val "\n");\
+                  if(0 == (val)) {\
+                         nErr = err_code;\
+                         VERIFY_EPRINTF(":Error: %x: " #val "\n", nErr);\
+                         goto bail;\
+                  } else {\
+                         VERIFY_IPRINTF(":info: passed: " #val "\n");\
+                  }\
+           } while(0)
+#endif //VERIFYC
+
+
+#endif //VERIFY_H
+
diff --git a/inc/verify_android.h b/inc/verify_android.h
new file mode 100644
index 0000000..43bc3a2
--- /dev/null
+++ b/inc/verify_android.h
@@ -0,0 +1,47 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 VERIFY_ANDROID
+#define VERIFY_ANDROID
+
+#ifdef __ANDROID__
+
+#include <android/log.h>
+
+#ifdef VERIFY_PRINT_INFO
+#define VERIFY_IPRINTF(format) __android_log_print(ANDROID_LOG_DEBUG , "adsprpc", format)
+#endif
+
+#ifdef VERIFY_PRINT_ERROR
+#define VERIFY_EPRINTF(format, ...) __android_log_print(ANDROID_LOG_ERROR , "adsprpc", format, ##__VA_ARGS__)
+#endif
+
+#endif //ANDROID
+
+#endif //VERIFY_ANDROID
diff --git a/inc/version.h b/inc/version.h
new file mode 100644
index 0000000..c75bc86
--- /dev/null
+++ b/inc/version.h
@@ -0,0 +1,119 @@
+#ifndef VERSION_H
+#define VERSION_H
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#if !defined(VERSION_CL)
+#define VERSION_CL "?"
+#endif
+
+#if !defined(VERSION_PROD)
+#define VERSION_PROD "unknown"
+#endif
+
+#if !defined(VERSION_BRANCH)
+#define VERSION_BRANCH "?"
+#endif
+
+#if !defined(VERSION_NUM)
+#define VERSION_NUM "?.?.?.?"
+#endif
+
+#define VERSION_STRING                                              \
+   VERSION_PROD " "                                                 \
+   VERSION_NUM " "                                                  \
+   "(br=" VERSION_BRANCH "; cl=" VERSION_CL ")"
+
+/*
+=======================================================================
+MACROS DOCUMENTATION
+=======================================================================
+
+VERSION_MAJOR
+
+Description:
+	Defines the major release number of the version.
+
+Comments:
+    It has to be a valid numerical value
+=======================================================================
+
+VERSION_MINOR
+
+Description:
+	Defines the minor release number of the version.
+
+Comments:
+    It has to be a valid numerical value
+=======================================================================
+
+VERSION_MAINT
+
+Description:
+	Defines the maintenance release of the version.
+
+Comments:
+    It has to be a valid numerical value
+=======================================================================
+
+VERSION_BUILD
+
+Description:
+	Defines the build ID of the version.
+
+Comments:
+    It has to be a valid numerical value
+=======================================================================
+
+VERSION_STRING
+
+Description:
+	Defines the version string that specifies the version number.
+
+Definition:
+
+   #define VERSION_STRING "a.b.c.d (name=value;name=value;...)"
+	where a=major release number
+	      b=minor release number
+	      c=maintenance release number
+	      d=build number
+
+	name=value pair provides additional information about the build.
+	Example:
+	patch/feature=comma separated list of features/patches that have been installed.
+	br=p4 branch that was used for the build
+	cl=p4 change list number
+	machine=hostname of the machine that was used for the build.
+
+Comments:
+
+=======================================================================
+*/
+
+#endif // VERSION_H
diff --git a/src/AEEsmath.h b/src/AEEsmath.h
new file mode 100644
index 0000000..1acac47
--- /dev/null
+++ b/src/AEEsmath.h
@@ -0,0 +1,38 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+/*======================================================================
+
+DESCRIPTION:  Safe math library; implements saturating add.
+
+====================================================================*/
+
+extern int smath_Add(int a, int b);
+extern int smath_Sub(int a, int b);
+extern int smath_Mul(int a, int b);
diff --git a/src/BufBound.c b/src/BufBound.c
new file mode 100644
index 0000000..e9e64e3
--- /dev/null
+++ b/src/BufBound.c
@@ -0,0 +1,225 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+/*==============================================================================
+
+FILE:  AEEBufBound.c
+
+SERVICES:
+        AEEBufBound APIs
+
+GENERAL DESCRIPTION:
+        AEEBufBound provides a "bounded buffer" API that facilitates
+          measuring strings or character output.  It's design accomodates
+          the implementation of functions that can have the same exact logic
+          for measuring and outputting char buffer content.
+
+REVISION HISTORY:
+        Sun Mar 06 11:23:10 2005 Created
+
+==============================================================================*/
+#include <limits.h>
+#include "AEEBufBound.h"
+#include "AEEstd.h"
+
+// Note on bounds-checking logic and saturation:
+//
+// Simple pointer comparisons are not adequate for bounds checking.  pcBuf
+// and pcEnd are assumed to be valid pointers in the address space.  But
+// pcWrite is not ... it is a theoretical value that can exceed pcEnd, and
+// may in fact wrap around the end of the address space.  In that case the
+// test for (pcWrite < pcEnd) will yield TRUE, although pcWrite is outside
+// the buffer.  Use (pcEnd-pcWrite) > 0 to be accurate.
+//
+// In order to ensure this works in all cases, we need to avoid integer
+// overflows.  We do this by restricting pcWrite to the range
+// [pcBuf..pcBuf+INT_MAX].  The ensures that pcWrite-pcBuf and pcWrite-pcBuf
+// will always be valid integers.  It also allows us to ensure that
+// BufBound_Wrote() will not return wildly misleading results.
+//
+//                                            PCSAT
+//    pcBuf               pcEnd            pcBuf+MAXINT
+//      |-------------------| . . . . . . . . . |
+//                   ^            ^
+//    pcWrite:      (a)          (b)
+//
+
+#define PCSAT(me)   ((me)->pcBuf + INT_MAX)
+
+
+// Advance me->pcWrite, saturating.
+//
+// On entry:
+//    *pnLen = number of bytes to be written (non-negative)
+// On exit:
+//    return value = where to write (pointer into the buffer)
+//    *pnLen       = number of bytes to write
+//
+static char *
+BufBound_ValidateWrite(BufBound *me, int *pnLen)
+{
+   int nLen = *pnLen;
+   char *pcWrite = me->pcWrite;
+   int nMaxCopy = me->pcEnd - pcWrite;        // could be negative!
+
+   if ( nMaxCopy < nLen ) {
+      // Must check PCSAT to validate advance
+      int nMaxAdvance = PCSAT(me) - pcWrite;      // max amount to advance
+
+      if (nLen > nMaxAdvance) {
+         nLen = nMaxAdvance;
+      }
+      if (nMaxCopy < 0) {
+         nMaxCopy = 0;
+      }
+   } else {
+      // Simple case: all fits in the buffer
+      nMaxCopy = nLen;
+   }
+
+   *pnLen = nMaxCopy;
+   me->pcWrite = pcWrite + nLen;
+   return pcWrite;
+}
+
+void BufBound_Write(BufBound *me, const char *pc, int nLen)
+{
+   if (nLen > 0) {
+      char *pcDest = BufBound_ValidateWrite(me, &nLen);
+
+      while (--nLen >= 0) {
+         pcDest[nLen] = pc[nLen];
+      }
+   }
+}
+
+void BufBound_Putnc(BufBound *me, char c, int nLen)
+{
+   if (nLen > 0) {
+      char *pcDest = BufBound_ValidateWrite(me, &nLen);
+
+      while (--nLen >= 0) {
+         pcDest[nLen] = c;
+      }
+   }
+}
+
+void BufBound_Advance(BufBound *me, int nLen)
+{
+   uint32 uOffset = (uint32)((me->pcWrite - me->pcBuf) + nLen);
+
+   if (uOffset > INT_MAX) {
+      uOffset = INT_MAX;
+      if (nLen < 0) {
+         uOffset = 0;
+      }
+   }
+   me->pcWrite = me->pcBuf + uOffset;
+}
+
+void BufBound_Init(BufBound *me, char *pBuf, int nLen)
+{
+   if (nLen < 0) {
+      nLen = 0;
+   }
+   me->pcWrite = me->pcBuf = pBuf;
+   me->pcEnd   = pBuf + nLen;
+}
+
+void BufBound_Putc(BufBound *me, char c)
+{
+   if ( (me->pcEnd - me->pcWrite) > 0) {
+      *me->pcWrite++ = c;
+   } else if (me->pcWrite != PCSAT(me)) {
+      ++me->pcWrite;
+   }
+}
+
+void BufBound_ForceNullTerm(BufBound *me)
+{
+   if ( (me->pcEnd - me->pcWrite) > 0) {
+      *me->pcWrite++ = '\0';
+   } else {
+      if (me->pcWrite != PCSAT(me)) {
+         ++me->pcWrite;
+      }
+      // ensure null termination if non-empty buffer
+      if (me->pcEnd != me->pcBuf) {
+         me->pcEnd[-1] = '\0';
+      }
+   }
+}
+
+void BufBound_Puts(BufBound *me, const char* cpsz)
+{
+   BufBound_Write(me, cpsz, std_strlen(cpsz));
+}
+
+int BufBound_BufSize(BufBound* me)
+{
+   return me->pcEnd - me->pcBuf;
+}
+
+int BufBound_Left(BufBound* me)
+{
+   return (me->pcEnd - me->pcWrite);
+}
+
+int BufBound_ReallyWrote(BufBound* me)
+{
+   return STD_MIN(me->pcEnd - me->pcBuf, me->pcWrite - me->pcBuf);
+}
+
+int BufBound_Wrote(BufBound* me)
+{
+   return (me->pcWrite - me->pcBuf);
+}
+
+void BufBound_WriteLE(BufBound *me,
+                      const void *pvSrc, int nSrcSize,
+                      const char *pszFields)
+{
+   if (nSrcSize > 0) {
+      int nLen = nSrcSize;
+      char *pcDest = BufBound_ValidateWrite(me, &nLen);
+
+      (void)std_CopyLE(pcDest, nLen, pvSrc, nSrcSize, pszFields);
+   }
+}
+
+void BufBound_WriteBE(BufBound *me,
+                      const void *pvSrc, int nSrcSize,
+                      const char *pszFields)
+{
+   if (nSrcSize > 0) {
+      int nLen = nSrcSize;
+      char *pcDest = BufBound_ValidateWrite(me, &nLen);
+
+      (void)std_CopyBE(pcDest, nLen, pvSrc, nSrcSize, pszFields);
+   }
+}
diff --git a/src/adsp_current_process1_stub.c b/src/adsp_current_process1_stub.c
new file mode 100644
index 0000000..cffe9d8
--- /dev/null
+++ b/src/adsp_current_process1_stub.c
@@ -0,0 +1,587 @@
+#ifndef _ADSP_CURRENT_PROCESS1_STUB_H
+#define _ADSP_CURRENT_PROCESS1_STUB_H
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "adsp_current_process1.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#include <string.h>
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSP_CURRENT_PROCESS1_SLIM_H
+#define _ADSP_CURRENT_PROCESS1_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[1];
+static const SequenceType sequenceTypes[1] = {{&(types[0]),0x0,0x4,0x4,0x0}};
+static const Type types[1] = {{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8)}};
+static const Parameter parameters[6] = {{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8),0,0},{SLIM_IFPTR32(0x4,0x8),{{(const uintptr_t)0xdeadc0de,(const uintptr_t)0}}, 0,SLIM_IFPTR32(0x4,0x8),3,0},{SLIM_IFPTR32(0x4,0x8),{{(const uintptr_t)0xdeadc0de,(const uintptr_t)0}}, 0,SLIM_IFPTR32(0x4,0x8),0,0},{0x2,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x2,0,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(sequenceTypes[0]),0}}, 25,SLIM_IFPTR32(0x4,0x8),0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,3,0}};
+static const Parameter* const parameterArrays[6] = {(&(parameters[3])),(&(parameters[4])),(&(parameters[0])),(&(parameters[1])),(&(parameters[5])),(&(parameters[2]))};
+static const Method methods[5] = {{REMOTE_SCALARS_MAKEX(0,0,0x2,0x0,0x0,0x1),0x4,0x0,2,2,(&(parameterArrays[2])),0x4,0x1},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x1,0x0),0x0,0x0,1,1,(&(parameterArrays[5])),0x1,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x0,0x0),0x0,0x0,0,0,0,0x0,0x0},{REMOTE_SCALARS_MAKEX(0,0,255,255,15,15),0x8,0x0,3,2,(&(parameterArrays[0])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x1,0x0,0x0),0x0,0x4,1,1,(&(parameterArrays[4])),0x1,0x4}};
+static const Method* const methodArrays[6] = {&(methods[0]),&(methods[1]),&(methods[2]),&(methods[2]),&(methods[3]),&(methods[4])};
+static const char strings[77] = "set_logging_params\0thread_exit\0filesToLog\0getASID\0close\0asid\0mask\0open\0uri\0h\0";
+static const uint16_t methodStrings[12] = {0,61,31,66,71,75,42,56,50,75,19,26};
+static const uint16_t methodStringsArrays[6] = {3,8,11,10,0,6};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adsp_current_process1_slim) = {6,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSP_CURRENT_PROCESS1_SLIM_H
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process1_skel_handle_invoke)(remote_handle64 _h, uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle64_invoke)(_h, _sc, _pra);
+}
+#ifdef __cplusplus
+extern "C" {
+#endif
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process1_open)(const char* uri, remote_handle64* h) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle64_open)(uri, h);
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process1_close)(remote_handle64 h) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle64_close)(h);
+}
+static __inline int _stub_method(remote_handle64 _handle, uint32_t _mid) {
+   remote_arg* _pra = 0;
+   int _nErr = 0;
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle64_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process1_exit)(remote_handle64 _handle) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 2;
+   return _stub_method(_handle, _mid);
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process1_thread_exit)(remote_handle64 _handle) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 3;
+   return _stub_method(_handle, _mid);
+}
+static __inline int _stub_unpack(remote_arg* _praROutPost, remote_arg* _ppraROutPost[1], void* _primROut, char* _in0[1], uint32_t _in0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praROutPostStart = _praROutPost;
+   remote_arg** _ppraROutPostStart = _ppraROutPost;
+   _ppraROutPost = &_praROutPost;
+   _ppraROutPostStart[0] += (_praROutPost - _praROutPostStart) +0;
+   return _nErr;
+}
+static __inline int _stub_pack(_allocator* _al, remote_arg* _praIn, remote_arg* _ppraIn[1], remote_arg* _praROut, remote_arg* _ppraROut[1], void* _primIn, void* _primROut, char* _in0[1], uint32_t _in0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praInStart = _praIn;
+   remote_arg** _ppraInStart = _ppraIn;
+   remote_arg* _praROutStart = _praROut;
+   remote_arg** _ppraROutStart = _ppraROut;
+   _ppraIn = &_praIn;
+   _ppraROut = &_praROut;
+   _in0Len[0] = (1 + strlen(_in0[0]));
+   _COPY(_primIn, 0, _in0Len, 0, 4);
+   _praIn[0].buf.pv = _in0[0];
+   _praIn[0].buf.nLen = (1 * _in0Len[0]);
+   _ppraInStart[0] += (_praIn - _praInStart) + 1;
+   _ppraROutStart[0] += (_praROut - _praROutStart) +0;
+   return _nErr;
+}
+static __inline void _count(int _numIn[1], int _numROut[1], char* _in0[1], uint32_t _in0Len[1]) {
+   _numIn[0] += 1;
+   _numROut[0] += 0;
+}
+static __inline int _stub_method_1(remote_handle64 _handle, uint32_t _mid, uint16_t _in0[1], void* _in1[1], uint32_t _in1Len[1]) {
+   remote_arg* _pra;
+   int _numIn[1];
+   int _numROut[1];
+   char* _seq_nat1;
+   int _ii;
+   _allocator _al[1] = {{0}};
+   uint32_t _primIn[2];
+   remote_arg* _praIn;
+   remote_arg** _ppraIn = &_praIn;
+   remote_arg* _praROut;
+   remote_arg** _ppraROut = &_praROut;
+   char* _seq_primIn1;
+   int _nErr = 0;
+   remote_arg* _praROutPost;
+   remote_arg** _ppraROutPost = &_praROutPost;
+   _numIn[0] = 1;
+   _numROut[0] = 0;
+   for(_ii = 0, _seq_nat1 = (char*)_in1[0];_ii < (int)_in1Len[0];++_ii, _seq_nat1 = (_seq_nat1 + SLIM_IFPTR32(8, 16)))
+   {
+      _count(_numIn, _numROut, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat1)[0]), (char**)&(((uint64_t*)_seq_nat1)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat1)[1]), (uint32_t*)&(((uint32_t*)_seq_nat1)[2])));
+   }
+   _allocator_init(_al, 0, 0);
+   _ALLOCATE(_nErr, _al, ((((_numIn[0] + _numROut[0]) + 1) + 0) * sizeof(_pra[0])), 4, _pra);
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _COPY(_primIn, 0, _in0, 0, 2);
+   _COPY(_primIn, 4, _in1Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 0);
+   _ALLOCATE(_nErr, _al, (_in1Len[0] * 4), 4, _praIn[0].buf.pv);
+   _praIn[0].buf.nLen = (4 * _in1Len[0]);
+   for(_ii = 0, _seq_primIn1 = (char*)_praIn[0].buf.pv, _seq_nat1 = (char*)_in1[0];_ii < (int)_in1Len[0];++_ii, _seq_primIn1 = (_seq_primIn1 + 4), _seq_nat1 = (_seq_nat1 + SLIM_IFPTR32(8, 16)))
+   {
+      _TRY(_nErr, _stub_pack(_al, (_praIn + 1), _ppraIn, (_praROut + 0), _ppraROut, _seq_primIn1, 0, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat1)[0]), (char**)&(((uint64_t*)_seq_nat1)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat1)[1]), (uint32_t*)&(((uint32_t*)_seq_nat1)[2]))));
+   }
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle64_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, (_numIn[0] + 1), (_numROut[0] + 0), 0, 0), _pra));
+   _praROutPost = _praROut;
+   for(_ii = 0, _seq_nat1 = (char*)_in1[0];_ii < (int)_in1Len[0];++_ii, _seq_nat1 = (_seq_nat1 + SLIM_IFPTR32(8, 16)))
+   {
+      _TRY(_nErr, _stub_unpack((_praROutPost + 0), _ppraROutPost, 0, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat1)[0]), (char**)&(((uint64_t*)_seq_nat1)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat1)[1]), (uint32_t*)&(((uint32_t*)_seq_nat1)[2]))));
+   }
+   _CATCH(_nErr) {}
+   _allocator_deinit(_al);
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process1_set_logging_params)(remote_handle64 _handle, unsigned short mask, const _cstring1_t* filesToLog, int filesToLogLen) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 4;
+   return _stub_method_1(_handle, _mid, (uint16_t*)&mask, (void**)&filesToLog, (uint32_t*)&filesToLogLen);
+}
+static __inline int _stub_method_2(remote_handle64 _handle, uint32_t _mid, uint32_t _rout0[1]) {
+   int _numIn[1];
+   remote_arg _pra[1];
+   uint32_t _primROut[1];
+   int _nErr = 0;
+   _numIn[0] = 0;
+   _pra[(_numIn[0] + 0)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 0)].buf.nLen = sizeof(_primROut);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle64_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 1, 0, 0), _pra));
+   _COPY(_rout0, 0, _primROut, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process1_getASID)(remote_handle64 _handle, unsigned int* asid) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 5;
+   return _stub_method_2(_handle, _mid, (uint32_t*)asid);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_CURRENT_PROCESS1_STUB_H
diff --git a/src/adsp_current_process_stub.c b/src/adsp_current_process_stub.c
new file mode 100644
index 0000000..32c3047
--- /dev/null
+++ b/src/adsp_current_process_stub.c
@@ -0,0 +1,669 @@
+#ifndef _ADSP_CURRENT_PROCESS_STUB_H
+#define _ADSP_CURRENT_PROCESS_STUB_H
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "adsp_current_process.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#include <string.h>
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type          *seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSP_CURRENT_PROCESS_SLIM_H
+#define _ADSP_CURRENT_PROCESS_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[1];
+static const SequenceType sequenceTypes[1] = {{&(types[0]),0x0,0x4,0x4,0x0}};
+static const Type types[1] = {{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8)}};
+static const Parameter parameters[3] = {{0x2,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x2,0,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(sequenceTypes[0]),0}}, 25,SLIM_IFPTR32(0x4,0x8),0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,3,0}};
+static const Parameter* const parameterArrays[3] = {(&(parameters[0])),(&(parameters[1])),(&(parameters[2]))};
+static const Method methods[3] = {{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x0,0x0),0x0,0x0,0,0,0,0x0,0x0},{REMOTE_SCALARS_MAKEX(0,0,255,255,15,15),0x8,0x0,3,2,(&(parameterArrays[0])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x1,0x0,0x0),0x0,0x4,1,1,(&(parameterArrays[2])),0x1,0x4}};
+static const Method* const methodArrays[4] = {&(methods[0]),&(methods[0]),&(methods[1]),&(methods[2])};
+static const char strings[60] = "set_logging_params\0thread_exit\0filesToLog\0getASID\0asid\0mask\0";
+static const uint16_t methodStrings[7] = {0,55,31,42,50,19,26};
+static const uint16_t methodStringsArrays[4] = {6,5,0,3};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adsp_current_process_slim) = {4,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSP_CURRENT_PROCESS_SLIM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _const_adsp_current_process_handle
+#define _const_adsp_current_process_handle ((remote_handle)-1)
+#endif //_const_adsp_current_process_handle
+
+static void _adsp_current_process_pls_dtor(void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   if(_const_adsp_current_process_handle != *ph) {
+      (void)__QAIC_REMOTE(remote_handle_close)(*ph);
+      *ph = _const_adsp_current_process_handle;
+   }
+}
+
+static int _adsp_current_process_pls_ctor(void* ctx, void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   *ph = _const_adsp_current_process_handle;
+   if(*ph == (remote_handle)-1) {
+      return __QAIC_REMOTE(remote_handle_open)((const char*)ctx, ph);
+   }
+   return 0;
+}
+
+#if (defined __qdsp6__) || (defined __hexagon__)
+#pragma weak  adsp_pls_add_lookup
+extern int adsp_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+#pragma weak  HAP_pls_add_lookup
+extern int HAP_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+
+__QAIC_STUB_EXPORT remote_handle _adsp_current_process_handle(void) {
+   remote_handle* ph;
+   if(adsp_pls_add_lookup) {
+      if(0 == adsp_pls_add_lookup((uint32_t)_adsp_current_process_handle, 0, sizeof(*ph),  _adsp_current_process_pls_ctor, "adsp_current_process",  _adsp_current_process_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   } else if(HAP_pls_add_lookup) {
+      if(0 == HAP_pls_add_lookup((uint32_t)_adsp_current_process_handle, 0, sizeof(*ph),  _adsp_current_process_pls_ctor, "adsp_current_process",  _adsp_current_process_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   }
+   return(remote_handle)-1;
+}
+
+#else //__qdsp6__ || __hexagon__
+
+uint32_t _adsp_current_process_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare);
+
+#ifdef _WIN32
+#include "Windows.h"
+uint32_t _adsp_current_process_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return (uint32_t)InterlockedCompareExchange((volatile LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
+}
+#elif __GNUC__
+uint32_t _adsp_current_process_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+#endif //_WIN32
+
+
+__QAIC_STUB_EXPORT remote_handle _adsp_current_process_handle(void) {
+   static remote_handle handle = _const_adsp_current_process_handle;
+   if((remote_handle)-1 != handle) {
+      return handle;
+   } else {
+      remote_handle tmp;
+      int nErr = _adsp_current_process_pls_ctor("adsp_current_process", (void*)&tmp);
+      if(nErr) {
+         return (remote_handle)-1;
+      }
+      if(((remote_handle)-1 != handle) || ((remote_handle)-1 != (remote_handle)_adsp_current_process_atomic_CompareAndExchange((uint32_t*)&handle, (uint32_t)tmp, (uint32_t)-1))) {
+         _adsp_current_process_pls_dtor(&tmp);
+      }
+      return handle;
+   }
+}
+
+#endif //__qdsp6__
+
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle_invoke)(_adsp_current_process_handle(), _sc, _pra);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _stub_method(remote_handle _handle, uint32_t _mid) {
+   remote_arg* _pra = 0;
+   int _nErr = 0;
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process_exit)(void) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 0;
+   return _stub_method(_adsp_current_process_handle(), _mid);
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process_thread_exit)(void) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 1;
+   return _stub_method(_adsp_current_process_handle(), _mid);
+}
+static __inline int _stub_unpack(remote_arg* _praROutPost, remote_arg* _ppraROutPost[1], void* _primROut, char* _in0[1], uint32_t _in0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praROutPostStart = _praROutPost;
+   remote_arg** _ppraROutPostStart = _ppraROutPost;
+   _ppraROutPost = &_praROutPost;
+   _ppraROutPostStart[0] += (_praROutPost - _praROutPostStart) +0;
+   return _nErr;
+}
+static __inline int _stub_pack(_allocator* _al, remote_arg* _praIn, remote_arg* _ppraIn[1], remote_arg* _praROut, remote_arg* _ppraROut[1], void* _primIn, void* _primROut, char* _in0[1], uint32_t _in0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praInStart = _praIn;
+   remote_arg** _ppraInStart = _ppraIn;
+   remote_arg* _praROutStart = _praROut;
+   remote_arg** _ppraROutStart = _ppraROut;
+   _ppraIn = &_praIn;
+   _ppraROut = &_praROut;
+   _in0Len[0] = (1 + strlen(_in0[0]));
+   _COPY(_primIn, 0, _in0Len, 0, 4);
+   _praIn[0].buf.pv = _in0[0];
+   _praIn[0].buf.nLen = (1 * _in0Len[0]);
+   _ppraInStart[0] += (_praIn - _praInStart) + 1;
+   _ppraROutStart[0] += (_praROut - _praROutStart) +0;
+   return _nErr;
+}
+static __inline void _count(int _numIn[1], int _numROut[1], char* _in0[1], uint32_t _in0Len[1]) {
+   _numIn[0] += 1;
+   _numROut[0] += 0;
+}
+static __inline int _stub_method_1(remote_handle _handle, uint32_t _mid, uint16_t _in0[1], void* _in1[1], uint32_t _in1Len[1]) {
+   remote_arg* _pra;
+   int _numIn[1];
+   int _numROut[1];
+   char* _seq_nat1;
+   int _ii;
+   _allocator _al[1] = {{0}};
+   uint32_t _primIn[2];
+   remote_arg* _praIn;
+   remote_arg** _ppraIn = &_praIn;
+   remote_arg* _praROut;
+   remote_arg** _ppraROut = &_praROut;
+   char* _seq_primIn1;
+   int _nErr = 0;
+   remote_arg* _praROutPost;
+   remote_arg** _ppraROutPost = &_praROutPost;
+   _numIn[0] = 1;
+   _numROut[0] = 0;
+   for(_ii = 0, _seq_nat1 = (char*)_in1[0];_ii < (int)_in1Len[0];++_ii, _seq_nat1 = (_seq_nat1 + SLIM_IFPTR32(8, 16)))
+   {
+      _count(_numIn, _numROut, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat1)[0]), (char**)&(((uint64_t*)_seq_nat1)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat1)[1]), (uint32_t*)&(((uint32_t*)_seq_nat1)[2])));
+   }
+   _allocator_init(_al, 0, 0);
+   _ALLOCATE(_nErr, _al, ((((_numIn[0] + _numROut[0]) + 1) + 0) * sizeof(_pra[0])), 4, _pra);
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _COPY(_primIn, 0, _in0, 0, 2);
+   _COPY(_primIn, 4, _in1Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 0);
+   _ALLOCATE(_nErr, _al, (_in1Len[0] * 4), 4, _praIn[0].buf.pv);
+   _praIn[0].buf.nLen = (4 * _in1Len[0]);
+   for(_ii = 0, _seq_primIn1 = (char*)_praIn[0].buf.pv, _seq_nat1 = (char*)_in1[0];_ii < (int)_in1Len[0];++_ii, _seq_primIn1 = (_seq_primIn1 + 4), _seq_nat1 = (_seq_nat1 + SLIM_IFPTR32(8, 16)))
+   {
+      _TRY(_nErr, _stub_pack(_al, (_praIn + 1), _ppraIn, (_praROut + 0), _ppraROut, _seq_primIn1, 0, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat1)[0]), (char**)&(((uint64_t*)_seq_nat1)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat1)[1]), (uint32_t*)&(((uint32_t*)_seq_nat1)[2]))));
+   }
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, (_numIn[0] + 1), (_numROut[0] + 0), 0, 0), _pra));
+   _praROutPost = _praROut;
+   for(_ii = 0, _seq_nat1 = (char*)_in1[0];_ii < (int)_in1Len[0];++_ii, _seq_nat1 = (_seq_nat1 + SLIM_IFPTR32(8, 16)))
+   {
+      _TRY(_nErr, _stub_unpack((_praROutPost + 0), _ppraROutPost, 0, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat1)[0]), (char**)&(((uint64_t*)_seq_nat1)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat1)[1]), (uint32_t*)&(((uint32_t*)_seq_nat1)[2]))));
+   }
+   _CATCH(_nErr) {}
+   _allocator_deinit(_al);
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process_set_logging_params)(unsigned short mask, const _cstring1_t* filesToLog, int filesToLogLen) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 2;
+   return _stub_method_1(_adsp_current_process_handle(), _mid, (uint16_t*)&mask, (void**)&filesToLog, (uint32_t*)&filesToLogLen);
+}
+static __inline int _stub_method_2(remote_handle _handle, uint32_t _mid, uint32_t _rout0[1]) {
+   int _numIn[1];
+   remote_arg _pra[1];
+   uint32_t _primROut[1];
+   int _nErr = 0;
+   _numIn[0] = 0;
+   _pra[(_numIn[0] + 0)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 0)].buf.nLen = sizeof(_primROut);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 1, 0, 0), _pra));
+   _COPY(_rout0, 0, _primROut, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_current_process_getASID)(unsigned int* asid) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 3;
+   return _stub_method_2(_adsp_current_process_handle(), _mid, (uint32_t*)asid);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_CURRENT_PROCESS_STUB_H
diff --git a/src/adsp_def_symbols.lst b/src/adsp_def_symbols.lst
new file mode 100644
index 0000000..f998107
--- /dev/null
+++ b/src/adsp_def_symbols.lst
@@ -0,0 +1,33 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+ADSPRPC {
+   global:
+      adsp_default_listener_start;
+   local: *;
+};
diff --git a/src/adsp_default_listener.c b/src/adsp_default_listener.c
new file mode 100644
index 0000000..5f1cb80
--- /dev/null
+++ b/src/adsp_default_listener.c
@@ -0,0 +1,106 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 VERIFY_PRINT_ERROR
+//#define VERIFY_PRINT_ERROR
+//#endif
+
+#define FARF_ERROR 1
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <poll.h>
+#include <unistd.h>
+#include <sys/eventfd.h>
+#include <string.h>
+#include "adsp_default_listener.h"
+#include "AEEStdErr.h"
+#include "verify.h"
+#include "remote.h"
+#include "HAP_farf.h"
+#include "adspmsgd_adsp.h"
+
+int adsp_default_listener_start(int argc, char* argv[]) {
+   struct pollfd pfd;
+   eventfd_t event = 0;
+   remote_handle fd;
+   int nErr = AEE_SUCCESS;
+   char *name = NULL;
+   int namelen = 0;
+   (void)argc;
+   (void)argv;
+   if (argc > 1) {
+      namelen = strlen(ITRANSPORT_PREFIX "createstaticpd:") + strlen(argv[1]);
+      name = (char *)malloc((namelen + 1) * sizeof(char));
+      VERIFYC(NULL != name, AEE_ENOMEMORY);
+      std_strlcpy(name,  ITRANSPORT_PREFIX "createstaticpd:", strlen(ITRANSPORT_PREFIX "createstaticpd:")+1);
+      std_strlcat(name, argv[1], namelen+1);
+   } else {
+      namelen = strlen(ITRANSPORT_PREFIX "attachguestos");
+      name = (char *)malloc((namelen + 1) * sizeof(char));
+      VERIFYC(NULL != name, AEE_ENOMEMORY);
+      std_strlcpy(name,  ITRANSPORT_PREFIX "attachguestos", strlen(ITRANSPORT_PREFIX "attachguestos")+1);
+   }
+   VERIFY_EPRINTF("adsp_default_listener_start started\n");
+   VERIFYC(!setenv("ADSP_LISTENER_MEM_CACHE_SIZE", "1048576", 0), AEE_ESETENV);
+   VERIFY(0 == (nErr = remote_handle_open(name, &fd)));
+   VERIFY(0 == (nErr = adsp_default_listener_register()));
+   VERIFY(0 == (nErr = remote_handle_open(ITRANSPORT_PREFIX "geteventfd",
+                                  (remote_handle*)&pfd.fd)));
+   free(name);
+   name = NULL;
+   pfd.events = POLLIN;
+   pfd.revents = 0;
+#ifdef PD_EXCEPTION_LOGGING
+
+if(argc == 1){
+	adspmsgd_adsp_init2();
+}
+
+#endif
+   while (1) {
+     VERIFYC(0 < poll(&pfd, 1, -1), AEE_EPOLL);
+     VERIFYC(0 == eventfd_read(pfd.fd, &event), AEE_EEVENTREAD);
+     if (event) {
+       break;
+     }
+   }
+bail:
+#ifdef PD_EXCEPTION_LOGGING
+if(argc == 1)
+	adspmsgd_adsp_deinit();
+#endif
+   if(nErr != AEE_SUCCESS) {
+      if(name != NULL){
+         free(name);
+         name = NULL;
+      }
+      //FARF(ERROR, "Error %x, adsp_default_listener_start exiting\n", nErr);
+   }
+   return nErr;
+}
diff --git a/src/adsp_default_listener_stub.c b/src/adsp_default_listener_stub.c
new file mode 100644
index 0000000..c2c0057
--- /dev/null
+++ b/src/adsp_default_listener_stub.c
@@ -0,0 +1,517 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_DEFAULT_LISTENER_STUB_H
+#define _ADSP_DEFAULT_LISTENER_STUB_H
+#include "adsp_default_listener.h"
+#include "remote.h"
+#ifndef ALLOCATOR_H
+#define ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} allocator;
+
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+
+static __inline int allocator_alloc(allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+
+static __inline void allocator_deinit(allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+static __inline void allocator_init(allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSP_DEFAULT_LISTENER_SLIM_H
+#define _ADSP_DEFAULT_LISTENER_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Method methods[1] = {{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x0,0x0),0x0,0x0,0,0,0,0x0,0x0}};
+static const Method* const methodArrays[1] = {&(methods[0])};
+static const char strings[9] = "register\0";
+static const uint16_t methodStrings[1] = {0};
+static const uint16_t methodStringsArrays[1] = {0};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adsp_default_listener_slim) = {1,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSP_DEFAULT_LISTENER_SLIM_H
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE_LINE__  ": error: %d\n", (int)(ee)));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _const_adsp_default_listener_handle
+#define _const_adsp_default_listener_handle ((remote_handle)-1)
+#endif //_const_adsp_default_listener_handle
+
+static void _adsp_default_listener_pls_dtor(void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   if(_const_adsp_default_listener_handle != *ph) {
+      (void)__QAIC_REMOTE(remote_handle_close)(*ph);
+      *ph = _const_adsp_default_listener_handle;
+   }
+}
+
+static int _adsp_default_listener_pls_ctor(void* ctx, void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   *ph = _const_adsp_default_listener_handle;
+   if(*ph == (remote_handle)-1) {
+      return __QAIC_REMOTE(remote_handle_open)((const char*)ctx, ph);
+   }
+   return 0;
+}
+
+#if (defined __qdsp6__) || (defined __hexagon__)
+#pragma weak  adsp_pls_add_lookup
+extern int adsp_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+#pragma weak  HAP_pls_add_lookup
+extern int HAP_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+
+__QAIC_STUB_EXPORT remote_handle _adsp_default_listener_handle(void) {
+   remote_handle* ph;
+   if(adsp_pls_add_lookup) {
+      if(0 == adsp_pls_add_lookup((uint32_t)_adsp_default_listener_handle, 0, sizeof(*ph),  _adsp_default_listener_pls_ctor, "adsp_default_listener",  _adsp_default_listener_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   } else if(HAP_pls_add_lookup) {
+      if(0 == HAP_pls_add_lookup((uint32_t)_adsp_default_listener_handle, 0, sizeof(*ph),  _adsp_default_listener_pls_ctor, "adsp_default_listener",  _adsp_default_listener_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   }
+   return(remote_handle)-1;
+}
+
+#else //__qdsp6__ || __hexagon__
+
+uint32_t _adsp_default_listener_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare);
+
+#ifdef _WIN32
+#include "Windows.h"
+uint32_t _adsp_default_listener_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return (uint32_t)InterlockedCompareExchange((volatile LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
+}
+#elif __GNUC__
+uint32_t _adsp_default_listener_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+#endif //_WIN32
+
+
+__QAIC_STUB_EXPORT remote_handle _adsp_default_listener_handle(void) {
+   static remote_handle handle = _const_adsp_default_listener_handle;
+   if((remote_handle)-1 != handle) {
+      return handle;
+   } else {
+      remote_handle tmp;
+      int nErr = _adsp_default_listener_pls_ctor("adsp_default_listener", (void*)&tmp);
+      if(nErr) {
+         return (remote_handle)-1;
+      }
+      if(((remote_handle)-1 != handle) || ((remote_handle)-1 != (remote_handle)_adsp_default_listener_atomic_CompareAndExchange((uint32_t*)&handle, (uint32_t)tmp, (uint32_t)-1))) {
+         _adsp_default_listener_pls_dtor(&tmp);
+      }
+      return handle;
+   }
+}
+
+#endif //__qdsp6__
+
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_default_listener_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle_invoke)(_adsp_default_listener_handle(), _sc, _pra);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _stub_method(remote_handle _handle, uint32_t _mid) {
+   remote_arg* _pra = 0;
+   int _nErr = 0;
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_default_listener_register)(void) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 0;
+   return _stub_method(_adsp_default_listener_handle(), _mid);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_DEFAULT_LISTENER_STUB_H
diff --git a/src/adsp_listener_stub.c b/src/adsp_listener_stub.c
new file mode 100644
index 0000000..f94e2c4
--- /dev/null
+++ b/src/adsp_listener_stub.c
@@ -0,0 +1,797 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_LISTENER_STUB_H
+#define _ADSP_LISTENER_STUB_H
+#include "adsp_listener.h"
+#include "remote.h"
+#ifndef ALLOCATOR_H
+#define ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} allocator;
+
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+
+static __inline int allocator_alloc(allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+
+static __inline void allocator_deinit(allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+static __inline void allocator_init(allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSP_LISTENER_SLIM_H
+#define _ADSP_LISTENER_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[3];
+static const SequenceType sequenceTypes[1] = {{&(types[0]),0x0,0x4,0x4,0x0}};
+static const Type types[3] = {{0x8,{{(const uintptr_t)&(types[1]),(const uintptr_t)0x0}}, 9,0x4},{0x1,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x1},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4}};
+static const Parameter parameters[9] = {{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,0,0},{0x8,{{(const uintptr_t)&(sequenceTypes[0]),0}}, 25,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,3,0},{0x8,{{(const uintptr_t)&(sequenceTypes[0]),0}}, 25,0x4,3,0},{0x8,{{(const uintptr_t)&(types[2]),(const uintptr_t)0x0}}, 9,0x4,3,0},{0x8,{{(const uintptr_t)&(types[1]),(const uintptr_t)0x0}}, 9,0x4,0,0},{0x8,{{(const uintptr_t)&(types[1]),(const uintptr_t)0x0}}, 9,0x4,3,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,3,0}};
+static const Parameter* const parameterArrays[23] = {(&(parameters[0])),(&(parameters[1])),(&(parameters[2])),(&(parameters[3])),(&(parameters[3])),(&(parameters[3])),(&(parameters[4])),(&(parameters[5])),(&(parameters[5])),(&(parameters[0])),(&(parameters[1])),(&(parameters[6])),(&(parameters[3])),(&(parameters[3])),(&(parameters[3])),(&(parameters[7])),(&(parameters[8])),(&(parameters[0])),(&(parameters[1])),(&(parameters[7])),(&(parameters[8])),(&(parameters[0])),(&(parameters[4]))};
+static const Method methods[5] = {{REMOTE_SCALARS_MAKEX(0,0,255,255,15,15),0x18,0xc,16,9,(&(parameterArrays[0])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,255,255,15,15),0x8,0x0,4,2,(&(parameterArrays[21])),0x4,0x1},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x0,0x0),0x0,0x0,0,0,0,0x0,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x2,0x0,0x0),0x10,0x10,11,8,(&(parameterArrays[9])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x2,0x0,0x0),0xc,0x4,6,4,(&(parameterArrays[17])),0x4,0x4}};
+static const Method* const methodArrays[6] = {&(methods[0]),&(methods[1]),&(methods[2]),&(methods[2]),&(methods[3]),&(methods[4])};
+static const char strings[165] = "invoke_get_in_bufs\0routBufLenReq\0get_in_bufs2\0inBufLenReq\0next_invoke\0bufsLenReq\0prevResult\0inBuffers\0prevbufs\0outBufs\0prevCtx\0offset\0handle\0next2\0init2\0init\0ctx\0sc\0";
+static const uint16_t methodStrings[29] = {58,119,81,111,158,134,162,92,46,19,141,119,81,102,158,134,162,14,70,33,158,127,14,70,0,158,92,147,153};
+static const uint16_t methodStringsArrays[6] = {0,24,28,27,10,19};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adsp_listener_slim) = {6,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSP_LISTENER_SLIM_H
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE_LINE__  ": error: %d\n", (int)(ee)));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _const_adsp_listener_handle
+#define _const_adsp_listener_handle ((remote_handle)-1)
+#endif //_const_adsp_listener_handle
+
+static void _adsp_listener_pls_dtor(void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   if(_const_adsp_listener_handle != *ph) {
+      (void)__QAIC_REMOTE(remote_handle_close)(*ph);
+      *ph = _const_adsp_listener_handle;
+   }
+}
+
+static int _adsp_listener_pls_ctor(void* ctx, void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   *ph = _const_adsp_listener_handle;
+   if(*ph == (remote_handle)-1) {
+      return __QAIC_REMOTE(remote_handle_open)((const char*)ctx, ph);
+   }
+   return 0;
+}
+
+#if (defined __qdsp6__) || (defined __hexagon__)
+#pragma weak  adsp_pls_add_lookup
+extern int adsp_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+#pragma weak  HAP_pls_add_lookup
+extern int HAP_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+
+__QAIC_STUB_EXPORT remote_handle _adsp_listener_handle(void) {
+   remote_handle* ph;
+   if(adsp_pls_add_lookup) {
+      if(0 == adsp_pls_add_lookup((uint32_t)_adsp_listener_handle, 0, sizeof(*ph),  _adsp_listener_pls_ctor, "adsp_listener",  _adsp_listener_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   } else if(HAP_pls_add_lookup) {
+      if(0 == HAP_pls_add_lookup((uint32_t)_adsp_listener_handle, 0, sizeof(*ph),  _adsp_listener_pls_ctor, "adsp_listener",  _adsp_listener_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   }
+   return(remote_handle)-1;
+}
+
+#else //__qdsp6__ || __hexagon__
+
+uint32_t _adsp_listener_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare);
+
+#ifdef _WIN32
+#include "Windows.h"
+uint32_t _adsp_listener_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return (uint32_t)InterlockedCompareExchange((volatile LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
+}
+#elif __GNUC__
+uint32_t _adsp_listener_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+#endif //_WIN32
+
+
+__QAIC_STUB_EXPORT remote_handle _adsp_listener_handle(void) {
+   static remote_handle handle = _const_adsp_listener_handle;
+   if((remote_handle)-1 != handle) {
+      return handle;
+   } else {
+      remote_handle tmp;
+      int nErr = _adsp_listener_pls_ctor("adsp_listener", (void*)&tmp);
+      if(nErr) {
+         return (remote_handle)-1;
+      }
+      if(((remote_handle)-1 != handle) || ((remote_handle)-1 != (remote_handle)_adsp_listener_atomic_CompareAndExchange((uint32_t*)&handle, (uint32_t)tmp, (uint32_t)-1))) {
+         _adsp_listener_pls_dtor(&tmp);
+      }
+      return handle;
+   }
+}
+
+#endif //__qdsp6__
+
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_listener_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle_invoke)(_adsp_listener_handle(), _sc, _pra);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _stub_unpack(remote_arg* _praROutPost, remote_arg* _ppraROutPost[1], void* _primROut, char* _rout0[1], uint32_t _rout0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praROutPostStart = _praROutPost;
+   remote_arg** _ppraROutPostStart = _ppraROutPost;
+   _ppraROutPost = &_praROutPost;
+   _ppraROutPostStart[0] += (_praROutPost - _praROutPostStart) +1;
+   return _nErr;
+}
+static __inline int _stub_unpack_1(remote_arg* _praROutPost, remote_arg* _ppraROutPost[1], void* _primROut, char* _in0[1], uint32_t _in0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praROutPostStart = _praROutPost;
+   remote_arg** _ppraROutPostStart = _ppraROutPost;
+   _ppraROutPost = &_praROutPost;
+   _ppraROutPostStart[0] += (_praROutPost - _praROutPostStart) +0;
+   return _nErr;
+}
+static __inline int _stub_pack(allocator* _al, remote_arg* _praIn, remote_arg* _ppraIn[1], remote_arg* _praROut, remote_arg* _ppraROut[1], void* _primIn, void* _primROut, char* _rout0[1], uint32_t _rout0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praInStart = _praIn;
+   remote_arg** _ppraInStart = _ppraIn;
+   remote_arg* _praROutStart = _praROut;
+   remote_arg** _ppraROutStart = _ppraROut;
+   _ppraIn = &_praIn;
+   _ppraROut = &_praROut;
+   _COPY(_primIn, 0, _rout0Len, 0, 4);
+   _praROut[0].buf.pv = _rout0[0];
+   _praROut[0].buf.nLen = (1 * _rout0Len[0]);
+   _ppraInStart[0] += (_praIn - _praInStart) + 0;
+   _ppraROutStart[0] += (_praROut - _praROutStart) +1;
+   return _nErr;
+}
+static __inline int _stub_pack_1(allocator* _al, remote_arg* _praIn, remote_arg* _ppraIn[1], remote_arg* _praROut, remote_arg* _ppraROut[1], void* _primIn, void* _primROut, char* _in0[1], uint32_t _in0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praInStart = _praIn;
+   remote_arg** _ppraInStart = _ppraIn;
+   remote_arg* _praROutStart = _praROut;
+   remote_arg** _ppraROutStart = _ppraROut;
+   _ppraIn = &_praIn;
+   _ppraROut = &_praROut;
+   _COPY(_primIn, 0, _in0Len, 0, 4);
+   _praIn[0].buf.pv = _in0[0];
+   _praIn[0].buf.nLen = (1 * _in0Len[0]);
+   _ppraInStart[0] += (_praIn - _praInStart) + 1;
+   _ppraROutStart[0] += (_praROut - _praROutStart) +0;
+   return _nErr;
+}
+static __inline void _count(int _numIn[1], int _numROut[1], char* _rout0[1], uint32_t _rout0Len[1]) {
+   _numIn[0] += 0;
+   _numROut[0] += 1;
+}
+static __inline void _count_1(int _numIn[1], int _numROut[1], char* _in0[1], uint32_t _in0Len[1]) {
+   _numIn[0] += 1;
+   _numROut[0] += 0;
+}
+static __inline int _stub_method(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], uint32_t _in1[1], void* _in2[1], uint32_t _in2Len[1], uint32_t _rout3[1], uint32_t _rout4[1], uint32_t _rout5[1], void* _rout6[1], uint32_t _rout6Len[1], char* _rout7[1], uint32_t _rout7Len[1], char* _rout8[1], uint32_t _rout8Len[1]) {
+   remote_arg* _pra;
+   int _numIn[1];
+   int _numROut[1];
+   char* _seq_nat2;
+   int _ii;
+   char* _seq_nat6;
+   allocator _al[1] = {{0}};
+   uint32_t _primIn[6];
+   uint32_t _primROut[3];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   remote_arg* _praROutPost;
+   remote_arg** _ppraROutPost = &_praROutPost;
+   remote_arg** _ppraIn = &_praIn;
+   remote_arg** _ppraROut = &_praROut;
+   char* _seq_primIn2;
+   int _nErr = 0;
+   char* _seq_primIn6;
+   _numIn[0] = 2;
+   _numROut[0] = 2;
+   for(_ii = 0, _seq_nat2 = (char*)_in2[0];_ii < (int)_in2Len[0];++_ii, _seq_nat2 = (_seq_nat2 + 8))
+   {
+      _count_1(_numIn, _numROut, (char**)&(((uint32_t*)_seq_nat2)[0]), (uint32_t*)&(((uint32_t*)_seq_nat2)[1]));
+   }
+   for(_ii = 0, _seq_nat6 = (char*)_rout6[0];_ii < (int)_rout6Len[0];++_ii, _seq_nat6 = (_seq_nat6 + 8))
+   {
+      _count(_numIn, _numROut, (char**)&(((uint32_t*)_seq_nat6)[0]), (uint32_t*)&(((uint32_t*)_seq_nat6)[1]));
+   }
+   allocator_init(_al, 0, 0);
+   _ALLOCATE(_nErr, _al, ((((_numIn[0] + _numROut[0]) + 1) + 1) * sizeof(_pra[0])), 4, _pra);
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _pra[(_numIn[0] + 1)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 1)].buf.nLen = sizeof(_primROut);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _praROutPost = _praROut;
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _in1, 0, 4);
+   _COPY(_primIn, 8, _in2Len, 0, 4);
+   _ALLOCATE(_nErr, _al, (_in2Len[0] * 4), 4, _praIn[0].buf.pv);
+   _praIn[0].buf.nLen = (4 * _in2Len[0]);
+   for(_ii = 0, _seq_primIn2 = (char*)_praIn[0].buf.pv, _seq_nat2 = (char*)_in2[0];_ii < (int)_in2Len[0];++_ii, _seq_primIn2 = (_seq_primIn2 + 4), _seq_nat2 = (_seq_nat2 + 8))
+   {
+      _TRY(_nErr, _stub_pack_1(_al, (_praIn + 1), _ppraIn, (_praROut + 0), _ppraROut, _seq_primIn2, 0, (char**)&(((uint32_t*)_seq_nat2)[0]), (uint32_t*)&(((uint32_t*)_seq_nat2)[1])));
+   }
+   _COPY(_primIn, 12, _rout6Len, 0, 4);
+   _ALLOCATE(_nErr, _al, (_rout6Len[0] * 4), 4, _praIn[1].buf.pv);
+   _praIn[1].buf.nLen = (4 * _rout6Len[0]);
+   for(_ii = 0, _seq_primIn6 = (char*)_praIn[1].buf.pv, _seq_nat6 = (char*)_rout6[0];_ii < (int)_rout6Len[0];++_ii, _seq_primIn6 = (_seq_primIn6 + 4), _seq_nat6 = (_seq_nat6 + 8))
+   {
+      _TRY(_nErr, _stub_pack(_al, (_praIn + 2), _ppraIn, (_praROut + 0), _ppraROut, _seq_primIn6, 0, (char**)&(((uint32_t*)_seq_nat6)[0]), (uint32_t*)&(((uint32_t*)_seq_nat6)[1])));
+   }
+   _COPY(_primIn, 16, _rout7Len, 0, 4);
+   _praROut[0].buf.pv = _rout7[0];
+   _praROut[0].buf.nLen = (4 * _rout7Len[0]);
+   _COPY(_primIn, 20, _rout8Len, 0, 4);
+   _praROut[1].buf.pv = _rout8[0];
+   _praROut[1].buf.nLen = (4 * _rout8Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, (_numIn[0] + 1), (_numROut[0] + 1), 0, 0), _pra));
+   for(_ii = 0, _seq_nat2 = (char*)_in2[0];_ii < (int)_in2Len[0];++_ii, _seq_nat2 = (_seq_nat2 + 8))
+   {
+      _TRY(_nErr, _stub_unpack_1((_praROutPost + 0), _ppraROutPost, 0, (char**)&(((uint32_t*)_seq_nat2)[0]), (uint32_t*)&(((uint32_t*)_seq_nat2)[1])));
+   }
+   _COPY(_rout3, 0, _primROut, 0, 4);
+   _COPY(_rout4, 0, _primROut, 4, 4);
+   _COPY(_rout5, 0, _primROut, 8, 4);
+   for(_ii = 0, _seq_nat6 = (char*)_rout6[0];_ii < (int)_rout6Len[0];++_ii, _seq_nat6 = (_seq_nat6 + 8))
+   {
+      _TRY(_nErr, _stub_unpack((_praROutPost + 0), _ppraROutPost, 0, (char**)&(((uint32_t*)_seq_nat6)[0]), (uint32_t*)&(((uint32_t*)_seq_nat6)[1])));
+   }
+   _CATCH(_nErr) {}
+   allocator_deinit(_al);
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_listener_next_invoke)(adsp_listener_invoke_ctx prevCtx, int prevResult, const adsp_listener_buffer* outBufs, int outBufsLen, adsp_listener_invoke_ctx* ctx, adsp_listener_remote_handle* handle, uint32* sc, adsp_listener_buffer* inBuffers, int inBuffersLen, int* inBufLenReq, int inBufLenReqLen, int* routBufLenReq, int routBufLenReqLen) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 0;
+   return _stub_method(_adsp_listener_handle(), _mid, (uint32_t*)&prevCtx, (uint32_t*)&prevResult, (void**)&outBufs, (uint32_t*)&outBufsLen, (uint32_t*)ctx, (uint32_t*)handle, (uint32_t*)sc, (void**)&inBuffers, (uint32_t*)&inBuffersLen, (char**)&inBufLenReq, (uint32_t*)&inBufLenReqLen, (char**)&routBufLenReq, (uint32_t*)&routBufLenReqLen);
+}
+static __inline int _stub_unpack_2(remote_arg* _praROutPost, remote_arg* _ppraROutPost[1], void* _primROut, char* _rout0[1], uint32_t _rout0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praROutPostStart = _praROutPost;
+   remote_arg** _ppraROutPostStart = _ppraROutPost;
+   _ppraROutPost = &_praROutPost;
+   _ppraROutPostStart[0] += (_praROutPost - _praROutPostStart) +1;
+   return _nErr;
+}
+static __inline int _stub_pack_2(allocator* _al, remote_arg* _praIn, remote_arg* _ppraIn[1], remote_arg* _praROut, remote_arg* _ppraROut[1], void* _primIn, void* _primROut, char* _rout0[1], uint32_t _rout0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praInStart = _praIn;
+   remote_arg** _ppraInStart = _ppraIn;
+   remote_arg* _praROutStart = _praROut;
+   remote_arg** _ppraROutStart = _ppraROut;
+   _ppraIn = &_praIn;
+   _ppraROut = &_praROut;
+   _COPY(_primIn, 0, _rout0Len, 0, 4);
+   _praROut[0].buf.pv = _rout0[0];
+   _praROut[0].buf.nLen = (1 * _rout0Len[0]);
+   _ppraInStart[0] += (_praIn - _praInStart) + 0;
+   _ppraROutStart[0] += (_praROut - _praROutStart) +1;
+   return _nErr;
+}
+static __inline int _stub_method_1(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], void* _rout1[1], uint32_t _rout1Len[1]) {
+   remote_arg* _pra;
+   int _numIn[1];
+   int _numROut[1];
+   char* _seq_nat1;
+   int _ii;
+   allocator _al[1] = {{0}};
+   uint32_t _primIn[2];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   remote_arg* _praROutPost;
+   remote_arg** _ppraROutPost = &_praROutPost;
+   remote_arg** _ppraIn = &_praIn;
+   remote_arg** _ppraROut = &_praROut;
+   char* _seq_primIn1;
+   int _nErr = 0;
+   _numIn[0] = 1;
+   _numROut[0] = 0;
+   for(_ii = 0, _seq_nat1 = (char*)_rout1[0];_ii < (int)_rout1Len[0];++_ii, _seq_nat1 = (_seq_nat1 + 8))
+   {
+      _count(_numIn, _numROut, (char**)&(((uint32_t*)_seq_nat1)[0]), (uint32_t*)&(((uint32_t*)_seq_nat1)[1]));
+   }
+   allocator_init(_al, 0, 0);
+   _ALLOCATE(_nErr, _al, ((((_numIn[0] + _numROut[0]) + 1) + 0) * sizeof(_pra[0])), 4, _pra);
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 0);
+   _praROutPost = _praROut;
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _rout1Len, 0, 4);
+   _ALLOCATE(_nErr, _al, (_rout1Len[0] * 4), 4, _praIn[0].buf.pv);
+   _praIn[0].buf.nLen = (4 * _rout1Len[0]);
+   for(_ii = 0, _seq_primIn1 = (char*)_praIn[0].buf.pv, _seq_nat1 = (char*)_rout1[0];_ii < (int)_rout1Len[0];++_ii, _seq_primIn1 = (_seq_primIn1 + 4), _seq_nat1 = (_seq_nat1 + 8))
+   {
+      _TRY(_nErr, _stub_pack_2(_al, (_praIn + 1), _ppraIn, (_praROut + 0), _ppraROut, _seq_primIn1, 0, (char**)&(((uint32_t*)_seq_nat1)[0]), (uint32_t*)&(((uint32_t*)_seq_nat1)[1])));
+   }
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, (_numIn[0] + 1), (_numROut[0] + 0), 0, 0), _pra));
+   for(_ii = 0, _seq_nat1 = (char*)_rout1[0];_ii < (int)_rout1Len[0];++_ii, _seq_nat1 = (_seq_nat1 + 8))
+   {
+      _TRY(_nErr, _stub_unpack_2((_praROutPost + 0), _ppraROutPost, 0, (char**)&(((uint32_t*)_seq_nat1)[0]), (uint32_t*)&(((uint32_t*)_seq_nat1)[1])));
+   }
+   _CATCH(_nErr) {}
+   allocator_deinit(_al);
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_listener_invoke_get_in_bufs)(adsp_listener_invoke_ctx ctx, adsp_listener_buffer* inBuffers, int inBuffersLen) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 1;
+   return _stub_method_1(_adsp_listener_handle(), _mid, (uint32_t*)&ctx, (void**)&inBuffers, (uint32_t*)&inBuffersLen);
+}
+static __inline int _stub_method_2(remote_handle _handle, uint32_t _mid) {
+   remote_arg* _pra = 0;
+   int _nErr = 0;
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_listener_init)(void) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 2;
+   return _stub_method_2(_adsp_listener_handle(), _mid);
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_listener_init2)(void) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 3;
+   return _stub_method_2(_adsp_listener_handle(), _mid);
+}
+static __inline int _stub_method_3(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], uint32_t _in1[1], char* _in2[1], uint32_t _in2Len[1], uint32_t _rout3[1], uint32_t _rout4[1], uint32_t _rout5[1], char* _rout6[1], uint32_t _rout6Len[1], uint32_t _rout7[1]) {
+   int _numIn[1];
+   remote_arg _pra[4];
+   uint32_t _primIn[4];
+   uint32_t _primROut[4];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _numIn[0] = 1;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _pra[(_numIn[0] + 1)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 1)].buf.nLen = sizeof(_primROut);
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _in1, 0, 4);
+   _COPY(_primIn, 8, _in2Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praIn[0].buf.pv = _in2[0];
+   _praIn[0].buf.nLen = (1 * _in2Len[0]);
+   _COPY(_primIn, 12, _rout6Len, 0, 4);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _praROut[0].buf.pv = _rout6[0];
+   _praROut[0].buf.nLen = (1 * _rout6Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 2, 2, 0, 0), _pra));
+   _COPY(_rout3, 0, _primROut, 0, 4);
+   _COPY(_rout4, 0, _primROut, 4, 4);
+   _COPY(_rout5, 0, _primROut, 8, 4);
+   _COPY(_rout7, 0, _primROut, 12, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_listener_next2)(adsp_listener_invoke_ctx prevCtx, int prevResult, const uint8* prevbufs, int prevbufsLen, adsp_listener_invoke_ctx* ctx, adsp_listener_remote_handle* handle, uint32* sc, uint8* bufs, int bufsLen, int* bufsLenReq) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 4;
+   return _stub_method_3(_adsp_listener_handle(), _mid, (uint32_t*)&prevCtx, (uint32_t*)&prevResult, (char**)&prevbufs, (uint32_t*)&prevbufsLen, (uint32_t*)ctx, (uint32_t*)handle, (uint32_t*)sc, (char**)&bufs, (uint32_t*)&bufsLen, (uint32_t*)bufsLenReq);
+}
+static __inline int _stub_method_4(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], uint32_t _in1[1], char* _rout2[1], uint32_t _rout2Len[1], uint32_t _rout3[1]) {
+   int _numIn[1];
+   remote_arg _pra[3];
+   uint32_t _primIn[3];
+   uint32_t _primROut[1];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _numIn[0] = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _pra[(_numIn[0] + 1)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 1)].buf.nLen = sizeof(_primROut);
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _in1, 0, 4);
+   _COPY(_primIn, 8, _rout2Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _praROut[0].buf.pv = _rout2[0];
+   _praROut[0].buf.nLen = (1 * _rout2Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 1, 2, 0, 0), _pra));
+   _COPY(_rout3, 0, _primROut, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_listener_get_in_bufs2)(adsp_listener_invoke_ctx ctx, int offset, uint8* bufs, int bufsLen, int* bufsLenReq) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 5;
+   return _stub_method_4(_adsp_listener_handle(), _mid, (uint32_t*)&ctx, (uint32_t*)&offset, (char**)&bufs, (uint32_t*)&bufsLen, (uint32_t*)bufsLenReq);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_LISTENER_STUB_H
diff --git a/src/adsp_perf_stub.c b/src/adsp_perf_stub.c
new file mode 100644
index 0000000..46ecc78
--- /dev/null
+++ b/src/adsp_perf_stub.c
@@ -0,0 +1,623 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSP_PERF_STUB_H
+#define _ADSP_PERF_STUB_H
+#include "adsp_perf.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSP_PERF_SLIM_H
+#define _ADSP_PERF_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[2];
+static const Type types[2] = {{0x8,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x8},{0x1,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x1}};
+static const Parameter parameters[4] = {{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,0,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(types[0]),(const uintptr_t)0x0}}, 9,SLIM_IFPTR32(0x4,0x8),3,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(types[1]),(const uintptr_t)0x0}}, 9,SLIM_IFPTR32(0x4,0x8),3,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,3,0}};
+static const Parameter* const parameterArrays[5] = {(&(parameters[2])),(&(parameters[3])),(&(parameters[3])),(&(parameters[1])),(&(parameters[0]))};
+static const Method methods[3] = {{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0x4,0x0,1,1,(&(parameterArrays[4])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x4,0x0,3,1,(&(parameterArrays[3])),0x4,0x1},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x2,0x0,0x0),0x4,0x8,5,3,(&(parameterArrays[0])),0x4,0x4}};
+static const Method* const methodArrays[3] = {&(methods[0]),&(methods[1]),&(methods[2])};
+static const char strings[48] = "get_usecs\0get_keys\0numKeys\0maxLen\0enable\0dst\0ix\0";
+static const uint16_t methodStrings[8] = {10,14,27,19,0,41,34,45};
+static const uint16_t methodStringsArrays[3] = {6,4,0};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adsp_perf_slim) = {3,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSP_PERF_SLIM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _const_adsp_perf_handle
+#define _const_adsp_perf_handle ((remote_handle)-1)
+#endif //_const_adsp_perf_handle
+
+static void _adsp_perf_pls_dtor(void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   if(_const_adsp_perf_handle != *ph) {
+      (void)__QAIC_REMOTE(remote_handle_close)(*ph);
+      *ph = _const_adsp_perf_handle;
+   }
+}
+
+static int _adsp_perf_pls_ctor(void* ctx, void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   *ph = _const_adsp_perf_handle;
+   if(*ph == (remote_handle)-1) {
+      return __QAIC_REMOTE(remote_handle_open)((const char*)ctx, ph);
+   }
+   return 0;
+}
+
+#if (defined __qdsp6__) || (defined __hexagon__)
+#pragma weak  adsp_pls_add_lookup
+extern int adsp_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+#pragma weak  HAP_pls_add_lookup
+extern int HAP_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+
+__QAIC_STUB_EXPORT remote_handle _adsp_perf_handle(void) {
+   remote_handle* ph;
+   if(adsp_pls_add_lookup) {
+      if(0 == adsp_pls_add_lookup((uint32_t)_adsp_perf_handle, 0, sizeof(*ph),  _adsp_perf_pls_ctor, "adsp_perf",  _adsp_perf_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   } else if(HAP_pls_add_lookup) {
+      if(0 == HAP_pls_add_lookup((uint32_t)_adsp_perf_handle, 0, sizeof(*ph),  _adsp_perf_pls_ctor, "adsp_perf",  _adsp_perf_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   }
+   return(remote_handle)-1;
+}
+
+#else //__qdsp6__ || __hexagon__
+
+uint32_t _adsp_perf_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare);
+
+#ifdef _WIN32
+#include "Windows.h"
+uint32_t _adsp_perf_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return (uint32_t)InterlockedCompareExchange((volatile LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
+}
+#elif __GNUC__
+uint32_t _adsp_perf_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+#endif //_WIN32
+
+
+__QAIC_STUB_EXPORT remote_handle _adsp_perf_handle(void) {
+   static remote_handle handle = _const_adsp_perf_handle;
+   if((remote_handle)-1 != handle) {
+      return handle;
+   } else {
+      remote_handle tmp;
+      int nErr = _adsp_perf_pls_ctor("adsp_perf", (void*)&tmp);
+      if(nErr) {
+         return (remote_handle)-1;
+      }
+      if(((remote_handle)-1 != handle) || ((remote_handle)-1 != (remote_handle)_adsp_perf_atomic_CompareAndExchange((uint32_t*)&handle, (uint32_t)tmp, (uint32_t)-1))) {
+         _adsp_perf_pls_dtor(&tmp);
+      }
+      return handle;
+   }
+}
+
+#endif //__qdsp6__
+
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_perf_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle_invoke)(_adsp_perf_handle(), _sc, _pra);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _stub_method(remote_handle _handle, uint32_t _mid, uint32_t _in0[1]) {
+   remote_arg _pra[1];
+   uint32_t _primIn[1];
+   int _nErr = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 1, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_perf_enable)(int ix) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 0;
+   return _stub_method(_adsp_perf_handle(), _mid, (uint32_t*)&ix);
+}
+static __inline int _stub_method_1(remote_handle _handle, uint32_t _mid, char* _rout0[1], uint32_t _rout0Len[1]) {
+   int _numIn[1];
+   remote_arg _pra[2];
+   uint32_t _primIn[1];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _numIn[0] = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _COPY(_primIn, 0, _rout0Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 0);
+   _praROut[0].buf.pv = _rout0[0];
+   _praROut[0].buf.nLen = (8 * _rout0Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 1, 1, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_perf_get_usecs)(int64* dst, int dstLen) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 1;
+   return _stub_method_1(_adsp_perf_handle(), _mid, (char**)&dst, (uint32_t*)&dstLen);
+}
+static __inline int _stub_method_2(remote_handle _handle, uint32_t _mid, char* _rout0[1], uint32_t _rout0Len[1], uint32_t _rout1[1], uint32_t _rout2[1]) {
+   int _numIn[1];
+   remote_arg _pra[3];
+   uint32_t _primIn[1];
+   uint32_t _primROut[2];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _numIn[0] = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _pra[(_numIn[0] + 1)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 1)].buf.nLen = sizeof(_primROut);
+   _COPY(_primIn, 0, _rout0Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _praROut[0].buf.pv = _rout0[0];
+   _praROut[0].buf.nLen = (1 * _rout0Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 1, 2, 0, 0), _pra));
+   _COPY(_rout1, 0, _primROut, 0, 4);
+   _COPY(_rout2, 0, _primROut, 4, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adsp_perf_get_keys)(char* keys, int keysLen, int* maxLen, int* numKeys) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 2;
+   return _stub_method_2(_adsp_perf_handle(), _mid, (char**)&keys, (uint32_t*)&keysLen, (uint32_t*)maxLen, (uint32_t*)numKeys);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSP_PERF_STUB_H
diff --git a/src/adspmsgd_adsp1_stub.c b/src/adspmsgd_adsp1_stub.c
new file mode 100644
index 0000000..d4c0050
--- /dev/null
+++ b/src/adspmsgd_adsp1_stub.c
@@ -0,0 +1,489 @@
+#ifndef _ADSPMSGD_ADSP1_STUB_H
+#define _ADSPMSGD_ADSP1_STUB_H
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "adspmsgd_adsp1.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#include <string.h>
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSPMSGD_ADSP1_SLIM_H
+#define _ADSPMSGD_ADSP1_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Parameter parameters[3] = {{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8),0,0},{SLIM_IFPTR32(0x4,0x8),{{(const uintptr_t)0xdeadc0de,(const uintptr_t)0}}, 0,SLIM_IFPTR32(0x4,0x8),3,0},{SLIM_IFPTR32(0x4,0x8),{{(const uintptr_t)0xdeadc0de,(const uintptr_t)0}}, 0,SLIM_IFPTR32(0x4,0x8),0,0}};
+static const Parameter* const parameterArrays[3] = {(&(parameters[0])),(&(parameters[1])),(&(parameters[2]))};
+static const Method methods[3] = {{REMOTE_SCALARS_MAKEX(0,0,0x2,0x0,0x0,0x1),0x4,0x0,2,2,(&(parameterArrays[0])),0x4,0x1},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x1,0x0),0x0,0x0,1,1,(&(parameterArrays[2])),0x1,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x0,0x0),0x0,0x0,0,0,0,0x0,0x0}};
+static const Method* const methodArrays[4] = {&(methods[0]),&(methods[1]),&(methods[2]),&(methods[2])};
+static const char strings[30] = "deinit\0init2\0close\0open\0uri\0h\0";
+static const uint16_t methodStrings[7] = {19,24,28,13,28,0,7};
+static const uint16_t methodStringsArrays[4] = {0,3,6,5};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adspmsgd_adsp1_slim) = {4,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSPMSGD_ADSP1_SLIM_H
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp1_skel_handle_invoke)(remote_handle64 _h, uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle64_invoke)(_h, _sc, _pra);
+}
+#ifdef __cplusplus
+extern "C" {
+#endif
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp1_open)(const char* uri, remote_handle64* h) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle64_open)(uri, h);
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp1_close)(remote_handle64 h) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle64_close)(h);
+}
+static __inline int _stub_method(remote_handle64 _handle, uint32_t _mid) {
+   remote_arg* _pra = 0;
+   int _nErr = 0;
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle64_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp1_init2)(remote_handle64 _handle) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 2;
+   return _stub_method(_handle, _mid);
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp1_deinit)(remote_handle64 _handle) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 3;
+   return _stub_method(_handle, _mid);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSPMSGD_ADSP1_STUB_H
diff --git a/src/adspmsgd_adsp_stub.c b/src/adspmsgd_adsp_stub.c
new file mode 100644
index 0000000..ab86f48
--- /dev/null
+++ b/src/adspmsgd_adsp_stub.c
@@ -0,0 +1,595 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSPMSGD_ADSP_STUB_H
+#define _ADSPMSGD_ADSP_STUB_H
+#include "adspmsgd_adsp.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSPMSGD_ADSP_SLIM_H
+#define _ADSPMSGD_ADSP_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Parameter parameters[3] = {{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,3,0}};
+static const Parameter* const parameterArrays[5] = {(&(parameters[0])),(&(parameters[1])),(&(parameters[1])),(&(parameters[1])),(&(parameters[2]))};
+static const Method methods[2] = {{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x10,0x4,5,5,(&(parameterArrays[0])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x0,0x0,0x0,0x0),0x0,0x0,0,0,0,0x0,0x0}};
+static const Method* const methodArrays[3] = {&(methods[0]),&(methods[1]),&(methods[1])};
+static const char strings[56] = "buff_addr\0ion_flags\0buf_size\0deinit\0filter\0heapid\0init2\0";
+static const uint16_t methodStrings[8] = {31,43,10,36,20,0,29,50};
+static const uint16_t methodStringsArrays[3] = {0,7,6};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adspmsgd_adsp_slim) = {3,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSPMSGD_ADSP_SLIM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _const_adspmsgd_adsp_handle
+#define _const_adspmsgd_adsp_handle ((remote_handle)-1)
+#endif //_const_adspmsgd_adsp_handle
+
+static void _adspmsgd_adsp_pls_dtor(void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   if(_const_adspmsgd_adsp_handle != *ph) {
+      (void)__QAIC_REMOTE(remote_handle_close)(*ph);
+      *ph = _const_adspmsgd_adsp_handle;
+   }
+}
+
+static int _adspmsgd_adsp_pls_ctor(void* ctx, void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   *ph = _const_adspmsgd_adsp_handle;
+   if(*ph == (remote_handle)-1) {
+      return __QAIC_REMOTE(remote_handle_open)((const char*)ctx, ph);
+   }
+   return 0;
+}
+
+#if (defined __qdsp6__) || (defined __hexagon__)
+#pragma weak  adsp_pls_add_lookup
+extern int adsp_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+#pragma weak  HAP_pls_add_lookup
+extern int HAP_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+
+__QAIC_STUB_EXPORT remote_handle _adspmsgd_adsp_handle(void) {
+   remote_handle* ph;
+   if(adsp_pls_add_lookup) {
+      if(0 == adsp_pls_add_lookup((uint32_t)_adspmsgd_adsp_handle, 0, sizeof(*ph),  _adspmsgd_adsp_pls_ctor, "adspmsgd_adsp",  _adspmsgd_adsp_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   } else if(HAP_pls_add_lookup) {
+      if(0 == HAP_pls_add_lookup((uint32_t)_adspmsgd_adsp_handle, 0, sizeof(*ph),  _adspmsgd_adsp_pls_ctor, "adspmsgd_adsp",  _adspmsgd_adsp_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   }
+   return(remote_handle)-1;
+}
+
+#else //__qdsp6__ || __hexagon__
+
+uint32_t _adspmsgd_adsp_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare);
+
+#ifdef _WIN32
+#include "Windows.h"
+uint32_t _adspmsgd_adsp_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return (uint32_t)InterlockedCompareExchange((volatile LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
+}
+#elif __GNUC__
+uint32_t _adspmsgd_adsp_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+#endif //_WIN32
+
+
+__QAIC_STUB_EXPORT remote_handle _adspmsgd_adsp_handle(void) {
+   static remote_handle handle = _const_adspmsgd_adsp_handle;
+   if((remote_handle)-1 != handle) {
+      return handle;
+   } else {
+      remote_handle tmp;
+      int nErr = _adspmsgd_adsp_pls_ctor("adspmsgd_adsp", (void*)&tmp);
+      if(nErr) {
+         return (remote_handle)-1;
+      }
+      if(((remote_handle)-1 != handle) || ((remote_handle)-1 != (remote_handle)_adspmsgd_adsp_atomic_CompareAndExchange((uint32_t*)&handle, (uint32_t)tmp, (uint32_t)-1))) {
+         _adspmsgd_adsp_pls_dtor(&tmp);
+      }
+      return handle;
+   }
+}
+
+#endif //__qdsp6__
+
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle_invoke)(_adspmsgd_adsp_handle(), _sc, _pra);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _stub_method(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], uint32_t _in1[1], uint32_t _in2[1], uint32_t _in3[1], uint32_t _rout4[1]) {
+   int _numIn[1];
+   remote_arg _pra[2];
+   uint32_t _primIn[4];
+   uint32_t _primROut[1];
+   int _nErr = 0;
+   _numIn[0] = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _pra[(_numIn[0] + 1)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 1)].buf.nLen = sizeof(_primROut);
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _in1, 0, 4);
+   _COPY(_primIn, 8, _in2, 0, 4);
+   _COPY(_primIn, 12, _in3, 0, 4);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 1, 1, 0, 0), _pra));
+   _COPY(_rout4, 0, _primROut, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp_init)(int heapid, uint32 ion_flags, uint32 filter, uint32 buf_size, int* buff_addr) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 0;
+   return _stub_method(_adspmsgd_adsp_handle(), _mid, (uint32_t*)&heapid, (uint32_t*)&ion_flags, (uint32_t*)&filter, (uint32_t*)&buf_size, (uint32_t*)buff_addr);
+}
+static __inline int _stub_method_1(remote_handle _handle, uint32_t _mid) {
+   remote_arg* _pra = 0;
+   int _nErr = 0;
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 0, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp_init2)(void) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 1;
+   return _stub_method_1(_adspmsgd_adsp_handle(), _mid);
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(adspmsgd_adsp_deinit)(void) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 2;
+   return _stub_method_1(_adspmsgd_adsp_handle(), _mid);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSPMSGD_ADSP_STUB_H
diff --git a/src/adspmsgd_android.c b/src/adspmsgd_android.c
new file mode 100644
index 0000000..edd45e5
--- /dev/null
+++ b/src/adspmsgd_android.c
@@ -0,0 +1,83 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include "adspmsgd_apps.h"
+#include "remote.h"
+
+#include <stdio.h>
+#include <android/log.h>
+
+#define LOG_NODE_SIZE           258
+#define LOG_FILENAME_SIZE       30
+#define LOG_MSG_SIZE            LOG_NODE_SIZE - LOG_FILENAME_SIZE - \
+    sizeof(enum adspmsgd_apps_Level) - (3*sizeof(unsigned short))
+
+typedef struct __attribute__((packed))
+{
+    enum adspmsgd_apps_Level level;
+    unsigned short line;
+    unsigned short thread_id;
+    unsigned short asid;
+    char str[LOG_MSG_SIZE];
+    char file [LOG_FILENAME_SIZE];
+} LogNode;
+
+static inline android_LogPriority convert_level_to_android_priority(
+    enum adspmsgd_apps_Level level)
+{
+    switch (level) {
+        case LOW:
+            return ANDROID_LOG_DEBUG;
+        case MEDIUM:
+            return ANDROID_LOG_INFO;
+        case HIGH:
+            return ANDROID_LOG_WARN;
+        case ERROR:
+            return ANDROID_LOG_ERROR;
+        case FATAL:
+            return ANDROID_LOG_FATAL;
+        default:
+            return ANDROID_LOG_DEFAULT;
+        }
+}
+
+int adspmsgd_apps_log(const unsigned char *log_message_buffer,
+                      int log_message_bufferLen)
+{
+    LogNode *logMessage = (LogNode *)log_message_buffer;
+    while (  (log_message_bufferLen  > 0) && (logMessage != NULL)) {
+        __android_log_print(convert_level_to_android_priority(logMessage->level),
+            "adsprpc", "%s:%d:0x%x:%d:%s", logMessage->file, logMessage->line,
+            logMessage->thread_id, logMessage->asid, logMessage->str);
+        logMessage++;
+        log_message_bufferLen -= sizeof(LogNode);
+    };
+
+    return 0;
+}
diff --git a/src/adspmsgd_apps.c b/src/adspmsgd_apps.c
new file mode 100644
index 0000000..f1871d3
--- /dev/null
+++ b/src/adspmsgd_apps.c
@@ -0,0 +1,82 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include "adspmsgd_apps.h"
+#include "remote.h"
+
+#include <stdio.h>
+
+#define LOG_NODE_SIZE           256
+#define LOG_FILENAME_SIZE       30
+#define LOG_MSG_SIZE            LOG_NODE_SIZE - LOG_FILENAME_SIZE - \
+    sizeof(enum adspmsgd_apps_Level) - (2*sizeof(unsigned short))
+
+typedef struct __attribute__((packed))
+{
+    enum adspmsgd_apps_Level level;
+    unsigned short line;
+    unsigned short thread_id;
+    char str[LOG_MSG_SIZE];
+    char file [LOG_FILENAME_SIZE];
+} LogNode;
+
+#if 0
+static inline android_LogPriority convert_level_to_android_priority(
+    enum adspmsgd_apps_Level level)
+{
+    switch (level) {
+        case LOW:
+            return LOW;
+        case MEDIUM:
+            return MEDIUM;
+        case HIGH:
+            return HIGH;
+        case ERROR:
+            return ERROR;
+        case FATAL:
+            return FATAL;
+        default:
+            return 0;
+        }
+}
+#endif
+
+int adspmsgd_apps_log(const unsigned char *log_message_buffer,
+                      int log_message_bufferLen)
+{
+    LogNode *logMessage = (LogNode *)log_message_buffer;
+    while (  (log_message_bufferLen  > 0) && (logMessage != NULL)) {
+        printf("adsprpc: %s:%d:0x%x:%s", logMessage->file, logMessage->line,
+            logMessage->thread_id, logMessage->str);
+        logMessage++;
+        log_message_bufferLen -= sizeof(LogNode);
+    };
+
+    return 0;
+}
diff --git a/src/adspmsgd_apps_skel.c b/src/adspmsgd_apps_skel.c
new file mode 100644
index 0000000..acc3361
--- /dev/null
+++ b/src/adspmsgd_apps_skel.c
@@ -0,0 +1,494 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _ADSPMSGD_APPS_SKEL_H
+#define _ADSPMSGD_APPS_SKEL_H
+#include "adspmsgd_apps.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _ADSPMSGD_APPS_SLIM_H
+#define _ADSPMSGD_APPS_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[1];
+static const Type types[1] = {{0x1,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x1}};
+static const Parameter parameters[1] = {{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(types[0]),(const uintptr_t)0x0}}, 9,SLIM_IFPTR32(0x4,0x8),0,0}};
+static const Parameter* const parameterArrays[1] = {(&(parameters[0]))};
+static const Method methods[1] = {{REMOTE_SCALARS_MAKEX(0,0,0x2,0x0,0x0,0x0),0x4,0x0,2,1,(&(parameterArrays[0])),0x4,0x0}};
+static const Method* const methodArrays[1] = {&(methods[0])};
+static const char strings[23] = "log_message_buffer\0log\0";
+static const uint16_t methodStrings[2] = {19,0};
+static const uint16_t methodStringsArrays[1] = {0};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(adspmsgd_apps_slim) = {1,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_ADSPMSGD_APPS_SLIM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _skel_method(int (*_pfn)(char*, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   uint32_t* _primIn;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 2) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 4);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, *_in0Len));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_SKEL_EXPORT int __QAIC_SKEL(adspmsgd_apps_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_SKEL_ATTRIBUTE {
+   switch(REMOTE_SCALARS_METHOD(_sc))
+   {
+      case 0:
+      return _skel_method((void*)__QAIC_IMPL(adspmsgd_apps_log), _sc, _pra);
+   }
+   return AEE_EUNSUPPORTED;
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_ADSPMSGD_APPS_SKEL_H
diff --git a/src/adsprpcd.c b/src/adsprpcd.c
new file mode 100644
index 0000000..9cf3f68
--- /dev/null
+++ b/src/adsprpcd.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 VERIFY_PRINT_ERROR
+#define VERIFY_PRINT_ERROR
+#endif
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include "verify.h"
+
+
+#ifndef ADSP_DEFAULT_LISTENER_NAME
+#define ADSP_DEFAULT_LISTENER_NAME "libadsp_default_listener.so"
+#endif
+
+typedef int (*adsp_default_listener_start_t)(int argc, char *argv[]);
+
+int main(int argc, char *argv[]) {
+
+  int nErr = 0;
+  void *adsphandler = NULL;
+  adsp_default_listener_start_t listener_start;
+
+  VERIFY_EPRINTF("adsp daemon starting");
+  while (1) {
+    if(NULL != (adsphandler = dlopen(ADSP_DEFAULT_LISTENER_NAME, RTLD_NOW))) {
+      if(NULL != (listener_start =
+	(adsp_default_listener_start_t)dlsym(adsphandler, "adsp_default_listener_start"))) {
+        VERIFY_IPRINTF("adsp_default_listener_start called");
+        listener_start(argc, argv);
+      }
+      if(0 != dlclose(adsphandler)) {
+        VERIFY_EPRINTF("dlclose failed");
+      }
+    } else {
+      VERIFY_EPRINTF("adsp daemon error %s", dlerror());
+    }
+    VERIFY_EPRINTF("adsp daemon will restart after 25ms...");
+    usleep(25000);
+  }
+  VERIFY_EPRINTF("adsp daemon exiting %x", nErr);
+bail:
+  return nErr;
+}
diff --git a/src/apps_mem_imp.c b/src/apps_mem_imp.c
new file mode 100644
index 0000000..d6f2ccb
--- /dev/null
+++ b/src/apps_mem_imp.c
@@ -0,0 +1,244 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 VERIFY_PRINT_ERROR
+#define VERIFY_PRINT_ERROR
+#endif /* VERIFY_PRINT_ERROR */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <pthread.h>
+#include <sys/mman.h>
+#include "apps_mem.h"
+#include "remote64.h"
+#include "rpcmem.h"
+#include "verify.h"
+#include "rpcmem.h"
+#include "AEEQList.h"
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+#include "fastrpc_apps_user.h"
+#include "platform_libs.h"
+
+#define ADSP_MMAP_HEAP_ADDR 4
+#define ADSP_MMAP_REMOTE_HEAP_ADDR 8
+#define ADSP_MMAP_ADD_PAGES   0x1000
+
+static QList memlst;
+static pthread_mutex_t memmt;
+
+struct mem_info {
+   QNode qn;
+   uint64 vapps;
+   uint64 vadsp;
+   int32 size;
+   int32 mapped;
+};
+
+/*
+These should be called in some static constructor of the .so that
+uses rpcmem.
+
+I moved them into fastrpc_apps_user.c because there is no gurantee in
+the order of when constructors are called.
+*/
+
+static int apps_mem_init(void) {
+   QList_Ctor(&memlst);
+   pthread_mutex_init(&memmt, 0);
+   return AEE_SUCCESS;
+}
+
+void apps_mem_deinit(void) {
+   QNode *pn;
+   while ((pn = QList_PopZ(&memlst)) != NULL) {
+      struct mem_info *mfree = STD_RECOVER_REC(struct mem_info, qn, pn);
+
+      if (mfree->vapps) {
+         if(mfree->mapped) {
+            munmap((void*)(uintptr_t)mfree->vapps, mfree->size);
+         } else {
+            rpcmem_free_internal((void *)(uintptr_t)mfree->vapps);
+         }
+      }
+      free(mfree);
+      mfree = NULL;
+   }
+   pthread_mutex_destroy(&memmt);
+}
+PL_DEFINE(apps_mem, apps_mem_init, apps_mem_deinit);
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_map64)(int heapid, uint32 lflags, uint32 rflags, uint64 vin, int64 len, uint64* vapps, uint64* vadsp) __QAIC_IMPL_ATTRIBUTE {
+   struct mem_info *minfo = 0;
+   int nErr = 0;
+   void* buf = 0;
+   uint64_t pbuf;
+   int fd = -1;
+
+   (void)vin;
+   VERIFYC(NULL != (minfo = malloc(sizeof(*minfo))), AEE_ENOMEMORY);
+   QNode_CtorZ(&minfo->qn);
+   *vadsp = 0;
+   if (rflags == ADSP_MMAP_HEAP_ADDR || rflags == ADSP_MMAP_REMOTE_HEAP_ADDR) {
+	VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(-1, rflags, 0, len, (uint64_t*)vadsp)));
+	*vapps = 0;
+	minfo->vapps = 0;
+   } else {
+	if ((rflags != ADSP_MMAP_ADD_PAGES) ||
+		((rflags == ADSP_MMAP_ADD_PAGES) && !is_kernel_alloc_supported(-1, -1))) {
+		VERIFYC(NULL != (buf = rpcmem_alloc_internal(heapid, lflags, len)), AEE_ENORPCMEMORY);
+		fd = rpcmem_to_fd_internal(buf);
+		VERIFYC(fd > 0, AEE_EINVALIDFD);
+	}
+	VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(fd, rflags, (uint64_t)buf, len, (uint64_t*)vadsp)));
+	pbuf = (uint64_t)buf;
+	*vapps = pbuf;
+	minfo->vapps = *vapps;
+   }
+   minfo->vadsp = *vadsp;
+   minfo->size = len;
+   minfo->mapped = 0;
+   pthread_mutex_lock(&memmt);
+   QList_AppendNode(&memlst, &minfo->qn);
+   pthread_mutex_unlock(&memmt);
+bail:
+   if(nErr) {
+      if(buf) {
+         rpcmem_free_internal(buf);
+         buf = NULL;
+      }
+      if(minfo) {
+         free(minfo);
+         minfo = NULL;
+      }
+      VERIFY_EPRINTF("Error %x: apps_mem_request_mmap64 failed\n", nErr);
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_map)(int heapid, uint32 lflags, uint32 rflags, uint32 vin, int32 len, uint32* vapps, uint32* vadsp) __QAIC_IMPL_ATTRIBUTE {
+   uint64 vin1, vapps1, vadsp1;
+   int64 len1;
+   int nErr = AEE_SUCCESS;
+   vin1 = (uint64)vin;
+   len1 = (int64)len;
+   nErr = apps_mem_request_map64(heapid, lflags, rflags, vin1, len1, &vapps1, &vadsp1);
+   *vapps = (uint32)vapps1;
+   *vadsp = (uint32)vadsp1;
+   if(nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: apps_mem_request_map failed\n", nErr);
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_unmap64)(uint64 vadsp, int64 len) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct mem_info *minfo, *mfree = 0;
+   QNode *pn, *pnn;
+   VERIFY(0 == (nErr = remote_munmap64((uint64_t)vadsp, len)));
+   pthread_mutex_lock(&memmt);
+   QLIST_NEXTSAFE_FOR_ALL(&memlst, pn, pnn) {
+      minfo = STD_RECOVER_REC(struct mem_info, qn, pn);
+      if(minfo->vadsp == vadsp) {
+         mfree = minfo;
+         QNode_Dequeue(&minfo->qn);
+         break;
+      }
+   }
+   pthread_mutex_unlock(&memmt);
+   VERIFYC(mfree, AEE_ENOSUCHMAP);
+   if(mfree->mapped) {
+      munmap((void*)(uintptr_t)mfree->vapps, mfree->size);
+   } else {
+      if (mfree->vapps)
+         rpcmem_free_internal((void *)(uintptr_t)mfree->vapps);
+   }
+   free(mfree);
+   mfree = NULL;
+bail:
+   if(nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: apps_mem_request_unmap64 failed\n", nErr);
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_request_unmap)(uint32 vadsp, int32 len) __QAIC_IMPL_ATTRIBUTE {
+   uint64 vadsp1 = (uint64)vadsp;
+   int64 len1 = (int64)len;
+   int nErr = apps_mem_request_unmap64(vadsp1, len1);
+   if(nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: apps_mem_request_unmap failed\n", nErr);
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_share_map)(int fd, int size, uint64* vapps, uint64* vadsp) __QAIC_IMPL_ATTRIBUTE {
+   struct mem_info *minfo = 0;
+   int nErr = AEE_SUCCESS;
+   void* buf = 0;
+   uint64_t pbuf;
+   VERIFYC(0 != (minfo = malloc(sizeof(*minfo))), AEE_ENOMEMORY);
+   QNode_CtorZ(&minfo->qn);
+   VERIFYC(fd > 0, AEE_EINVALIDFD);
+   *vadsp = 0;
+   VERIFYC(MAP_FAILED != (buf = (void *)mmap(NULL, size,
+                           PROT_READ|PROT_WRITE, MAP_SHARED, fd, 0)), AEE_EMMAP);
+   VERIFY(AEE_SUCCESS == (nErr = remote_mmap64(fd, 0, (uint64_t)buf, size, (uint64_t*)vadsp)));
+   pbuf = (uint64_t)buf;
+   *vapps = pbuf;
+   minfo->vapps = *vapps;
+   minfo->vadsp = *vadsp;
+   minfo->size = size;
+   minfo->mapped = 1;
+   pthread_mutex_lock(&memmt);
+   QList_AppendNode(&memlst, &minfo->qn);
+   pthread_mutex_unlock(&memmt);
+bail:
+   if(nErr) {
+      if(buf) {
+         munmap(buf, size);
+      }
+      if(minfo) {
+         free(minfo);
+         minfo = NULL;
+      }
+      VERIFY_EPRINTF("Error %x: apps_mem_share_map failed\n", nErr);
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_mem_share_unmap)(uint64 vadsp, int size) __QAIC_IMPL_ATTRIBUTE {
+   int64 len1 = (int64)size;
+   int nErr = AEE_SUCCESS;
+   nErr = apps_mem_request_unmap64(vadsp, len1);
+   if(nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: apps_mem_share_unmap failed\n", nErr);
+   }
+   return nErr;
+}
diff --git a/src/apps_mem_skel.c b/src/apps_mem_skel.c
new file mode 100644
index 0000000..8bd74d5
--- /dev/null
+++ b/src/apps_mem_skel.c
@@ -0,0 +1,617 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _APPS_MEM_SKEL_H
+#define _APPS_MEM_SKEL_H
+#include "apps_mem.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _APPS_MEM_SLIM_H
+#define _APPS_MEM_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Parameter parameters[6] = {{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,3,0},{0x8,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x8,0,0},{0x8,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x8,0,0},{0x8,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x8,3,0}};
+static const Parameter* const parameterArrays[20] = {(&(parameters[0])),(&(parameters[1])),(&(parameters[1])),(&(parameters[3])),(&(parameters[4])),(&(parameters[5])),(&(parameters[5])),(&(parameters[0])),(&(parameters[1])),(&(parameters[1])),(&(parameters[1])),(&(parameters[0])),(&(parameters[2])),(&(parameters[2])),(&(parameters[0])),(&(parameters[0])),(&(parameters[5])),(&(parameters[5])),(&(parameters[3])),(&(parameters[0]))};
+static const Method methods[6] = {{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x14,0x8,7,7,(&(parameterArrays[7])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0x8,0x0,2,2,(&(parameterArrays[10])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x20,0x10,11,7,(&(parameterArrays[0])),0x8,0x8},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0x10,0x0,6,2,(&(parameterArrays[3])),0x8,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x8,0x10,4,4,(&(parameterArrays[14])),0x4,0x8},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0xc,0x0,4,2,(&(parameterArrays[18])),0x8,0x0}};
+static const Method* const methodArrays[6] = {&(methods[0]),&(methods[1]),&(methods[2]),&(methods[3]),&(methods[4]),&(methods[5])};
+static const char strings[130] = "request_unmap64\0request_map64\0request_unmap\0share_unmap\0request_map\0share_map\0ion_flags\0rflags\0heapid\0vadsp\0vapps\0size\0len\0vin\0fd\0";
+static const uint16_t methodStrings[30] = {16,95,78,88,123,119,108,102,56,95,78,88,123,119,108,102,68,127,114,108,102,44,102,114,0,102,119,30,102,119};
+static const uint16_t methodStringsArrays[6] = {8,27,0,24,16,21};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(apps_mem_slim) = {6,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_APPS_MEM_SLIM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _skel_method(int (*_pfn)(uint64_t, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint64_t _in0[1];
+   uint32_t _in1[1];
+   uint64_t* _primIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 1) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 12);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 8);
+   _COPY(_in1, 0, _primIn, 8, 4);
+   _TRY(_nErr, _pfn(*_in0, *_in1));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_1(int (*_pfn)(uint32_t, uint32_t, uint64_t*, uint64_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t _in1[1];
+   uint64_t _rout2[1];
+   uint64_t _rout3[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint64_t* _primROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 2) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 16);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1, 0, _primIn, 4, 4);
+   _TRY(_nErr, _pfn(*_in0, *_in1, _rout2, _rout3));
+   _COPY(_primROut, 0, _rout2, 0, 8);
+   _COPY(_primROut, 8, _rout3, 0, 8);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_2(int (*_pfn)(uint64_t, uint64_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint64_t _in0[1];
+   uint64_t _in1[1];
+   uint64_t* _primIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 1) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 16);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 8);
+   _COPY(_in1, 0, _primIn, 8, 8);
+   _TRY(_nErr, _pfn(*_in0, *_in1));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_3(int (*_pfn)(uint32_t, uint32_t, uint32_t, uint64_t, uint64_t, uint64_t*, uint64_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t _in1[1];
+   uint32_t _in2[1];
+   uint64_t _in3[1];
+   uint64_t _in4[1];
+   uint64_t _rout5[1];
+   uint64_t _rout6[1];
+   uint64_t* _primIn;
+   int _numIn[1];
+   uint64_t* _primROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 2) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 32);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 16);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1, 0, _primIn, 4, 4);
+   _COPY(_in2, 0, _primIn, 8, 4);
+   _COPY(_in3, 0, _primIn, 16, 8);
+   _COPY(_in4, 0, _primIn, 24, 8);
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in2, *_in3, *_in4, _rout5, _rout6));
+   _COPY(_primROut, 0, _rout5, 0, 8);
+   _COPY(_primROut, 8, _rout6, 0, 8);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_4(int (*_pfn)(uint32_t, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t _in1[1];
+   uint32_t* _primIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 1) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1, 0, _primIn, 4, 4);
+   _TRY(_nErr, _pfn(*_in0, *_in1));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_5(int (*_pfn)(uint32_t, uint32_t, uint32_t, uint32_t, uint32_t, uint32_t*, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t _in1[1];
+   uint32_t _in2[1];
+   uint32_t _in3[1];
+   uint32_t _in4[1];
+   uint32_t _rout5[1];
+   uint32_t _rout6[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 2) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 20);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 8);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1, 0, _primIn, 4, 4);
+   _COPY(_in2, 0, _primIn, 8, 4);
+   _COPY(_in3, 0, _primIn, 12, 4);
+   _COPY(_in4, 0, _primIn, 16, 4);
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in2, *_in3, *_in4, _rout5, _rout6));
+   _COPY(_primROut, 0, _rout5, 0, 4);
+   _COPY(_primROut, 4, _rout6, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_SKEL_EXPORT int __QAIC_SKEL(apps_mem_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_SKEL_ATTRIBUTE {
+   switch(REMOTE_SCALARS_METHOD(_sc))
+   {
+      case 0:
+      return _skel_method_5((void*)__QAIC_IMPL(apps_mem_request_map), _sc, _pra);
+      case 1:
+      return _skel_method_4((void*)__QAIC_IMPL(apps_mem_request_unmap), _sc, _pra);
+      case 2:
+      return _skel_method_3((void*)__QAIC_IMPL(apps_mem_request_map64), _sc, _pra);
+      case 3:
+      return _skel_method_2((void*)__QAIC_IMPL(apps_mem_request_unmap64), _sc, _pra);
+      case 4:
+      return _skel_method_1((void*)__QAIC_IMPL(apps_mem_share_map), _sc, _pra);
+      case 5:
+      return _skel_method((void*)__QAIC_IMPL(apps_mem_share_unmap), _sc, _pra);
+   }
+   return AEE_EUNSUPPORTED;
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_APPS_MEM_SKEL_H
diff --git a/src/apps_remotectl_skel.c b/src/apps_remotectl_skel.c
new file mode 100644
index 0000000..afd3c38
--- /dev/null
+++ b/src/apps_remotectl_skel.c
@@ -0,0 +1,499 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _APPS_REMOTECTL_SKEL_H
+#define _APPS_REMOTECTL_SKEL_H
+#include "apps_remotectl.h"
+#include "remote.h"
+#include <string.h>
+#ifndef ALLOCATOR_H
+#define ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} allocator;
+
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+
+static __inline int allocator_alloc(allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+
+static __inline void allocator_deinit(allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+static __inline void allocator_init(allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _APPS_REMOTECTL_SLIM_H
+#define _APPS_REMOTECTL_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[1];
+static const Type types[1] = {{0x1,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x1}};
+static const Parameter parameters[4] = {{0x8,{{(const uintptr_t)0x0,0}}, 4,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,3,0},{0x8,{{(const uintptr_t)&(types[0]),(const uintptr_t)0x0}}, 9,0x4,3,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,0,0}};
+static const Parameter* const parameterArrays[7] = {(&(parameters[0])),(&(parameters[1])),(&(parameters[2])),(&(parameters[1])),(&(parameters[3])),(&(parameters[2])),(&(parameters[1]))};
+static const Method methods[2] = {{REMOTE_SCALARS_MAKEX(0,0,0x2,0x2,0x0,0x0),0x8,0x8,6,4,(&(parameterArrays[0])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x2,0x0,0x0),0x8,0x4,5,3,(&(parameterArrays[4])),0x4,0x4}};
+static const Method* const methodArrays[2] = {&(methods[0]),&(methods[1])};
+static const char strings[36] = "dlerror\0handle\0close\0nErr\0name\0open\0";
+static const uint16_t methodStrings[9] = {31,26,8,0,21,15,8,0,21};
+static const uint16_t methodStringsArrays[2] = {0,5};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(apps_remotectl_slim) = {2,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_APPS_REMOTECTL_SLIM_H
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#endif
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE_LINE__  ": error: %d\n", (int)(ee)));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _skel_method(int (*_pfn)(uint32_t, char*, uint32_t, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _rout1[1];
+   uint32_t _rout1Len[1];
+   uint32_t _rout2[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 3) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 4);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_rout1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _ASSERT(_nErr, (int)((_praROut[0].buf.nLen / 1)) >= (int)(_rout1Len[0]));
+   _rout1[0] = _praROut[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, *_rout1, *_rout1Len, _rout2));
+   _COPY(_primROut, 0, _rout2, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_1(int (*_pfn)(char*, uint32_t*, char*, uint32_t, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   uint32_t _rout1[1];
+   char* _rout2[1];
+   uint32_t _rout2Len[1];
+   uint32_t _rout3[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc));
+   _ASSERT(_nErr, (_pra + 4) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 8);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   if(_in0Len[0] > 0)
+   {
+      _in0[0][(_in0Len[0] - 1)] = 0;
+   }
+   _COPY(_rout2Len, 0, _primIn, 4, 4);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _ASSERT(_nErr, (int)((_praROut[0].buf.nLen / 1)) >= (int)(_rout2Len[0]));
+   _rout2[0] = _praROut[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, _rout1, *_rout2, *_rout2Len, _rout3));
+   _COPY(_primROut, 0, _rout1, 0, 4);
+   _COPY(_primROut, 4, _rout3, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_SKEL_EXPORT int __QAIC_SKEL(apps_remotectl_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_SKEL_ATTRIBUTE {
+   switch(REMOTE_SCALARS_METHOD(_sc))
+   {
+      case 0:
+      return _skel_method_1((void*)__QAIC_IMPL(apps_remotectl_open), _sc, _pra);
+      case 1:
+      return _skel_method((void*)__QAIC_IMPL(apps_remotectl_close), _sc, _pra);
+   }
+   return AEE_EUNSUPPORTED;
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_APPS_REMOTECTL_SKEL_H
diff --git a/src/apps_std_imp.c b/src/apps_std_imp.c
new file mode 100644
index 0000000..d2559c6
--- /dev/null
+++ b/src/apps_std_imp.c
@@ -0,0 +1,1076 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _WIN32
+#ifndef _CRT_SECURE_NO_WARNINGS
+#define _CRT_SECURE_NO_WARNINGS
+#endif// _CRT_SECURE_NO_WARNINGS
+
+#pragma warning( disable : 4996 )
+#define strtok_r strtok_s
+#define S_ISDIR(mode) (mode & S_IFDIR)
+#endif //_WIN32
+
+#ifndef VERIFY_PRINT_ERROR
+#define VERIFY_PRINT_ERROR
+#endif //VERIFY_PRINT_ERROR
+#define FARF_ERROR 1
+
+#include <stdlib.h>
+#include <errno.h>
+#include <string.h>
+#include <pthread.h>
+#include <dlfcn.h>
+#include <dirent.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <stdio.h>
+#include "remote.h"
+#include "verify.h"
+#include "apps_std.h"
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+#include "AEEatomic.h"
+#include "AEEQList.h"
+#include "platform_libs.h"
+#include "fastrpc_apps_user.h"
+#include "HAP_farf.h"
+#include "rpcmem.h"
+
+#ifndef _WIN32
+#include <unistd.h>
+#endif // _WiN32
+
+#ifndef C_ASSERT
+#define C_ASSERT(test) \
+    switch(0) {\
+      case 0:\
+      case test:;\
+    }
+#endif //C_ASSERT
+
+#define APPS_FD_BASE 100
+#define ERRNO (errno == 0 ? -1 : errno)
+#define APPS_STD_STREAM_FILE 1
+#define APPS_STD_STREAM_BUF 2
+
+#define ION_HEAP_ID_QSEECOM 27
+
+#define FREEIF(pv) \
+   do {\
+      if(pv) { \
+         void* tmp = (void*)pv;\
+         pv = 0;\
+         free(tmp);\
+         tmp = 0;\
+      } \
+   } while(0)
+
+extern int get_domain_id();
+
+struct apps_std_buf_info {
+   char* fbuf;
+   int flen;
+   int pos;
+};
+
+struct apps_std_info {
+   QNode qn;
+   int type;
+   union {
+      FILE* stream;
+      struct apps_std_buf_info binfo;
+   } u;
+   apps_std_FILE fd;
+};
+
+static QList apps_std_qlst;
+static pthread_mutex_t apps_std_mt;
+
+int setenv(const char *name, const char *value, int overwrite);
+int unsetenv(const char *name);
+
+int apps_std_init(void) {
+   QList_Ctor(&apps_std_qlst);
+   pthread_mutex_init(&apps_std_mt, 0);
+   return AEE_SUCCESS;
+}
+
+void apps_std_deinit(void) {
+   pthread_mutex_destroy(&apps_std_mt);
+}
+
+PL_DEFINE(apps_std, apps_std_init, apps_std_deinit);
+
+static int apps_std_FILE_free(struct apps_std_info* sfree) {
+   int nErr = AEE_SUCCESS;
+
+   pthread_mutex_lock(&apps_std_mt);
+   QNode_Dequeue(&sfree->qn);
+   pthread_mutex_unlock(&apps_std_mt);
+
+   free(sfree);
+   sfree = NULL;
+   return nErr;
+}
+
+static int apps_std_FILE_alloc(FILE *stream, apps_std_FILE *fd) {
+   struct apps_std_info *sinfo = 0, *info;
+   QNode *pn = 0;
+   apps_std_FILE prevfd = APPS_FD_BASE - 1;
+   int nErr = AEE_SUCCESS;
+
+   VERIFYC(0 != (sinfo = calloc(1, sizeof(*sinfo))), AEE_ENOMEMORY);
+   QNode_CtorZ(&sinfo->qn);
+   sinfo->type = APPS_STD_STREAM_FILE;
+   pthread_mutex_lock(&apps_std_mt);
+   pn = QList_GetFirst(&apps_std_qlst);
+   if(pn) {
+      info = STD_RECOVER_REC(struct apps_std_info, qn, pn);
+      prevfd = info->fd;
+      QLIST_FOR_REST(&apps_std_qlst, pn) {
+         info = STD_RECOVER_REC(struct apps_std_info, qn, pn);
+         if (info->fd != prevfd + 1) {
+            sinfo->fd = prevfd + 1;
+            QNode_InsPrev(pn, &sinfo->qn);
+            break;
+         }
+         prevfd = info->fd;
+      }
+   }
+   if(!QNode_IsQueuedZ(&sinfo->qn)) {
+      sinfo->fd = prevfd + 1;
+      QList_AppendNode(&apps_std_qlst, &sinfo->qn);
+   }
+   pthread_mutex_unlock(&apps_std_mt);
+
+   sinfo->u.stream = stream;
+   *fd = sinfo->fd;
+
+bail:
+   if(nErr) {
+      FREEIF(sinfo);
+      VERIFY_EPRINTF("Error %x: apps_std_FILE_alloc failed\n", nErr);
+   }
+   return nErr;
+}
+
+static int apps_std_FILE_get(apps_std_FILE fd, struct apps_std_info** info) {
+   struct apps_std_info *sinfo = 0;
+   QNode *pn, *pnn;
+   FILE* stream = NULL;
+   int nErr = AEE_ENOSUCHSTREAM;
+
+   pthread_mutex_lock(&apps_std_mt);
+   QLIST_NEXTSAFE_FOR_ALL(&apps_std_qlst, pn, pnn) {
+      sinfo = STD_RECOVER_REC(struct apps_std_info, qn, pn);
+      if(sinfo->fd == fd) {
+         *info = sinfo;
+         nErr = AEE_SUCCESS;
+         break;
+      }
+   }
+   pthread_mutex_unlock(&apps_std_mt);
+
+   return nErr;
+}
+
+static void apps_std_FILE_set_buffer_stream(struct apps_std_info* sinfo, char* fbuf, int flen, int pos) {
+   pthread_mutex_lock(&apps_std_mt);
+   fclose(sinfo->u.stream);
+   sinfo->type = APPS_STD_STREAM_BUF;
+   sinfo->u.binfo.fbuf = fbuf;
+   sinfo->u.binfo.flen = flen;
+   sinfo->u.binfo.pos = pos;
+   pthread_mutex_unlock(&apps_std_mt);
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fopen)(const char* name, const char* mode, apps_std_FILE* psout) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   FILE* stream = fopen(name, mode);
+   if(stream) {
+      return apps_std_FILE_alloc(stream, psout);
+   } else {
+      nErr = AEE_ENOSUCHFILE;
+   }
+   if(nErr != AEE_SUCCESS) {
+      // Ignoring this error, as fopen happens on all ADSP_LIBRARY_PATHs
+      VERIFY_IPRINTF("Error %x: fopen for %s failed. errno: %s\n", nErr, name, strerror(ERRNO));
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_freopen)(apps_std_FILE sin, const char* name, const char* mode, apps_std_FILE* psout) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+   FILE* stream;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   VERIFY(sinfo->type == APPS_STD_STREAM_FILE);
+   stream = freopen(name, mode, sinfo->u.stream);
+   if(stream) {
+      FARF(HIGH, "freopen success: %s %x\n", name, stream);
+      return apps_std_FILE_alloc(stream, psout);
+   } else {
+      nErr = AEE_EFOPEN;
+   }
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: freopen for %s failed. errno: %s\n", nErr, name, strerror(ERRNO));
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fflush)(apps_std_FILE sin) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      VERIFYC(0 == fflush(sinfo->u.stream), AEE_EFFLUSH);
+   }
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: fflush for %x failed. errno: %s\n", nErr, sin, strerror(ERRNO));
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fclose)(apps_std_FILE sin) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      VERIFYC(0 == fclose(sinfo->u.stream), AEE_EFCLOSE);
+   } else {
+      if(sinfo->u.binfo.fbuf) {
+         rpcmem_free_internal(sinfo->u.binfo.fbuf);
+         sinfo->u.binfo.fbuf = NULL;
+      }
+   }
+   apps_std_FILE_free(sinfo);
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: freopen for %x failed. errno: %s\n", nErr, sin, strerror(ERRNO));
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fread)(apps_std_FILE sin, byte* buf, int bufLen, int* bytesRead, int* bEOF) __QAIC_IMPL_ATTRIBUTE {
+   int out = 0, nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      out = fread(buf, 1, bufLen, sinfo->u.stream);
+      *bEOF = FALSE;
+      if(out <= bufLen) {
+         int err;
+         if(0 == out && (0 != (err = ferror(sinfo->u.stream)))) {
+            nErr = AEE_EFREAD;
+            VERIFY_EPRINTF("Error %x: fread returning %d bytes, requested was %d bytes, errno is %x\n", nErr, out, bufLen, err);
+            return nErr;
+         }
+         *bEOF = feof(sinfo->u.stream);
+      }
+      *bytesRead = out;
+   } else {
+      *bytesRead = std_memscpy(buf, bufLen, sinfo->u.binfo.fbuf + sinfo->u.binfo.pos,
+                               sinfo->u.binfo.flen - sinfo->u.binfo.pos);
+      sinfo->u.binfo.pos += *bytesRead;
+      *bEOF = sinfo->u.binfo.pos == sinfo->u.binfo.flen ? TRUE : FALSE;
+   }
+   FARF(HIGH, "fread returning %d %d 0", out, bufLen);
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fwrite)(apps_std_FILE sin, const byte* buf, int bufLen, int* bytesRead, int* bEOF) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      int out = fwrite(buf, 1, bufLen, sinfo->u.stream);
+      *bEOF = FALSE;
+      if(out <= bufLen) {
+         int err;
+         if(0 == out && (0 != (err = ferror(sinfo->u.stream)))) {
+            nErr = AEE_EFWRITE;
+            VERIFY_EPRINTF("Error %x: fwrite returning %d bytes, requested was %d bytes, errno is %x\n", nErr, out, bufLen, err);
+            return nErr;
+         }
+         *bEOF = feof(sinfo->u.stream);
+      }
+      *bytesRead = out;
+   } else {
+      nErr = AEE_EFWRITE;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fgetpos)(apps_std_FILE sin, byte* pos, int posLen, int* posLenReq) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   fpos_t fpos;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      if(0 == fgetpos(sinfo->u.stream, &fpos)) {
+         std_memmove(pos, &fpos, STD_MIN((int)sizeof(fpos), posLen));
+         *posLenReq = sizeof(fpos);
+         return AEE_SUCCESS;
+      } else {
+         nErr = AEE_EFGETPOS;
+      }
+   } else {
+      nErr = AEE_EFGETPOS;
+   }
+bail:
+   VERIFY_EPRINTF("Error %x: fgetpos failed for %x, errno is %s\n", nErr, sin, strerror(ERRNO));
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fsetpos)(apps_std_FILE sin, const byte* pos, int posLen) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   fpos_t fpos;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      if(sizeof(fpos) != posLen) {
+         return AEE_EBADSIZE;
+      }
+      std_memmove(&fpos, pos, sizeof(fpos));
+      if(0 == fsetpos(sinfo->u.stream, &fpos)) {
+         return AEE_SUCCESS;
+      } else {
+         nErr = AEE_EFSETPOS;
+      }
+   } else {
+      nErr = AEE_EFSETPOS;
+   }
+bail:
+   VERIFY_EPRINTF("Error %x: fsetpos failed for %x, errno is %s\n", nErr, sin, strerror(ERRNO));
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_ftell)(apps_std_FILE sin, int* pos) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      if((*pos = ftell(sinfo->u.stream)) >= 0) {
+         return AEE_SUCCESS;
+      } else {
+         nErr = AEE_EFTELL;
+      }
+   } else {
+      *pos = sinfo->u.binfo.pos;
+      return AEE_SUCCESS;
+   }
+bail:
+   VERIFY_EPRINTF("Error %x: ftell failed for %x, errno is %s\n", nErr, sin, strerror(ERRNO));
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fseek)(apps_std_FILE sin, int offset, apps_std_SEEK whence) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   int op = (int)whence;
+   struct apps_std_info* sinfo = 0;
+
+   C_ASSERT(APPS_STD_SEEK_SET == SEEK_SET);
+   C_ASSERT(APPS_STD_SEEK_CUR == SEEK_CUR);
+   C_ASSERT(APPS_STD_SEEK_END == SEEK_END);
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      if(0 == fseek(sinfo->u.stream, offset, whence)) {
+         return AEE_SUCCESS;
+      } else {
+         nErr = AEE_EFSEEK;
+      }
+   } else {
+      switch(op) {
+      case APPS_STD_SEEK_SET:
+         VERIFYC(offset <= sinfo->u.binfo.flen, AEE_EFSEEK);
+         sinfo->u.binfo.pos = offset;
+         break;
+      case APPS_STD_SEEK_CUR:
+         VERIFYC(offset + sinfo->u.binfo.pos <= sinfo->u.binfo.flen, AEE_EFSEEK);
+         sinfo->u.binfo.pos += offset;
+         break;
+      case APPS_STD_SEEK_END:
+         VERIFYC(offset + sinfo->u.binfo.flen <= sinfo->u.binfo.flen, AEE_EFSEEK);
+         sinfo->u.binfo.pos += offset + sinfo->u.binfo.flen;
+         break;
+      }
+   }
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: fseek failed for %x, errno is %s\n", nErr, sin, strerror(ERRNO));
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_rewind)(apps_std_FILE sin) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      rewind(sinfo->u.stream);
+   } else {
+      sinfo->u.binfo.pos = 0;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_feof)(apps_std_FILE sin, int* bEOF) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      *bEOF = feof(sinfo->u.stream);
+   } else {
+      nErr = AEE_EUNSUPPORTED;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_ferror)(apps_std_FILE sin, int* err) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      *err = ferror(sinfo->u.stream);
+   } else {
+      nErr = AEE_EUNSUPPORTED;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_clearerr)(apps_std_FILE sin) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      clearerr(sinfo->u.stream);
+   } else {
+      nErr = AEE_EUNSUPPORTED;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_flen)(apps_std_FILE sin, uint64* len) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      struct stat st_buf;
+      int fd = fileno(sinfo->u.stream);
+      C_ASSERT(sizeof(st_buf.st_size) <= sizeof(*len));
+      if(fd == -1) {
+         nErr = AEE_EFLEN;
+         VERIFY_EPRINTF("Error %x: flen failed for %x, errno is %s\n", nErr, sin, strerror(ERRNO));
+         return nErr;
+      }
+      if(0 != fstat(fd, &st_buf)) {
+         nErr = AEE_EFLEN;
+         VERIFY_EPRINTF("Error %x: flen failed for %x, errno is %s\n", nErr, sin, strerror(ERRNO));
+         return nErr;
+      }
+      *len = st_buf.st_size;
+   } else {
+      *len = sinfo->u.binfo.flen;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_print_string)(const char* str) __QAIC_IMPL_ATTRIBUTE {
+   printf("%s", str);
+   return AEE_SUCCESS;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_getenv)(const char* name, char* val, int valLen, int* valLenReq) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   char* vv = getenv(name);
+   if(vv) {
+      *valLenReq = std_strlen(vv) + 1;
+      std_strlcpy(val, vv, valLen);
+      return AEE_SUCCESS;
+   }
+   nErr = AEE_EGETENV;
+   VERIFY_IPRINTF("Error %x: apps_std getenv failed: %s %s\n", nErr, name, strerror(ERRNO));
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_setenv)(const char* name, const char* val, int override) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+#ifdef _WIN32
+   return AEE_EUNSUPPORTED;
+#else //_WIN32
+   if(0 != setenv(name, val, override)) {
+      nErr = AEE_ESETENV;
+      VERIFY_EPRINTF("Error %x: setenv failed for %s, errno is %s\n", nErr, name, strerror(ERRNO));
+      return nErr;
+   }
+   return AEE_SUCCESS;
+#endif //_WIN32
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_unsetenv)(const char* name) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+#ifdef _WIN32
+   return AEE_EUNSUPPORTED;
+#else //_WIN32
+   if(0 != unsetenv(name)) {
+      nErr = AEE_ESETENV;
+      VERIFY_EPRINTF("Error %x: unsetenv failed for %s, errno is %s\n", nErr, name, strerror(ERRNO));
+      return nErr;
+   }
+   return AEE_SUCCESS;
+#endif //_WIN32
+}
+
+
+#if (defined LE_ENABLE)
+static char* ADSP_LIBRARY_PATH=";/usr/lib/rfsa/adsp;/usr/lib;/dsp;/usr/share/fastrpc";
+static char* ADSP_AVS_CFG_PATH=";/etc/acdbdata/";
+#elif (defined __BRILLO__)
+static char* ADSP_LIBRARY_PATH=";/system/etc/lib/rfsa/adsp;/system/vendor/etc/lib/rfsa/adsp;/dsp";
+static char* ADSP_AVS_CFG_PATH=";/etc/acdbdata/";
+#elif (defined _ANDROID) || (defined ANDROID)
+#if (defined ANDROID_P) && (defined FULL_TREBLE)
+#ifdef SYSTEM_RPC_LIBRARY
+static char* ADSP_LIBRARY_PATH=";/system/lib/rfsa/adsp";
+static char* ADSP_AVS_CFG_PATH=";/etc/acdbdata/";
+#else
+static char* ADSP_LIBRARY_PATH=";/vendor/lib/rfsa/adsp;/vendor/dsp";
+static char* ADSP_AVS_CFG_PATH=";/vendor/etc/acdbdata/";
+#endif
+#else
+static char* ADSP_LIBRARY_PATH=";/system/lib/rfsa/adsp;/system/vendor/lib/rfsa/adsp;/dsp;/vendor/dsp";
+static char* ADSP_AVS_CFG_PATH=";/etc/acdbdata/;/vendor/etc/acdbdata/";
+#endif
+#elif (defined __QNX__)
+static char* ADSP_LIBRARY_PATH="/radio/lib/firmware";
+#else
+static char* ADSP_LIBRARY_PATH="";
+#endif
+
+#define     EMTPY_STR      ""
+#define     ENV_LEN_GUESS  256
+
+static int get_dirlist_from_env(const char* envvarname, char** ppDirList){
+   char     *envList    =  NULL;
+   char     *envListBuf =  NULL;
+   char     *dirList    =  NULL;
+   char     *dirListBuf =  NULL;
+   char     *srcStr     =  NULL;
+   int      nErr        =  AEE_SUCCESS;
+   int      envListLen  =  0;
+   int      listLen     =  0;
+   int      envLenGuess = STD_MAX(ENV_LEN_GUESS, 1 + std_strlen(ADSP_LIBRARY_PATH));
+
+   VERIFYC(NULL != ppDirList, AEE_EMEMPTR);
+
+   VERIFYC(envListBuf = (char*)malloc(sizeof(char) * envLenGuess), AEE_ENOMEMORY);
+   envList = envListBuf;
+   *envList = '\0';
+   if (0 == apps_std_getenv(envvarname, envList, envLenGuess, &envListLen)) {
+      if (envLenGuess < envListLen) {
+         FREEIF(envListBuf);
+         VERIFYC(envListBuf = realloc(envListBuf, sizeof(char) * envListLen), AEE_ENOMEMORY);
+         envList = envListBuf;
+         VERIFY(0 == (nErr = apps_std_getenv(envvarname, envList, envListLen, &listLen)));
+      }
+   } else if(std_strncmp(envvarname, "ADSP_LIBRARY_PATH", 17) == 0) {
+      envListLen = listLen = 1 + std_strlcpy(envListBuf, ADSP_LIBRARY_PATH, envLenGuess);
+   } else if(std_strncmp(envvarname, "ADSP_AVS_CFG_PATH", 17) == 0) {
+      envListLen = listLen = 1 + std_strlcpy(envListBuf, ADSP_AVS_CFG_PATH, envLenGuess);
+   }
+
+   /*
+    * Allocate mem. to copy envvarname.
+    * If envvarname not set, allocate mem to create an empty string
+    */
+   if('\0' != *envList) {
+      srcStr = envList;
+   } else {
+      srcStr = EMTPY_STR;
+      envListLen = std_strlen(EMTPY_STR) + 1;
+   }
+   VERIFYC(dirListBuf = (char*)malloc(sizeof(char) * envListLen), AEE_ENOMEMORY);
+   dirList = dirListBuf;
+   std_strlcpy(dirList, srcStr, envListLen);
+   *ppDirList = dirListBuf;
+bail:
+   FREEIF(envListBuf);
+   if(nErr != AEE_SUCCESS) {
+       VERIFY_EPRINTF("Error %x: get dirlist from env failed for %s\n", nErr, envvarname);
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fopen_with_env)(const char* envvarname,
+        const char* delim, const char* name, const char* mode,
+        apps_std_FILE* psout) __QAIC_IMPL_ATTRIBUTE {
+
+   int      nErr        =  AEE_SUCCESS;
+   char     *dirName    =  NULL;
+   char     *pos        =  NULL;
+   char     *dirListBuf =  NULL;
+   char     *dirList    =  NULL;
+   char     *absName    =  NULL;
+   uint16   absNameLen  =  0;
+   int domain;
+
+   VERIFYC(NULL != mode, AEE_EINVALIDMODE);
+   VERIFYC(NULL != delim, AEE_EINVALIDFORMAT);
+   VERIFYC(NULL != name, AEE_EMEMPTR);
+
+   VERIFY(0 == (nErr = get_dirlist_from_env(envvarname, &dirListBuf )));
+   VERIFYC(NULL != (dirList = dirListBuf), AEE_EMEMPTR);
+
+   while(dirList)
+   {
+      pos = strstr(dirList, delim);
+      dirName = dirList;
+      if (pos) {
+         *pos = '\0';
+         dirList = pos + std_strlen(delim);
+      } else {
+         dirList = 0;
+      }
+
+      // Account for slash char
+      absNameLen = std_strlen(dirName) + std_strlen(name) + 2;
+      VERIFYC(NULL != (absName = (char*)malloc(sizeof(char) * absNameLen)), AEE_ENOMEMORY);
+      if ('\0' != *dirName) {
+         std_strlcpy(absName, dirName, absNameLen);
+         std_strlcat(absName, "/", absNameLen);
+         std_strlcat(absName, name, absNameLen);
+      } else {
+         std_strlcpy(absName, name, absNameLen);
+      }
+
+      nErr = apps_std_fopen(absName, mode, psout);
+      FREEIF(absName);
+      if (AEE_SUCCESS == nErr) {
+	 // Success
+         goto bail;
+      }
+   }
+   domain = get_domain_id() & DOMAIN_ID_MASK;
+
+#ifdef ANDROID_P
+   absNameLen = std_strlen("/vendor/dsp/adsp/") + std_strlen(name) + 1;
+   VERIFYC(NULL != (absName = (char*)malloc(sizeof(char) * absNameLen)), AEE_ENOMEMORY);
+
+   if (domain == ADSP_DOMAIN_ID){
+       std_strlcpy(absName, "/vendor/dsp/adsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else if (domain == MDSP_DOMAIN_ID){
+       std_strlcpy(absName, "/vendor/dsp/mdsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else if (domain == SDSP_DOMAIN_ID){
+       std_strlcpy(absName, "/vendor/dsp/sdsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else if (domain == CDSP_DOMAIN_ID) {
+       std_strlcpy(absName, "/vendor/dsp/cdsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else {
+       absName[0] = '\0';
+   }
+   nErr = apps_std_fopen(absName, mode, psout);
+#else
+   absNameLen = std_strlen("/dsp/adsp/") + std_strlen(name) + 1;
+   VERIFYC(NULL != (absName = (char*)malloc(sizeof(char) * absNameLen)), AEE_ENOMEMORY);
+
+   if (domain == ADSP_DOMAIN_ID){
+       std_strlcpy(absName, "/dsp/adsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else if (domain == MDSP_DOMAIN_ID){
+       std_strlcpy(absName, "/dsp/mdsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else if (domain == SDSP_DOMAIN_ID){
+       std_strlcpy(absName, "/dsp/sdsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else if (domain == CDSP_DOMAIN_ID) {
+       std_strlcpy(absName, "/dsp/cdsp/", absNameLen);
+       std_strlcat(absName, name,absNameLen);
+   } else {
+       absName[0] = '\0';
+   }
+   nErr = apps_std_fopen(absName, mode, psout);
+#endif
+bail:
+   FREEIF(absName);
+   FREEIF(dirListBuf);
+   if (nErr != AEE_SUCCESS) {
+	VERIFY_IPRINTF("Error %x: fopen failed for %s. (%s)", nErr, name, strerror(ERRNO));
+   }
+   return nErr;
+}
+
+__QAIC_HEADER_EXPORT int __QAIC_IMPL(apps_std_get_search_paths_with_env)(
+    const char* envvarname, const char* delim, _cstring1_t* paths,
+    int pathsLen, uint32* numPaths, uint16* maxPathLen) __QAIC_IMPL_ATTRIBUTE{
+
+   char *path        = NULL;
+   int  nErr         = AEE_SUCCESS;
+   char *dirListBuf  = NULL;
+   int  i            = 0;
+   char *saveptr     = NULL;
+   struct stat st;
+
+   VERIFYC(NULL != numPaths, AEE_EBADSIZE);
+   VERIFYC(NULL != delim, AEE_EINVALIDFORMAT);
+   VERIFYC(NULL != maxPathLen, AEE_EBADSIZE);
+
+   VERIFY(AEE_SUCCESS == (nErr = get_dirlist_from_env(envvarname, &dirListBuf )));
+
+   *numPaths = 0;
+   *maxPathLen = 0;
+
+   // Get the number of folders
+    path = strtok_r (dirListBuf, delim, &saveptr);
+    while (path != NULL){
+        // If the path exists, add it to the return
+        if ((stat(path, &st) == 0) && (S_ISDIR(st.st_mode))) {
+            *maxPathLen = STD_MAX(*maxPathLen, std_strlen(path)+1);
+            if (paths && i < pathsLen && paths[i].data && paths[i].dataLen >= std_strlen(path)) {
+                    std_strlcpy(paths[i].data, path, paths[i].dataLen);
+            }
+            i++;
+         }
+        path = strtok_r (NULL, delim, &saveptr);
+    }
+    *numPaths = i;
+
+bail:
+   FREEIF(dirListBuf);
+   if (nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: apps_std_get_search_paths_with_env failed\n", nErr);
+   }
+   return nErr;
+}
+
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fgets)(apps_std_FILE sin, byte* buf, int bufLen, int* bEOF) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      char* out = fgets((char*)buf, bufLen, sinfo->u.stream);
+      *bEOF = FALSE;
+      if(!out) {
+         int err;
+         if(0 != (err = ferror(sinfo->u.stream))) {
+	    nErr = AEE_EFGETS;
+            VERIFY_EPRINTF("Error %x: fgets failed for %x, errno is %s\n", nErr, sin, strerror(ERRNO));
+            return nErr;
+         }
+         *bEOF = feof(sinfo->u.stream);
+      }
+   } else {
+      nErr = AEE_EUNSUPPORTED;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_fileExists)(const char* path, boolean* exists) __QAIC_HEADER_ATTRIBUTE{
+    int nErr = AEE_SUCCESS;
+    struct stat   buffer;
+
+    VERIFYC(path != NULL, AEE_EMEMPTR);
+    VERIFYC(exists != NULL, AEE_EMEMPTR);
+
+    *exists = (stat (path, &buffer) == 0);
+
+bail:
+    if (nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: fileExists failed for path %s\n", nErr, path);
+    }
+    return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fsync)(apps_std_FILE sin) __QAIC_IMPL_ATTRIBUTE {
+    int nErr = AEE_SUCCESS;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      // This flushes the given sin file stream to user-space buffer.
+      // NOTE: this does NOT ensure data is physically sotred on disk
+      nErr = fflush(sinfo->u.stream);
+      if(nErr != AEE_SUCCESS){
+         VERIFY_EPRINTF("Error %x: apps_std fsync failed,errno is %s\n", nErr, strerror(ERRNO));
+      }
+   } else {
+      nErr = AEE_EUNSUPPORTED;
+   }
+
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fremove)(const char* name) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+
+   if(NULL == name){
+      return nErr;
+   }
+   nErr = remove(name);
+   if(nErr != AEE_SUCCESS){
+      VERIFY_EPRINTF("Error %x: failed to remove file %s,errno is %s\n", nErr, name, strerror(ERRNO));
+   }
+
+   return nErr;
+}
+
+static int decrypt_int(char* fbuf, int size) {
+   int nErr = 0, fd;
+   void* handle = 0;
+   int32_t (*l_init)(void);
+   int32_t (*l_deinit)(void);
+   int32_t (*l_decrypt)(int32_t, int32_t);
+
+   VERIFYC(NULL != (handle = dlopen("liblmclient.so", RTLD_NOW)), AEE_EBADHANDLE);
+   VERIFYC(NULL != (l_init = dlsym(handle, "license_manager_init")), AEE_ENOSUCHSYMBOL);
+   VERIFYC(NULL != (l_deinit = dlsym(handle, "license_manager_deinit")), AEE_ENOSUCHSYMBOL);
+   VERIFYC(NULL != (l_decrypt = dlsym(handle, "license_manager_decrypt")), AEE_ENOSUCHSYMBOL);
+   VERIFY(0 == (nErr = l_init()));
+   VERIFY(-1 != (fd = rpcmem_to_fd_internal(fbuf)));
+   VERIFY(0 == (nErr = l_decrypt(fd, size)));
+   VERIFY(0 == (nErr = l_deinit()));
+bail:
+   if(nErr) {
+      VERIFY_EPRINTF("Error %x: dlopen for licmgr failed. errno: %s\n", nErr, dlerror());
+   }
+   if(handle) {
+      dlclose(handle);
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_fdopen_decrypt)(apps_std_FILE sin, apps_std_FILE *psout) __QAIC_IMPL_ATTRIBUTE {
+   int fd, nErr = AEE_SUCCESS;
+   struct stat st_buf;
+   struct apps_std_info* sinfo = 0;
+   int sz, pos;
+   char* fbuf = 0;
+
+   VERIFY(0 == (nErr = apps_std_FILE_get(sin, &sinfo)));
+   if(sinfo->type == APPS_STD_STREAM_FILE) {
+      pos = ftell(sinfo->u.stream);
+      VERIFYC(-1 != (fd = fileno(sinfo->u.stream)), AEE_EFLEN);
+      VERIFYC(0 == fstat(fd, &st_buf), AEE_EFLEN);
+      sz = (int)st_buf.st_size;
+      VERIFYC(0 != (fbuf = rpcmem_alloc_internal(ION_HEAP_ID_QSEECOM, 1, sz)), AEE_EMEMPTR);
+      VERIFYC(0 == fseek(sinfo->u.stream, 0, SEEK_SET), AEE_EFSEEK);
+      VERIFYC(sz == (int)fread(fbuf, 1, sz, sinfo->u.stream), AEE_EFREAD);
+      VERIFY(0 == (nErr = decrypt_int(fbuf, sz)));
+      apps_std_FILE_set_buffer_stream(sinfo, fbuf, sz, pos);
+      *psout = sin;
+   } else {
+      nErr = AEE_EUNSUPPORTED;
+   }
+bail:
+   if(nErr) {
+      if(fbuf) {
+         rpcmem_free_internal(fbuf);
+         fbuf = NULL;
+      }
+   }
+   return nErr;
+}
+
+
+__QAIC_IMPL_EXPORT int __QAIC_HEADER(apps_std_opendir)(const char* name, apps_std_DIR* dir) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = 0;
+   DIR *odir;
+
+   if(NULL == dir) {
+      return AEE_EBADPARM;
+   }
+   odir = opendir(name);
+   if(odir != NULL) {
+      dir->handle = (uint64)odir;
+   } else {
+      nErr = -1;
+      VERIFY_EPRINTF("Error %x: failed to opendir %s,errno is %s\n", nErr, name, strerror(ERRNO));
+   }
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_HEADER(apps_std_closedir)(const apps_std_DIR* dir) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+
+   if((NULL == dir) || (0 == dir->handle)){
+      return AEE_EBADPARM;
+   }
+   nErr = closedir((DIR *)dir->handle);
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: failed to closedir, errno is %s\n", nErr, strerror(ERRNO));
+   }
+
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_HEADER(apps_std_readdir)(const apps_std_DIR* dir, apps_std_DIRENT* dirent, int *bEOF) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+   struct dirent *odirent;
+
+   if((NULL == dir) || (0 == dir->handle)){
+      return AEE_EBADPARM;
+   }
+   *bEOF = 0;
+   errno = 0;
+   odirent = readdir((DIR *)dir->handle);
+   if(odirent != NULL) {
+      dirent->ino = (int)odirent->d_ino;
+      std_strlcpy(dirent->name, odirent->d_name, sizeof(dirent->name));
+   } else {
+      if(errno == 0) {
+         *bEOF = 1;
+      } else {
+         nErr = -1;
+      }
+   }
+
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_HEADER(apps_std_mkdir)(const char* name, int mode) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+
+   if(NULL == name){
+      return nErr;
+   }
+   nErr = mkdir(name, mode);
+   if(nErr != AEE_SUCCESS){
+      VERIFY_EPRINTF("Error %x: failed to mkdir %s,errno is %s\n", nErr, name, strerror(ERRNO));
+   }
+
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_HEADER(apps_std_rmdir)(const char* name) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS;
+
+   if(NULL == name){
+      return nErr;
+   }
+   nErr = rmdir(name);
+   if(nErr != AEE_SUCCESS){
+      VERIFY_EPRINTF("Error %x: failed to rmdir %s,errno is %s\n", nErr, name, strerror(ERRNO));
+   }
+
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_HEADER(apps_std_stat)(const char* name, apps_std_STAT* ist) __QAIC_IMPL_ATTRIBUTE {
+   int nErr = AEE_SUCCESS, nOpenErr = AEE_SUCCESS, fd = -1;
+   apps_std_FILE ps;
+   struct apps_std_info* sinfo = 0;
+   struct stat st;
+
+   if((NULL == name) || (NULL == ist)) {
+      return AEE_EBADPARM;
+   }
+   VERIFYC(0 == (nOpenErr = apps_std_fopen_with_env("ADSP_LIBRARY_PATH", ";", name, "r", &ps)), AEE_EFOPEN);
+   VERIFYC(0 == (nErr = apps_std_FILE_get(ps, &sinfo)), AEE_EBADFD);
+   VERIFYC(-1 != (fd = fileno(sinfo->u.stream)), AEE_EBADFD);
+   VERIFYC(0 == fstat(fd, &st), AEE_EBADFD);
+   ist->dev = st.st_dev;
+   ist->ino = st.st_ino;
+   ist->mode = st.st_mode;
+   ist->nlink = st.st_nlink;
+   ist->rdev = st.st_rdev;
+   ist->size = st.st_size;
+   ist->atime = (int64)st.st_atim.tv_sec;
+   ist->atimensec = (int64)st.st_atim.tv_nsec;
+   ist->mtime = (int64)st.st_mtim.tv_sec;
+   ist->mtimensec =(int64)st.st_mtim.tv_nsec;
+   ist->ctime = (int64)st.st_ctim.tv_nsec;
+   ist->ctimensec = (int64)st.st_ctim.tv_nsec;
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: failed to stat %s, file open returned %x, errno is %s\n", nErr, name, nOpenErr, strerror(ERRNO));
+   }
+   if (nOpenErr == AEE_SUCCESS) {
+     apps_std_fclose(ps);
+     sinfo = 0;
+   }
+   if(sinfo) {
+      apps_std_FILE_free(sinfo);
+   }
+   return nErr;
+}
+
+__QAIC_HEADER_EXPORT int __QAIC_HEADER(apps_std_ftrunc)(apps_std_FILE sin, int offset) __QAIC_HEADER_ATTRIBUTE {
+   int nErr = 0, fd = -1;
+   struct apps_std_info* sinfo = 0;
+
+   VERIFYC(0 == (nErr = apps_std_FILE_get(sin, &sinfo)), AEE_EBADFD);
+   VERIFYC(-1 != (fd = fileno(sinfo->u.stream)), AEE_EBADFD);
+
+   if(0 != ftruncate(fd, offset)) {
+      return ERRNO;
+   }
+bail:
+   return nErr;
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_std_frename)(const char* oldname, const char* newname) __QAIC_IMPL_ATTRIBUTE {
+  int nErr = AEE_SUCCESS;
+
+  VERIFYC(NULL != oldname && NULL != newname, AEE_EBADPARM);
+  nErr = rename(oldname, newname);
+bail:
+  if(nErr != AEE_SUCCESS) {
+    VERIFY_EPRINTF("Error %x: failed to rename file, errno is %s\n", nErr, strerror(ERRNO));
+  }
+  return nErr;
+}
diff --git a/src/apps_std_skel.c b/src/apps_std_skel.c
new file mode 100644
index 0000000..19944cb
--- /dev/null
+++ b/src/apps_std_skel.c
@@ -0,0 +1,1227 @@
+#ifndef _APPS_STD_SKEL_H
+#define _APPS_STD_SKEL_H
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "apps_std.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#include <string.h>
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _APPS_STD_SLIM_H
+#define _APPS_STD_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[7];
+static const Type* const typeArrays[15] = {&(types[2]),&(types[2]),&(types[2]),&(types[5]),&(types[5]),&(types[2]),&(types[2]),&(types[6]),&(types[6]),&(types[6]),&(types[6]),&(types[6]),&(types[6]),&(types[3]),&(types[4])};
+static const StructType structTypes[3] = {{0x1,&(typeArrays[0]),0x8,0x0,0x8,0x8,0x1,0x8},{0x2,&(typeArrays[13]),0x104,0x0,0x104,0x4,0x1,0x4},{0xd,&(typeArrays[0]),0x60,0x0,0x60,0x8,0x1,0x8}};
+static const SequenceType sequenceTypes[1] = {{&(types[1]),0x0,0x4,0x4,0x0}};
+static const Type types[7] = {{0x1,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x1},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8)},{0x8,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x8},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4},{0xff,{{(const uintptr_t)&(types[0]),(const uintptr_t)0xff}}, 8,0x1},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4},{0x8,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x8}};
+static const Parameter parameters[16] = {{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8),0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,3,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,0,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(types[0]),(const uintptr_t)0x0}}, 9,SLIM_IFPTR32(0x4,0x8),3,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(types[0]),(const uintptr_t)0x0}}, 9,SLIM_IFPTR32(0x4,0x8),0,0},{0x4,{{0,0}}, 3,0x4,0,0},{0x8,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x8,3,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8),3,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(sequenceTypes[0]),0}}, 25,SLIM_IFPTR32(0x4,0x8),3,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,3,0},{0x2,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x2,3,0},{0x1,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x1,3,0},{0x8,{{(const uintptr_t)&(structTypes[0]),0}}, 6,0x8,3,0},{0x8,{{(const uintptr_t)&(structTypes[0]),0}}, 6,0x8,0,0},{0x104,{{(const uintptr_t)&(structTypes[1]),0}}, 6,0x4,3,0},{0x60,{{(const uintptr_t)&(structTypes[2]),0}}, 6,0x8,3,0}};
+static const Parameter* const parameterArrays[44] = {(&(parameters[0])),(&(parameters[0])),(&(parameters[8])),(&(parameters[9])),(&(parameters[10])),(&(parameters[0])),(&(parameters[0])),(&(parameters[0])),(&(parameters[0])),(&(parameters[1])),(&(parameters[2])),(&(parameters[4])),(&(parameters[1])),(&(parameters[1])),(&(parameters[2])),(&(parameters[3])),(&(parameters[1])),(&(parameters[1])),(&(parameters[2])),(&(parameters[0])),(&(parameters[0])),(&(parameters[1])),(&(parameters[13])),(&(parameters[14])),(&(parameters[1])),(&(parameters[0])),(&(parameters[0])),(&(parameters[2])),(&(parameters[0])),(&(parameters[7])),(&(parameters[1])),(&(parameters[2])),(&(parameters[2])),(&(parameters[5])),(&(parameters[0])),(&(parameters[15])),(&(parameters[0])),(&(parameters[12])),(&(parameters[0])),(&(parameters[11])),(&(parameters[2])),(&(parameters[6])),(&(parameters[2])),(&(parameters[1]))};
+static const Method methods[23] = {{REMOTE_SCALARS_MAKEX(0,0,0x3,0x1,0x0,0x0),0x8,0x4,3,3,(&(parameterArrays[7])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x3,0x1,0x0,0x0),0xc,0x4,4,4,(&(parameterArrays[18])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0x4,0x0,1,1,(&(parameterArrays[10])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x2,0x0,0x0),0x8,0x8,6,4,(&(parameterArrays[14])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x1,0x0,0x0),0x8,0x8,5,4,(&(parameterArrays[10])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x2,0x0,0x0),0x8,0x4,5,3,(&(parameterArrays[14])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x0,0x0,0x0),0x8,0x0,3,2,(&(parameterArrays[10])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x4,0x4,2,2,(&(parameterArrays[42])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0xc,0x0,3,3,(&(parameterArrays[31])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x4,0x8,2,2,(&(parameterArrays[40])),0x4,0x8},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x0,0x0,0x0),0x4,0x0,1,1,(&(parameterArrays[0])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x2,0x0,0x0),0x8,0x4,5,3,(&(parameterArrays[28])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x3,0x0,0x0,0x0),0xc,0x0,3,3,(&(parameterArrays[25])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x5,0x1,0x0,0x0),0x10,0x4,5,5,(&(parameterArrays[5])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,255,255,15,15),0xc,0x6,7,5,(&(parameterArrays[0])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x1,0x0,0x0),0x4,0x1,2,2,(&(parameterArrays[38])),0x4,0x1},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x1,0x0,0x0),0x4,0x8,2,2,(&(parameterArrays[36])),0x4,0x8},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0x8,0x0,1,1,(&(parameterArrays[22])),0x8,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x1,0x0,0x0),0x8,0x108,3,3,(&(parameterArrays[22])),0x8,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x0,0x0,0x0),0x8,0x0,2,2,(&(parameterArrays[26])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x1,0x0,0x0),0x4,0x60,2,2,(&(parameterArrays[34])),0x4,0x8},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0x8,0x0,2,2,(&(parameterArrays[31])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x3,0x0,0x0,0x0),0x8,0x0,2,2,(&(parameterArrays[0])),0x4,0x0}};
+static const Method* const methodArrays[34] = {&(methods[0]),&(methods[1]),&(methods[2]),&(methods[2]),&(methods[3]),&(methods[4]),&(methods[5]),&(methods[6]),&(methods[7]),&(methods[8]),&(methods[9]),&(methods[2]),&(methods[7]),&(methods[7]),&(methods[2]),&(methods[10]),&(methods[11]),&(methods[12]),&(methods[10]),&(methods[13]),&(methods[5]),&(methods[14]),&(methods[15]),&(methods[2]),&(methods[10]),&(methods[7]),&(methods[16]),&(methods[17]),&(methods[18]),&(methods[19]),&(methods[10]),&(methods[20]),&(methods[21]),&(methods[22])};
+static const char strings[530] = "get_search_paths_with_env\0fdopen_decrypt\0fopen_with_env\0print_string\0bytesWritten\0fileExists\0maxPathLen\0envvarname\0ctimensec\0mtimensec\0atimensec\0valLenReq\0posLenReq\0bytesRead\0closedir\0numPaths\0unsetenv\0override\0clearerr\0newname\0oldname\0frename\0readdir\0opendir\0fremove\0fsetpos\0fgetpos\0freopen\0ftrunc\0dirent\0handle\0exists\0getenv\0ferror\0rewind\0whence\0offset\0fwrite\0fclose\0fflush\0ctime\0mtime\0atime\0nlink\0rmdir\0mkdir\0fsync\0paths\0fgets\0delim\0fseek\0ftell\0fread\0psout\0fopen\0size\0rdev\0stat\0path\0feof\0flen\0bEOF\0mode\0tsz\0ino\0val\0str\0buf\0sin\0";
+static const uint16_t methodStrings[129] = {476,110,476,506,472,510,501,394,471,466,388,135,382,125,376,115,244,180,306,299,510,110,496,0,104,430,418,184,93,41,104,430,110,501,454,355,526,522,69,496,448,526,522,165,496,284,526,110,501,454,252,110,180,306,424,526,522,496,195,110,514,202,320,110,514,145,436,526,348,341,276,526,272,155,460,110,501,454,236,228,220,292,526,348,406,110,501,175,180,306,26,526,454,82,481,313,327,526,216,486,526,496,491,526,492,442,526,272,268,526,272,400,110,260,110,412,526,193,110,56,518,211,526,334,526,362,526,369,526};
+static const uint16_t methodStringsArrays[34] = {74,45,127,125,40,35,70,108,105,66,102,123,99,96,121,119,62,58,117,29,54,23,93,115,113,90,50,87,16,84,111,0,81,78};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(apps_std_slim) = {34,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_APPS_STD_SLIM_H
+extern int adsp_mmap_fd_getinfo(int, uint32_t *);
+#ifdef __cplusplus
+extern "C" {
+#endif
+static __inline int _skel_method(int (*_pfn)(char*, char*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   char* _in2[1];
+   uint32_t _in2Len[1];
+   uint32_t* _primIn;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((3 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 12);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in1Len[0] > 0) && (_in1[0][(_in1Len[0] - 1)] == 0));
+   _COPY(_in2Len, 0, _primIn, 8, 4);
+   _ASSERT(_nErr, (int)((_praIn[1].buf.nLen / 1)) >= (int)(_in2Len[0]));
+   _in2[0] = _praIn[1].buf.pv;
+   _ASSERT(_nErr, (_in2Len[0] > 0) && (_in2[0][(_in2Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in1, *_in2));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_1(int (*_pfn)(uint32_t, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t _in1[1];
+   uint32_t _in2[1];
+   uint32_t* _primIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 12);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1, 0, _primIn, 4, 4);
+   _COPY(_in2, 0, _primIn, 8, 4);
+   _TRY(_nErr, _pfn(*_in1, *_in2));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_2(int (*_pfn)(char*, uint64_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   uint64_t _rout2[12];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint64_t* _primROut;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 96);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in1Len[0] > 0) && (_in1[0][(_in1Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in1, _rout2));
+   _COPY(_primROut, 0, _rout2, 0, 96);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_invoke(uint32_t _mid, uint32_t _sc, remote_arg* _pra) {
+   switch(_mid)
+   {
+      case 31:
+      return _skel_method_2((void*)__QAIC_IMPL(apps_std_stat), _sc, _pra);
+      case 32:
+      return _skel_method_1((void*)__QAIC_IMPL(apps_std_ftrunc), _sc, _pra);
+      case 33:
+      return _skel_method((void*)__QAIC_IMPL(apps_std_frename), _sc, _pra);
+   }
+   return AEE_EUNSUPPORTED;
+}
+static __inline int _skel_method_3(int (*_pfn)(char*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   uint32_t* _primIn;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 4);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in0));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_4(int (*_pfn)(char*, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   uint32_t _in1[1];
+   uint32_t* _primIn;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _COPY(_in1, 0, _primIn, 4, 4);
+   _TRY(_nErr, _pfn(*_in0, *_in1));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_5(int (*_pfn)(uint64_t*, uint32_t*, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint64_t _in0[1];
+   uint32_t _rout1[65];
+   uint32_t _rout2[1];
+   uint64_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 264);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 8);
+   _TRY(_nErr, _pfn(_in0, _rout1, _rout2));
+   _COPY(_primROut, 0, _rout1, 0, 260);
+   _COPY(_primROut, 260, _rout2, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_6(int (*_pfn)(uint64_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint64_t _in0[1];
+   uint64_t* _primIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 8);
+   _TRY(_nErr, _pfn(_in0));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_7(int (*_pfn)(char*, uint64_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   uint64_t _rout1[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint64_t* _primROut;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 4);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 8);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in0, _rout1));
+   _COPY(_primROut, 0, _rout1, 0, 8);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_8(int (*_pfn)(uint32_t, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t _rout1[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 4);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 4);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _TRY(_nErr, _pfn(*_in0, _rout1));
+   _COPY(_primROut, 0, _rout1, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_9(int (*_pfn)(uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t* _primIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 4);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _TRY(_nErr, _pfn(*_in0));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_10(int (*_pfn)(char*, uint8_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   uint8_t _rout1[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint8_t* _primROut;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 4);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 1);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in0, _rout1));
+   _COPY(_primROut, 0, _rout1, 0, 1);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_pack(remote_arg* _praROutPost, remote_arg* _ppraROutPost[1], void* _primROut, char* _rout0[1], uint32_t _rout0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praROutPostStart = _praROutPost;
+   remote_arg** _ppraROutPostStart = _ppraROutPost;
+   _ppraROutPost = &_praROutPost;
+   _ppraROutPostStart[0] += (_praROutPost - _praROutPostStart) +1;
+   return _nErr;
+}
+static __inline int _skel_unpack(_allocator* _al, remote_arg* _praIn, remote_arg* _ppraIn[1], remote_arg* _praROut, remote_arg* _ppraROut[1], remote_arg* _praHIn, remote_arg* _ppraHIn[1], remote_arg* _praHROut, remote_arg* _ppraHROut[1], void* _primIn, void* _primROut, char* _rout0[1], uint32_t _rout0Len[1]) {
+   int _nErr = 0;
+   remote_arg* _praInStart = _praIn;
+   remote_arg** _ppraInStart = _ppraIn;
+   remote_arg* _praROutStart = _praROut;
+   remote_arg** _ppraROutStart = _ppraROut;
+   _ppraIn = &_praIn;
+   _ppraROut = &_praROut;
+   _COPY(_rout0Len, 0, _primIn, 0, 4);
+   _ASSERT(_nErr, (int)((_praROut[0].buf.nLen / 1)) >= (int)(_rout0Len[0]));
+   _rout0[0] = _praROut[0].buf.pv;
+   _ppraInStart[0] += (_praIn - _praInStart) + 0;
+   _ppraROutStart[0] += (_praROut - _praROutStart) +1;
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_11(int (*_pfn)(char*, char*, void*, uint32_t, uint32_t*, uint16_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   void* _rout2[1];
+   uint32_t _rout2Len[1];
+   uint32_t _rout3[1];
+   uint16_t _rout4[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   int _numInH[1];
+   int _numROut[1];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   remote_arg* _praROutPost;
+   remote_arg** _ppraROutPost = &_praROutPost;
+   _allocator _al[1] = {{0}};
+   remote_arg** _ppraIn = &_praIn;
+   remote_arg** _ppraROut = &_praROut;
+   remote_arg* _praHIn = 0;
+   remote_arg** _ppraHIn = &_praHIn;
+   remote_arg* _praHROut = 0;
+   remote_arg** _ppraHROut = &_praHROut;
+   char* _seq_primIn2;
+   char* _seq_nat2;
+   int _ii;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((4 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 12);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 6);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _numInH[0] = REMOTE_SCALARS_INHANDLES(_sc);
+   _numROut[0] = REMOTE_SCALARS_OUTBUFS(_sc);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _praROutPost = _praROut;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _ASSERT(_nErr, (int)((_praIn[1].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[1].buf.pv;
+   _ASSERT(_nErr, (_in1Len[0] > 0) && (_in1[0][(_in1Len[0] - 1)] == 0));
+   _COPY(_rout2Len, 0, _primIn, 8, 4);
+   _allocator_init(_al, 0, 0);
+   if(_praHIn == 0)
+   {
+      _praHIn = ((_praROut + _numROut[0]) + 1);
+   }
+   if(_praHROut == 0)
+      (_praHROut = _praHIn + _numInH[0] + 0);
+   _ASSERT(_nErr, (int)((_praIn[2].buf.nLen / 4)) >= (int)(_rout2Len[0]));
+   _ALLOCATE(_nErr, _al, (_rout2Len[0] * SLIM_IFPTR32(8, 16)), SLIM_IFPTR32(4, 8), _rout2[0]);
+   for(_ii = 0, _seq_primIn2 = (char*)_praIn[2].buf.pv, _seq_nat2 = (char*)_rout2[0];_ii < (int)_rout2Len[0];++_ii, _seq_primIn2 = (_seq_primIn2 + 4), _seq_nat2 = (_seq_nat2 + SLIM_IFPTR32(8, 16)))
+   {
+      _TRY(_nErr, _skel_unpack(_al, (_praIn + 3), _ppraIn, (_praROut + 0), _ppraROut, _praHIn, _ppraHIn, _praHROut, _ppraHROut, _seq_primIn2, 0, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat2)[0]), (char**)&(((uint64_t*)_seq_nat2)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat2)[1]), (uint32_t*)&(((uint32_t*)_seq_nat2)[2]))));
+   }
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_rout2, *_rout2Len, _rout3, _rout4));
+   for(_ii = 0, _seq_nat2 = (char*)_rout2[0];_ii < (int)_rout2Len[0];++_ii, _seq_nat2 = (_seq_nat2 + SLIM_IFPTR32(8, 16)))
+   {
+      _TRY(_nErr, _skel_pack((_praROutPost + 0), _ppraROutPost, 0, SLIM_IFPTR32((char**)&(((uint32_t*)_seq_nat2)[0]), (char**)&(((uint64_t*)_seq_nat2)[0])), SLIM_IFPTR32((uint32_t*)&(((uint32_t*)_seq_nat2)[1]), (uint32_t*)&(((uint32_t*)_seq_nat2)[2]))));
+   }
+   _COPY(_primROut, 0, _rout3, 0, 4);
+   _COPY(_primROut, 4, _rout4, 0, 2);
+   _CATCH(_nErr) {}
+   _allocator_deinit(_al);
+   return _nErr;
+}
+static __inline int _skel_method_12(int (*_pfn)(uint32_t, char*, uint32_t, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _rout1[1];
+   uint32_t _rout1Len[1];
+   uint32_t _rout2[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 2) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 4);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_rout1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _ASSERT(_nErr, (int)((_praROut[0].buf.nLen / 1)) >= (int)(_rout1Len[0]));
+   _rout1[0] = _praROut[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, *_rout1, *_rout1Len, _rout2));
+   _COPY(_primROut, 0, _rout2, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_13(int (*_pfn)(char*, char*, char*, char*, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   char* _in2[1];
+   uint32_t _in2Len[1];
+   char* _in3[1];
+   uint32_t _in3Len[1];
+   uint32_t _rout4[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((5 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 16);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 4);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _ASSERT(_nErr, (int)((_praIn[1].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[1].buf.pv;
+   _ASSERT(_nErr, (_in1Len[0] > 0) && (_in1[0][(_in1Len[0] - 1)] == 0));
+   _COPY(_in2Len, 0, _primIn, 8, 4);
+   _ASSERT(_nErr, (int)((_praIn[2].buf.nLen / 1)) >= (int)(_in2Len[0]));
+   _in2[0] = _praIn[2].buf.pv;
+   _ASSERT(_nErr, (_in2Len[0] > 0) && (_in2[0][(_in2Len[0] - 1)] == 0));
+   _COPY(_in3Len, 0, _primIn, 12, 4);
+   _ASSERT(_nErr, (int)((_praIn[3].buf.nLen / 1)) >= (int)(_in3Len[0]));
+   _in3[0] = _praIn[3].buf.pv;
+   _ASSERT(_nErr, (_in3Len[0] > 0) && (_in3[0][(_in3Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in2, *_in3, _rout4));
+   _COPY(_primROut, 0, _rout4, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_14(int (*_pfn)(char*, char*, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   uint32_t _in2[1];
+   uint32_t* _primIn;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((3 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 12);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _ASSERT(_nErr, (int)((_praIn[1].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[1].buf.pv;
+   _ASSERT(_nErr, (_in1Len[0] > 0) && (_in1[0][(_in1Len[0] - 1)] == 0));
+   _COPY(_in2, 0, _primIn, 8, 4);
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in2));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_15(int (*_pfn)(char*, char*, uint32_t, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   char* _rout1[1];
+   uint32_t _rout1Len[1];
+   uint32_t _rout2[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 2) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 4);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _COPY(_rout1Len, 0, _primIn, 4, 4);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _ASSERT(_nErr, (int)((_praROut[0].buf.nLen / 1)) >= (int)(_rout1Len[0]));
+   _rout1[0] = _praROut[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, *_rout1, *_rout1Len, _rout2));
+   _COPY(_primROut, 0, _rout2, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_16(int (*_pfn)(uint32_t, uint64_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint64_t _rout1[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint64_t* _primROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 4);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 8);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _TRY(_nErr, _pfn(*_in0, _rout1));
+   _COPY(_primROut, 0, _rout1, 0, 8);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_17(int (*_pfn)(uint32_t, uint32_t, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   uint32_t _in1[1];
+   uint32_t _in2[1];
+   uint32_t* _primIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 12);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1, 0, _primIn, 4, 4);
+   _COPY(_in2, 0, _primIn, 8, 4);
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in2));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_18(int (*_pfn)(uint32_t, char*, uint32_t), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   uint32_t* _primIn;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 0) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in1Len));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_19(int (*_pfn)(uint32_t, char*, uint32_t, uint32_t*, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   uint32_t _rout2[1];
+   uint32_t _rout3[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((2 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 8);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in1Len, _rout2, _rout3));
+   _COPY(_primROut, 0, _rout2, 0, 4);
+   _COPY(_primROut, 4, _rout3, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_20(int (*_pfn)(uint32_t, char*, uint32_t, uint32_t*, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _rout1[1];
+   uint32_t _rout1Len[1];
+   uint32_t _rout2[1];
+   uint32_t _rout3[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((1 + 2) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 8);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_rout1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _ASSERT(_nErr, (int)((_praROut[0].buf.nLen / 1)) >= (int)(_rout1Len[0]));
+   _rout1[0] = _praROut[0].buf.pv;
+   _TRY(_nErr, _pfn(*_in0, *_rout1, *_rout1Len, _rout2, _rout3));
+   _COPY(_primROut, 0, _rout2, 0, 4);
+   _COPY(_primROut, 4, _rout3, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_21(int (*_pfn)(uint32_t, char*, char*, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   uint32_t _in0[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   char* _in2[1];
+   uint32_t _in2Len[1];
+   uint32_t _rout3[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((3 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 12);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 4);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0, 0, _primIn, 0, 4);
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in1Len[0] > 0) && (_in1[0][(_in1Len[0] - 1)] == 0));
+   _COPY(_in2Len, 0, _primIn, 8, 4);
+   _ASSERT(_nErr, (int)((_praIn[1].buf.nLen / 1)) >= (int)(_in2Len[0]));
+   _in2[0] = _praIn[1].buf.pv;
+   _ASSERT(_nErr, (_in2Len[0] > 0) && (_in2[0][(_in2Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in0, *_in1, *_in2, _rout3));
+   _COPY(_primROut, 0, _rout3, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+static __inline int _skel_method_22(int (*_pfn)(char*, char*, uint32_t*), uint32_t _sc, remote_arg* _pra) {
+   remote_arg* _praEnd;
+   char* _in0[1];
+   uint32_t _in0Len[1];
+   char* _in1[1];
+   uint32_t _in1Len[1];
+   uint32_t _rout2[1];
+   uint32_t* _primIn;
+   int _numIn[1];
+   uint32_t* _primROut;
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _praEnd = ((_pra + REMOTE_SCALARS_INBUFS(_sc)) + REMOTE_SCALARS_OUTBUFS(_sc) + REMOTE_SCALARS_INHANDLES(_sc) + REMOTE_SCALARS_OUTHANDLES(_sc));
+   _ASSERT(_nErr, (_pra + ((3 + 1) + (((0 + 0) + 0) + 0))) <= _praEnd);
+   _numIn[0] = (REMOTE_SCALARS_INBUFS(_sc) - 1);
+   _ASSERT(_nErr, _pra[0].buf.nLen >= 8);
+   _primIn = _pra[0].buf.pv;
+   _ASSERT(_nErr, _pra[(_numIn[0] + 1)].buf.nLen >= 4);
+   _primROut = _pra[(_numIn[0] + 1)].buf.pv;
+   _COPY(_in0Len, 0, _primIn, 0, 4);
+   _praIn = (_pra + 1);
+   _ASSERT(_nErr, (int)((_praIn[0].buf.nLen / 1)) >= (int)(_in0Len[0]));
+   _in0[0] = _praIn[0].buf.pv;
+   _ASSERT(_nErr, (_in0Len[0] > 0) && (_in0[0][(_in0Len[0] - 1)] == 0));
+   _COPY(_in1Len, 0, _primIn, 4, 4);
+   _ASSERT(_nErr, (int)((_praIn[1].buf.nLen / 1)) >= (int)(_in1Len[0]));
+   _in1[0] = _praIn[1].buf.pv;
+   _ASSERT(_nErr, (_in1Len[0] > 0) && (_in1[0][(_in1Len[0] - 1)] == 0));
+   _TRY(_nErr, _pfn(*_in0, *_in1, _rout2));
+   _COPY(_primROut, 0, _rout2, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_SKEL_EXPORT int __QAIC_SKEL(apps_std_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_SKEL_ATTRIBUTE {
+   switch(REMOTE_SCALARS_METHOD(_sc))
+   {
+      case 0:
+      return _skel_method_22((void*)__QAIC_IMPL(apps_std_fopen), _sc, _pra);
+      case 1:
+      return _skel_method_21((void*)__QAIC_IMPL(apps_std_freopen), _sc, _pra);
+      case 2:
+      return _skel_method_9((void*)__QAIC_IMPL(apps_std_fflush), _sc, _pra);
+      case 3:
+      return _skel_method_9((void*)__QAIC_IMPL(apps_std_fclose), _sc, _pra);
+      case 4:
+      return _skel_method_20((void*)__QAIC_IMPL(apps_std_fread), _sc, _pra);
+      case 5:
+      return _skel_method_19((void*)__QAIC_IMPL(apps_std_fwrite), _sc, _pra);
+      case 6:
+      return _skel_method_12((void*)__QAIC_IMPL(apps_std_fgetpos), _sc, _pra);
+      case 7:
+      return _skel_method_18((void*)__QAIC_IMPL(apps_std_fsetpos), _sc, _pra);
+      case 8:
+      return _skel_method_8((void*)__QAIC_IMPL(apps_std_ftell), _sc, _pra);
+      case 9:
+      return _skel_method_17((void*)__QAIC_IMPL(apps_std_fseek), _sc, _pra);
+      case 10:
+      return _skel_method_16((void*)__QAIC_IMPL(apps_std_flen), _sc, _pra);
+      case 11:
+      return _skel_method_9((void*)__QAIC_IMPL(apps_std_rewind), _sc, _pra);
+      case 12:
+      return _skel_method_8((void*)__QAIC_IMPL(apps_std_feof), _sc, _pra);
+      case 13:
+      return _skel_method_8((void*)__QAIC_IMPL(apps_std_ferror), _sc, _pra);
+      case 14:
+      return _skel_method_9((void*)__QAIC_IMPL(apps_std_clearerr), _sc, _pra);
+      case 15:
+      return _skel_method_3((void*)__QAIC_IMPL(apps_std_print_string), _sc, _pra);
+      case 16:
+      return _skel_method_15((void*)__QAIC_IMPL(apps_std_getenv), _sc, _pra);
+      case 17:
+      return _skel_method_14((void*)__QAIC_IMPL(apps_std_setenv), _sc, _pra);
+      case 18:
+      return _skel_method_3((void*)__QAIC_IMPL(apps_std_unsetenv), _sc, _pra);
+      case 19:
+      return _skel_method_13((void*)__QAIC_IMPL(apps_std_fopen_with_env), _sc, _pra);
+      case 20:
+      return _skel_method_12((void*)__QAIC_IMPL(apps_std_fgets), _sc, _pra);
+      case 21:
+      return _skel_method_11((void*)__QAIC_IMPL(apps_std_get_search_paths_with_env), _sc, _pra);
+      case 22:
+      return _skel_method_10((void*)__QAIC_IMPL(apps_std_fileExists), _sc, _pra);
+      case 23:
+      return _skel_method_9((void*)__QAIC_IMPL(apps_std_fsync), _sc, _pra);
+      case 24:
+      return _skel_method_3((void*)__QAIC_IMPL(apps_std_fremove), _sc, _pra);
+      case 25:
+      return _skel_method_8((void*)__QAIC_IMPL(apps_std_fdopen_decrypt), _sc, _pra);
+      case 26:
+      return _skel_method_7((void*)__QAIC_IMPL(apps_std_opendir), _sc, _pra);
+      case 27:
+      return _skel_method_6((void*)__QAIC_IMPL(apps_std_closedir), _sc, _pra);
+      case 28:
+      return _skel_method_5((void*)__QAIC_IMPL(apps_std_readdir), _sc, _pra);
+      case 29:
+      return _skel_method_4((void*)__QAIC_IMPL(apps_std_mkdir), _sc, _pra);
+      case 30:
+      return _skel_method_3((void*)__QAIC_IMPL(apps_std_rmdir), _sc, _pra);
+      case 31:
+      {
+         uint32_t* _mid;
+         if(REMOTE_SCALARS_INBUFS(_sc) < 1 || _pra[0].buf.nLen < 4) { return AEE_EBADPARM; }
+         _mid = (uint32_t*)_pra[0].buf.pv;
+         return _skel_invoke(*_mid, _sc, _pra);
+      }
+   }
+   return AEE_EUNSUPPORTED;
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_APPS_STD_SKEL_H
diff --git a/src/atomic.c b/src/atomic.c
new file mode 100644
index 0000000..cfe1067
--- /dev/null
+++ b/src/atomic.c
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "AEEatomic.h"
+
+uint32 atomic_Add(uint32 * volatile puDest, int nAdd) {
+   uint32 previous;
+   uint32 current;
+   do {
+      current = *puDest;
+      previous = atomic_CompareAndExchange(puDest, current + nAdd, current);
+   } while(previous != current);
+   return (current + nAdd);
+}
+
+uint32 atomic_Exchange(uint32* volatile puDest, uint32 uVal) {
+   uint32 previous;
+   uint32 current;
+   do {
+      current = *puDest;
+      previous = atomic_CompareAndExchange(puDest, uVal, current);
+   } while(previous != current);
+   return previous;
+}
+
+uint32 atomic_CompareOrAdd(uint32* volatile puDest, uint32 uCompare, int nAdd) {
+   uint32 previous;
+   uint32 current;
+   uint32 result;
+   do {
+      current = *puDest;
+      previous = current;
+      result = current;
+      if(current != uCompare) {
+         previous = atomic_CompareAndExchange(puDest, current + nAdd, current);
+         if(previous == current) {
+            result = current + nAdd;
+         }
+      }
+   } while(previous != current);
+   return result;
+}
+
diff --git a/src/cae.c b/src/cae.c
new file mode 100644
index 0000000..2711170
--- /dev/null
+++ b/src/cae.c
@@ -0,0 +1,88 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "AEEatomic.h"
+
+#ifdef _WIN32
+#include "Windows.h"
+uint32 atomic_CompareAndExchange(uint32 * volatile puDest, uint32 uExchange, uint32 uCompare) {
+   C_ASSERT(sizeof(LONG) == sizeof(uint32));
+   return (uint32)InterlockedCompareExchange((LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
+}
+uintptr_t atomic_CompareAndExchangeUP(uintptr_t * volatile puDest, uintptr_t uExchange, uintptr_t uCompare) {
+   C_ASSERT(sizeof(uintptr_t) == sizeof(void*));
+   return (uintptr_t)InterlockedCompareExchangePointer((void**)puDest, (void*)uExchange, (void*)uCompare);
+}
+#elif __hexagon__
+
+#ifndef C_ASSERT
+#define C_ASSERT(test) \
+    switch(0) {\
+      case 0:\
+      case test:;\
+    }
+#endif
+
+static inline unsigned int
+qurt_atomic_compare_val_and_set(unsigned int* target,
+                                unsigned int old_val,
+                                unsigned int new_val)
+{
+   unsigned int current_val;
+
+   __asm__ __volatile__(
+       "1:     %0 = memw_locked(%2)\n"
+       "       p0 = cmp.eq(%0, %3)\n"
+       "       if !p0 jump 2f\n"
+       "       memw_locked(%2, p0) = %4\n"
+       "       if !p0 jump 1b\n"
+       "2:\n"
+       : "=&r" (current_val),"+m" (*target)
+       : "r" (target), "r" (old_val), "r" (new_val)
+       : "p0");
+
+   return current_val;
+}
+uint32 atomic_CompareAndExchange(uint32 * volatile puDest, uint32 uExchange, uint32 uCompare) {
+   return (uint32)qurt_atomic_compare_val_and_set((unsigned int*)puDest, uCompare, uExchange);
+}
+uintptr_t atomic_CompareAndExchangeUP(uintptr_t * volatile puDest, uintptr_t uExchange, uintptr_t uCompare) {
+   C_ASSERT(sizeof(uintptr_t) == sizeof(uint32));
+   return (uint32)atomic_CompareAndExchange((uint32*)puDest, (uint32)uExchange, (uint32)uCompare);
+}
+#elif __GNUC__
+uint32 atomic_CompareAndExchange(uint32 * volatile puDest, uint32 uExchange, uint32 uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+uint64 atomic_CompareAndExchange64(uint64 * volatile puDest, uint64 uExchange, uint64 uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+uintptr_t atomic_CompareAndExchangeUP(uintptr_t * volatile puDest, uintptr_t uExchange, uintptr_t uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+#endif //compare and exchange
diff --git a/src/cdsprpcd.c b/src/cdsprpcd.c
new file mode 100644
index 0000000..759d297
--- /dev/null
+++ b/src/cdsprpcd.c
@@ -0,0 +1,71 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 VERIFY_PRINT_ERROR
+#define VERIFY_PRINT_ERROR
+#endif
+
+#include <stdio.h>
+#include <dlfcn.h>
+#include <unistd.h>
+#include "verify.h"
+
+
+#ifndef CDSP_DEFAULT_LISTENER_NAME
+#define CDSP_DEFAULT_LISTENER_NAME "libcdsp_default_listener.so"
+#endif
+
+typedef int (*adsp_default_listener_start_t)(int argc, char *argv[]);
+
+int main(int argc, char *argv[]) {
+
+  int nErr = 0;
+  void *cdsphandler = NULL;
+  adsp_default_listener_start_t listener_start;
+
+  VERIFY_EPRINTF("cdsp daemon starting");
+  while (1) {
+    if(NULL != (cdsphandler = dlopen(CDSP_DEFAULT_LISTENER_NAME, RTLD_NOW))) {
+      if(NULL != (listener_start =
+        (adsp_default_listener_start_t)dlsym(cdsphandler, "adsp_default_listener_start"))) {
+        VERIFY_IPRINTF("cdsp_default_listener_start called");
+        listener_start(argc, argv);
+      }
+      if(0 != dlclose(cdsphandler)) {
+        VERIFY_EPRINTF("dlclose failed");
+      }
+    } else {
+      VERIFY_EPRINTF("cdsp daemon error %s", dlerror());
+    }
+    VERIFY_EPRINTF("cdsp daemon will restart after 100ms...");
+    usleep(100000);
+  }
+  VERIFY_EPRINTF("cdsp daemon exiting %x", nErr);
+bail:
+  return nErr;
+}
diff --git a/src/fastrpc_apps_user.c b/src/fastrpc_apps_user.c
new file mode 100644
index 0000000..328dfa0
--- /dev/null
+++ b/src/fastrpc_apps_user.c
@@ -0,0 +1,1915 @@
+/*
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/time.h>
+#include <errno.h>
+#include <pthread.h>
+
+#define FARF_ERROR 1
+//#define FARF_HIGH 1
+#include "HAP_farf.h"
+#include "verify.h"
+#include "remote_priv.h"
+#include "shared.h"
+#include "fastrpc_internal.h"
+#include "fastrpc_apps_user.h"
+#include "adsp_current_process.h"
+#include "adsp_current_process1.h"
+#include "adspmsgd_adsp1.h"
+#include "remotectl.h"
+#include "rpcmem.h"
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+#include "AEEQList.h"
+#include "apps_std.h"
+#include "platform_libs.h"
+#include "fastrpc_perf.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <errno.h>
+
+#ifndef _WIN32
+#include <pthread.h>
+#include <sys/inotify.h>
+#include <sys/eventfd.h>
+#include <poll.h>
+#include <sys/mman.h>
+#endif // __WIN32
+
+#ifndef INT_MAX
+#define INT_MAX (int)(-1)
+#endif
+
+#define ADSPRPC_DEVICE "/dev/fastrpc-adsp"
+#define SDSPRPC_DEVICE "/dev/fastrpc-sdsp"
+#define MDSPRPC_DEVICE "/dev/fastrpc-mdsp"
+#define CDSPRPC_DEVICE "/dev/fastrpc-cdsp"
+
+/* Secure and default device nodes */
+#define SECURE_DEVICE "/dev/fastrpc-adsp-secure"
+#define DEFAULT_DEVICE "/dev/fastrpc-adsp"
+
+#define INVALID_DOMAIN_ID -1
+#define INVALID_HANDLE (remote_handle64)(-1)
+#define INVALID_KEY    (pthread_key_t)(-1)
+
+#define MAX_DMA_HANDLES 256
+
+#define FASTRPC_TRACE_INVOKE_START "fastrpc_trace_invoke_start"
+#define FASTRPC_TRACE_INVOKE_END   "fastrpc_trace_invoke_end"
+#define FASTRPC_TRACE_LOG(k, handle, sc) if(fastrpc_trace == 1 && !IS_STATIC_HANDLE(handle)) { \
+                                            FARF(ALWAYS, "%s: sc 0x%x", (k), (sc)); } \
+
+#define FASTRPC_MODE_DEBUG			(0x1)
+#define FASTRPC_MODE_PTRACE			(0x2)
+#define FASTRPC_MODE_CRC			(0x4)
+#define FASTRPC_MODE_ADAPTIVE_QOS	(0x10)
+
+#define FASTRPC_DISABLE_QOS		0
+#define FASTRPC_PM_QOS			1
+#define FASTRPC_ADAPTIVE_QOS	2
+
+/* FastRPC mode for Unsigned module */
+#define FASTRPC_MODE_UNSIGNED_MODULE (0x8)
+
+#define M_CRCLIST (64)
+#define IS_DEBUG_MODE_ENABLED(var) (var & FASTRPC_MODE_DEBUG)
+#define IS_CRC_CHECK_ENABLED(var)  (var & FASTRPC_MODE_CRC)
+#define POLY32 0x04C11DB7	// G(x) = x^32+x^26+x^23+x^22+x^16+x^12
+                                // +x^11+x^10+x^8+x^7+x^5+x^4+x^2+x+1
+
+#define FASTRPC_LATENCY_START      (1)
+#define FASTRPC_LATENCY_STOP       (0)
+#define FASTRPC_LATENCY_EXIT       (2)
+#define FASTRPC_LATENCY_VOTE_ON    (1)
+#define FASTRPC_LATENCY_VOTE_OFF   (0)
+#define FASTRPC_LATENCY_WAIT_TIME  (1)
+
+#ifdef ANDROID_P
+#define FASTRPC_PROP_PROCESS  "vendor.fastrpc.process.attrs"
+#define FASTRPC_PROP_TRACE    "vendor.fastrpc.debug.trace"
+#define FASTRPC_PROP_TESTSIG  "vendor.fastrpc.debug.testsig"
+#else
+#define FASTRPC_PROP_PROCESS  "fastrpc.process.attrs"
+#define FASTRPC_PROP_TRACE    "fastrpc.debug.trace"
+#define FASTRPC_PROP_TESTSIG  "fastrpc.debug.testsig"
+#endif
+
+#define DEFAULT_UTHREAD_PRIORITY	0xC0
+#define DEFAULT_UTHREAD_STACK_SIZE	16*1024
+
+/* Shell prefix for signed and unsigned */
+const char* const SIGNED_SHELL = "fastrpc_shell_";
+const char* const UNSIGNED_SHELL = "fastrpc_shell_unsigned_";
+
+struct fastrpc_latency {
+	int adaptive_qos;
+	int state;
+	int exit;
+	int invoke;
+	int vote;
+	int dev;
+	int wait_time;
+	int latency;
+	pthread_t thread;
+	pthread_mutex_t mut;
+	pthread_mutex_t wmut;
+	pthread_cond_t cond;
+};
+
+struct fastrpc_thread_params {
+	uint32_t prio;
+	uint32_t stack_size;
+	int reqID;
+	pthread_t thread;
+};
+
+struct mem_to_fd {
+   QNode qn;
+   void* buf;
+   int size;
+   int fd;
+   int nova;
+   int attr;
+   int refcount;
+};
+
+struct mem_to_fd_list {
+   QList ql;
+   pthread_mutex_t mut;
+};
+
+struct dma_handle_info {
+   int fd;
+   int len;
+   int used;
+   uint32_t attr;
+};
+
+struct handle_info {
+   QNode qn;
+   struct handle_list *hlist;
+   remote_handle64 local;
+   remote_handle64 remote;
+};
+
+struct handle_list {
+	QList ql;
+	pthread_mutex_t mut;
+	pthread_mutex_t init;
+	int dsppd;
+	char *dsppdname;
+	int domainsupport;
+	int nondomainsupport;
+	int kmem_support;
+	int dev;
+	int initialized;
+	int setmode;
+	uint32_t mode;
+	uint32_t info;
+	void* pdmem;
+	remote_handle64 cphandle;
+	remote_handle64 msghandle;
+	int procattrs;
+	struct fastrpc_latency qos;
+	struct fastrpc_thread_params th_params;
+	int unsigned_module;
+};
+
+static struct mem_to_fd_list fdlist;
+static struct handle_list *hlist = 0;
+static struct dma_handle_info dhandles[MAX_DMA_HANDLES];
+static int dma_handle_count = 0;
+static pthread_key_t tlsKey = INVALID_KEY;
+
+static int fastrpc_trace = 0;
+
+extern int listener_android_domain_init(int domain);
+extern void listener_android_domain_deinit(int domain);
+extern int initFileWatcher(int domain);
+extern void deinitFileWatcher(int domain);
+static int open_dev(int domain);
+static void domain_deinit(int domain);
+static int __attribute__((constructor)) fastrpc_init_once(void);
+remote_handle64 get_adsp_current_process1_handle(int domain);
+remote_handle64 get_adspmsgd_adsp1_handle(int domain);
+static int remote_unmap_fd(void *buf, int size, int fd, int attr);
+
+static uint32_t crc_table[256];
+
+static void GenCrc32Tab(uint32_t GenPoly, uint32_t *crctab)
+{
+   uint32_t crc;
+   int i, j;
+
+   for (i = 0; i < 256; i++) {
+       crc = i<<24;
+       for (j = 0; j <8; j++) {
+           crc = (crc << 1) ^ (crc & 0x80000000 ? GenPoly : 0);
+       }
+       crctab[i] = crc;
+   }
+}
+
+static uint32_t crc32_lut(unsigned char *data, int nbyte, uint32_t *crctab)
+{
+   uint32_t crc = 0;
+   if (!data || !crctab)
+      return 0;
+
+   while(nbyte--) {
+       crc = (crc<<8) ^ crctab[(crc>>24) ^ *data++];
+   }
+   return crc;
+}
+
+int fastrpc_latency_refinc(struct fastrpc_latency *qp) {
+    int nErr = 0;
+
+    if (qp == NULL || qp->state == FASTRPC_LATENCY_STOP)
+       goto bail;
+    qp->invoke++;
+    if (qp->vote == FASTRPC_LATENCY_VOTE_OFF) {
+       pthread_mutex_lock(&qp->wmut);
+       pthread_cond_signal(&qp->cond);
+       pthread_mutex_unlock(&qp->wmut);
+    }
+bail:
+    return 0;
+}
+
+static void* fastrpc_latency_thread_handler(void* arg) {
+   FARF(ALWAYS, "Unsupported: rpc latency thread exited");
+   return NULL;
+}
+
+int fastrpc_latency_init(int dev, struct fastrpc_latency *qos) {
+   int i, nErr = 0;
+
+   VERIFY(qos && dev != -1);
+
+   qos->dev = dev;
+   qos->state = FASTRPC_LATENCY_STOP;
+   qos->thread = 0;
+   qos->wait_time = FASTRPC_LATENCY_WAIT_TIME;
+   pthread_mutex_init(&qos->mut, 0);
+   pthread_mutex_init(&qos->wmut, 0);
+   pthread_cond_init(&qos->cond, NULL);
+bail:
+   return nErr;
+}
+
+int fastrpc_latency_deinit(struct fastrpc_latency *qos) {
+   int nErr = 0;
+
+   VERIFY(qos);
+   if (qos->state == FASTRPC_LATENCY_START) {
+      pthread_mutex_lock(&qos->wmut);
+      qos->exit = FASTRPC_LATENCY_EXIT;
+      pthread_cond_signal(&qos->cond);
+      pthread_mutex_unlock(&qos->wmut);
+      if(qos->thread) {
+         pthread_join(qos->thread, 0);
+         qos->thread = 0;
+         FARF(ALWAYS, "latency thread joined");
+      }
+      qos->state = FASTRPC_LATENCY_STOP;
+      pthread_mutex_destroy(&qos->mut);
+      pthread_mutex_destroy(&qos->wmut);
+   }
+bail:
+   return 0;
+}
+
+/* Thread function that will be invoked to update remote user PD parameters */
+static void *fastrpc_set_remote_uthread_params(void *arg)
+{
+	int nErr = AEE_SUCCESS, paramsLen = 2;
+	struct fastrpc_thread_params *th_params = (struct fastrpc_thread_params*)arg;
+
+	VERIFY(th_params != NULL);
+	VERIFY(AEE_SUCCESS == (nErr = remotectl_set_param(th_params->reqID, (uint32_t*)th_params, paramsLen)));
+bail:
+	if (nErr != AEE_SUCCESS)
+		FARF(ERROR, "Error 0x%x: setting remote user thread parameters failed !", nErr);
+	return NULL;
+}
+
+void *remote_register_fd_attr(int fd, int size, int attr) {
+   int nErr = AEE_SUCCESS;
+   void *po = NULL;
+   void *buf = (void*)-1;
+   struct mem_to_fd* tofd = 0;
+
+   VERIFY(!fastrpc_init_once());
+   VERIFYC(NULL != (tofd = calloc(1, sizeof(*tofd))), AEE_ENOMEMORY);
+   QNode_CtorZ(&tofd->qn);
+   VERIFYC((void*)-1 != (buf = mmap(0, size, PROT_NONE, MAP_ANONYMOUS|MAP_PRIVATE, -1, 0)), AEE_EMMAP);
+   tofd->buf = buf;
+   tofd->size = size;
+   tofd->fd = fd;
+   tofd->nova = 1;
+   tofd->attr = attr;
+
+   pthread_mutex_lock(&fdlist.mut);
+   QList_AppendNode(&fdlist.ql, &tofd->qn);
+   pthread_mutex_unlock(&fdlist.mut);
+
+   tofd = 0;
+   po = buf;
+   buf = (void*)-1;
+bail:
+   if(buf != (void*)-1)
+      munmap(buf, size);
+   if(tofd)
+   {
+      free(tofd);
+      tofd = NULL;
+   }
+   if(nErr != AEE_SUCCESS) {
+	FARF(ERROR,"Error %x: remote register fd fails for fd %x, size %x\n", nErr, fd, size);
+   }
+   return po;
+}
+
+void *remote_register_fd(int fd, int size) {
+   return remote_register_fd_attr(fd, size, 0);
+}
+
+static void remote_register_buf_common(void* buf, int size, int fd, int attr) {
+   int nErr = 0;
+   VERIFY(!fastrpc_init_once());
+   if(fd != -1) {
+      struct mem_to_fd* tofd;
+      int fdfound = 0;
+      QNode* pn, *pnn;
+
+      pthread_mutex_lock(&fdlist.mut);
+      QLIST_NEXTSAFE_FOR_ALL(&fdlist.ql, pn, pnn) {
+         tofd = STD_RECOVER_REC(struct mem_to_fd, qn, pn);
+         if(tofd->buf == buf && tofd->size == size && tofd->fd == fd) {
+            fdfound = 1;
+            if(attr)
+               tofd->attr = attr;
+            tofd->refcount++;
+            break;
+         }
+      }
+      pthread_mutex_unlock(&fdlist.mut);
+      if(!fdfound) {
+         VERIFYC(NULL != (tofd = calloc(1, sizeof(*tofd))), AEE_ENOMEMORY);
+         QNode_CtorZ(&tofd->qn);
+         tofd->buf = buf;
+         tofd->size = size;
+         tofd->fd = fd;
+         if (attr)
+            tofd->attr = attr;
+         tofd->refcount++;
+         pthread_mutex_lock(&fdlist.mut);
+         QList_AppendNode(&fdlist.ql, &tofd->qn);
+         pthread_mutex_unlock(&fdlist.mut);
+      }
+   } else {
+      QNode* pn, *pnn;
+      pthread_mutex_lock(&fdlist.mut);
+      QLIST_NEXTSAFE_FOR_ALL(&fdlist.ql, pn, pnn) {
+         struct mem_to_fd* tofd = STD_RECOVER_REC(struct mem_to_fd, qn, pn);
+         if(tofd->buf == buf && tofd->size == size) {
+            tofd->refcount--;
+            if(tofd->refcount <= 0) {
+               QNode_DequeueZ(&tofd->qn);
+	       if (tofd->attr & FASTRPC_ATTR_KEEP_MAP) {
+		  remote_unmap_fd(tofd->buf, tofd->size, tofd->fd, tofd->attr);
+               }
+               if(tofd->nova) {
+                  munmap(tofd->buf, tofd->size);
+               }
+               free(tofd);
+               tofd = NULL;
+            }
+            break;
+         }
+      }
+      pthread_mutex_unlock(&fdlist.mut);
+   }
+bail:
+   if(nErr != AEE_SUCCESS) {
+      FARF(ERROR, "Error %x: remote_register_buf failed buf %p, size %d, fd %x", nErr, buf, size, fd);
+   }
+   return;
+}
+
+void remote_register_buf(void* buf, int size, int fd) {
+   return remote_register_buf_common(buf, size, fd, 0);
+}
+
+void remote_register_buf_attr(void* buf, int size, int fd, int attr) {
+   return remote_register_buf_common(buf, size, fd, attr);
+}
+
+int remote_register_dma_handle_attr(int fd, uint32_t len, uint32_t attr) {
+	int nErr = AEE_SUCCESS, i;
+	int fd_found = 0;
+
+	if (attr && attr != FASTRPC_ATTR_NOMAP) {
+		FARF(ERROR, "Error: %s failed, unsupported attribute 0x%x", __func__, attr);
+		return AEE_EBADPARM;
+	}
+	VERIFY(!fastrpc_init_once());
+
+	pthread_mutex_lock(&fdlist.mut);
+	for(i = 0; i < dma_handle_count; i++) {
+		if(dhandles[i].used && dhandles[i].fd == fd) {
+			/* If fd already present in handle list, then just update attribute only if its zero */
+			if(!dhandles[i].attr) {
+				dhandles[i].attr = attr;
+			}
+			fd_found = 1;
+			break;
+		}
+	}
+	pthread_mutex_unlock(&fdlist.mut);
+
+	if (fd_found) {
+		return AEE_SUCCESS;
+	}
+
+	pthread_mutex_lock(&fdlist.mut);
+	for(i = 0; i < dma_handle_count; i++) {
+		if(!dhandles[i].used) {
+			dhandles[i].fd = fd;
+			dhandles[i].len = len;
+			dhandles[i].used = 1;
+			dhandles[i].attr = attr;
+			break;
+		}
+	}
+	if(i == dma_handle_count) {
+		if(dma_handle_count >= MAX_DMA_HANDLES) {
+			FARF(ERROR, "Error: %s: DMA handle list is already full (count %d)", __func__, dma_handle_count);
+			nErr = AEE_EOUTOFHANDLES;
+		} else {
+			dhandles[dma_handle_count].fd = fd;
+			dhandles[dma_handle_count].len = len;
+			dhandles[dma_handle_count].used = 1;
+			dhandles[dma_handle_count].attr = attr;
+			dma_handle_count++;
+		}
+	}
+	pthread_mutex_unlock(&fdlist.mut);
+
+bail:
+	if(nErr) {
+		FARF(ERROR, "Error 0x%x: %s failed for fd 0x%x, len %d, attr 0x%x", nErr, __func__, fd, len, attr);
+	}
+	return nErr;
+}
+
+int remote_register_dma_handle(int fd, uint32_t len) {
+	return remote_register_dma_handle_attr(fd, len, 0);
+}
+
+static void unregister_dma_handle(int fd, uint32_t *len, uint32_t *attr) {
+	int i, last_used = 0;
+
+	*len = 0;
+	*attr = 0;
+
+	pthread_mutex_lock(&fdlist.mut);
+	for(i = 0; i < dma_handle_count; i++) {
+		if(dhandles[i].used) {
+			if(dhandles[i].fd == fd) {
+				dhandles[i].used = 0;
+				*len = dhandles[i].len;
+				*attr = dhandles[i].attr;
+				if(i == (dma_handle_count - 1)) {
+					dma_handle_count = last_used + 1;
+				}
+				break;
+			} else {
+				last_used = i;
+			}
+		}
+	}
+	pthread_mutex_unlock(&fdlist.mut);
+}
+
+static int fdlist_fd_from_buf(void* buf, int bufLen, int* nova, void** base, int* attr, int* ofd) {
+   QNode* pn;
+   int fd = -1;
+   pthread_mutex_lock(&fdlist.mut);
+   QLIST_FOR_ALL(&fdlist.ql, pn) {
+      if(fd != -1) {
+         break;
+      } else {
+         struct mem_to_fd* tofd = STD_RECOVER_REC(struct mem_to_fd, qn, pn);
+         if(STD_BETWEEN(buf, tofd->buf, (unsigned long)tofd->buf + tofd->size)) {
+            if(STD_BETWEEN((unsigned long)buf + bufLen -1, tofd->buf, (unsigned long)tofd->buf + tofd->size)) {
+               fd = tofd->fd;
+               *nova = tofd->nova;
+               *base = tofd->buf;
+               *attr = tofd->attr;
+            } else {
+               pthread_mutex_unlock(&fdlist.mut);
+			   FARF(ERROR,"Error %x: Mismatch in buffer address(%p) or size(%x) to the registered FD(%x), address(%p) and size(%x)\n", AEE_EBADPARM, buf, bufLen, tofd->fd, tofd->buf, tofd->size);
+               return AEE_EBADPARM;
+            }
+         }
+      }
+   }
+   *ofd = fd;
+   pthread_mutex_unlock(&fdlist.mut);
+   return 0;
+}
+
+static int verify_local_handle(remote_handle64 local) {
+	struct handle_info* hinfo = (struct handle_info*)(uintptr_t)local;
+	int nErr = AEE_SUCCESS;
+
+	VERIFYC(hinfo, AEE_EMEMPTR);
+	VERIFYC((hinfo->hlist >= &hlist[0]) && (hinfo->hlist < &hlist[NUM_DOMAINS_EXTEND]), AEE_EMEMPTR);
+	VERIFYC(QNode_IsQueuedZ(&hinfo->qn), AEE_ENOSUCHHANDLE);
+bail:
+	if (nErr != AEE_SUCCESS) {
+		FARF(HIGH, "Error %x: verify local handle failed. handle %p\n", nErr, &local);
+	}
+	return nErr;
+}
+
+static int get_domain_from_handle(remote_handle64 local, int *domain) {
+	struct handle_info *hinfo = (struct handle_info*)(uintptr_t)local;
+	int dom, nErr = AEE_SUCCESS;
+
+	VERIFY(AEE_SUCCESS == (nErr = verify_local_handle(local)));
+	dom = (int)(hinfo->hlist - &hlist[0]);
+	VERIFYC((dom >= 0) && (dom < NUM_DOMAINS_EXTEND), AEE_EINVALIDDOMAIN);
+	*domain = dom;
+bail:
+	if (nErr != AEE_SUCCESS) {
+		FARF(HIGH, "Error %x: get domain from handle failed. handle %p\n", nErr, &local);
+	}
+	return nErr;
+}
+
+static int get_domain_from_name(const char *uri) {
+   int domain = DEFAULT_DOMAIN_ID;
+
+   if(uri) {
+      if(std_strstr(uri, ADSP_DOMAIN)) {
+         domain = ADSP_DOMAIN_ID;
+      } else if(std_strstr(uri, MDSP_DOMAIN)) {
+         domain = MDSP_DOMAIN_ID;
+      } else if(std_strstr(uri, SDSP_DOMAIN)) {
+         domain = SDSP_DOMAIN_ID;
+      } else if(std_strstr(uri, CDSP_DOMAIN)) {
+         domain = CDSP_DOMAIN_ID;
+      } else {
+         domain = INVALID_DOMAIN_ID;
+         FARF(ERROR, "invalid domain uri: %s\n", uri);
+      }
+      if (std_strstr(uri, FASTRPC_SESSION_URI)) {
+         domain = domain | FASTRPC_SESSION_ID1;
+      }
+   }
+   VERIFY_IPRINTF("get_domain_from_name: %d\n", domain);
+   return domain;
+}
+
+static int alloc_handle(int domain, remote_handle64 remote, struct handle_info **info) {
+   struct handle_info* hinfo;
+   int nErr = AEE_SUCCESS;
+
+   VERIFYC(NULL != (hinfo = malloc(sizeof(*hinfo))), AEE_ENOMEMORY);
+   hinfo->local = (remote_handle64)(uintptr_t)hinfo;
+   hinfo->remote = remote;
+   hinfo->hlist = &hlist[domain];
+   QNode_CtorZ(&hinfo->qn);
+   pthread_mutex_lock(&hlist[domain].mut);
+   QList_PrependNode(&hlist[domain].ql, &hinfo->qn);
+   pthread_mutex_unlock(&hlist[domain].mut);
+   *info = hinfo;
+
+bail:
+   if (nErr != AEE_SUCCESS) {
+	FARF(ERROR, "Error %x: alloc handle failed. domain %d\n", nErr, domain); 
+   }
+   return nErr;
+}
+
+#define IS_CONST_HANDLE(h)  (((h) < 0xff) ? 1 : 0)
+static int is_last_handle(int domain) {
+   QNode* pn;
+   int nErr = AEE_SUCCESS, empty = 0;
+
+   pthread_mutex_lock(&hlist[domain].mut);
+   if(!(hlist[domain].domainsupport && !hlist[domain].nondomainsupport)){
+       VERIFY_IPRINTF("Error %x: hlist[domain].domainsupport && !hlist[domain].nondomainsupport\n",AEE_EBADDOMAIN);
+       goto bail;
+   }
+   empty = 1;
+   if (!QList_IsEmpty(&hlist[domain].ql)) {
+      empty = 1;
+      QLIST_FOR_ALL(&hlist[domain].ql, pn) {
+         struct handle_info* hi = STD_RECOVER_REC(struct handle_info, qn, pn);
+         empty = empty & IS_CONST_HANDLE(hi->remote);
+         if(!empty)
+            break;
+      }
+   }
+bail:
+   pthread_mutex_unlock(&hlist[domain].mut);
+   if (nErr != AEE_SUCCESS) {
+       VERIFY_IPRINTF("Error %x: is_last_handle %d failed\n", nErr, domain);
+   }
+   return empty;
+}
+
+static int free_handle(remote_handle64 local) {
+   struct handle_info* hinfo = (struct handle_info*)(uintptr_t)local;
+   int nErr = AEE_SUCCESS;
+
+   VERIFY(AEE_SUCCESS == (nErr = verify_local_handle(local)));
+   pthread_mutex_lock(&hinfo->hlist->mut);
+   QNode_DequeueZ(&hinfo->qn);
+   pthread_mutex_unlock(&hinfo->hlist->mut);
+   free(hinfo);
+   hinfo = NULL;
+bail:
+   if (nErr != AEE_SUCCESS) {
+	FARF(ERROR, "Error %x: free handle failed %p\n", nErr, &local);
+   }
+   return nErr;
+}
+
+static int get_handle_remote(remote_handle64 local, remote_handle64 *remote) {
+   struct handle_info* hinfo = (struct handle_info*)(uintptr_t)local;
+   int nErr = AEE_SUCCESS;
+
+   VERIFY(AEE_SUCCESS == (nErr = verify_local_handle(local)));
+   *remote = hinfo->remote;
+bail:
+   if (nErr != AEE_SUCCESS) {
+        FARF(ERROR, "Error %x: get handle remote failed %p\n", nErr, &local);
+   }
+   return nErr;
+}
+
+void set_thread_context(int domain) {
+   if(tlsKey != INVALID_KEY) {
+      pthread_setspecific(tlsKey, (void*)&hlist[domain]);
+   }
+}
+
+int get_domain_id() {
+   int domain;
+   struct handle_list* list;
+   list = (struct handle_list*)pthread_getspecific(tlsKey);
+   if(list && hlist){
+      domain = (int)(list - &hlist[0]);
+   }else{
+      domain = DEFAULT_DOMAIN_ID;
+   }
+   return domain;
+}
+
+int is_smmu_enabled(void) {
+	struct handle_list* list;
+	int domain, nErr = 0;
+
+	list = (struct handle_list*)pthread_getspecific(tlsKey);
+	if (list) {
+		domain = (int)(list - &hlist[0]);
+		VERIFY((domain >= 0) && (domain < NUM_DOMAINS_EXTEND));
+		return hlist[domain].info & FASTRPC_INFO_SMMU;
+	}
+bail:
+	return 0;
+}
+
+static int fdlist_fd_to_buf(void *buf)
+{
+	QNode *pn;
+	int fd = -1;
+	pthread_mutex_lock(&fdlist.mut);
+	QLIST_FOR_ALL(&fdlist.ql, pn)
+	{
+		if (fd != -1)
+		{
+			break;
+		}
+		else
+		{
+			struct mem_to_fd *tofd = STD_RECOVER_REC(struct mem_to_fd, qn, pn);
+			if (STD_BETWEEN(buf, tofd->buf, (unsigned long)tofd->buf + tofd->size))
+			{
+				fd = tofd->fd;
+			}
+		}
+	}
+	pthread_mutex_unlock(&fdlist.mut);
+	return fd;
+}
+
+int remote_handle_invoke_domain(int domain, remote_handle handle, uint32_t sc, remote_arg* pra) {
+    struct fastrpc_invoke invoke;
+	struct fastrpc_invoke_args *args;
+	int bufs, i, req, nErr = 0;
+	int dev;
+	VERIFY(dev != -1);
+	invoke.handle = handle;
+	invoke.sc = sc;
+	struct handle_list* list;
+	
+   VERIFYC(-1 != (dev = open_dev(domain)), AEE_EINVALIDDEVICE);
+   list = &hlist[domain];
+   if(0 == pthread_getspecific(tlsKey)) {
+      pthread_setspecific(tlsKey, (void*)list);
+   }
+	bufs = REMOTE_SCALARS_LENGTH(sc);
+
+	args = malloc(bufs * sizeof(*args));
+	if (!args)
+		return -ENOMEM;
+
+	invoke.args = (__u64)(uintptr_t)args;
+
+	for (i = 0; i < bufs; i++)
+	{
+		args[i].reserved = 0;
+		args[i].length = pra[i].buf.nLen;
+		args[i].ptr = (__u64)(uintptr_t)pra[i].buf.pv;
+		
+
+		if (pra[i].buf.nLen)
+		{
+			FARF(HIGH,"debug:sc:%x,handle:%x,len:%llx\n",sc,pra[i].buf.nLen);
+			args[i].fd = fdlist_fd_to_buf(pra[i].buf.pv);
+		}
+		else
+		{
+			args[i].fd = -1;
+		}
+	}
+	req = FASTRPC_IOCTL_INVOKE;
+
+	if (0 == pthread_getspecific(tlsKey))
+	{
+		pthread_setspecific(tlsKey, (void *)1);
+	}
+    FARF(HIGH,"debug:sc:%x,handle:%x\n",sc,handle);
+	nErr = ioctl(dev, req, (unsigned long)&invoke);
+	free(args);
+bail:
+	return nErr;
+}
+
+int remote_handle_invoke(remote_handle handle, uint32_t sc, remote_arg* pra) {
+	struct handle_list* list;
+	int domain = DEFAULT_DOMAIN_ID, nErr = AEE_SUCCESS;
+
+	VERIFYC(handle != (remote_handle)-1, AEE_EBADHANDLE);
+	list = (struct handle_list*)pthread_getspecific(tlsKey);
+
+	if(list) {
+		domain = (int)(list - &hlist[0]);
+		VERIFYC((domain >= 0) && (domain < NUM_DOMAINS_EXTEND), AEE_EINVALIDDOMAIN);
+	} else {
+		domain = DEFAULT_DOMAIN_ID;
+	}
+	VERIFY(AEE_SUCCESS == (nErr = remote_handle_invoke_domain(domain, handle, sc, pra)));
+bail:
+	if (nErr != AEE_SUCCESS) {
+		FARF(HIGH, "Error %x: remote handle invoke failed. domain %d, handle %x, sc %x, pra %p\n", nErr, domain, handle, sc, pra);
+	}
+	return nErr;
+}
+
+int remote_handle64_invoke(remote_handle64 local, uint32_t sc, remote_arg* pra) {
+	remote_handle64 remote;
+	int nErr = AEE_SUCCESS, domain = DEFAULT_DOMAIN_ID;
+
+	VERIFYC(local != (remote_handle64)-1, AEE_EBADHANDLE);
+	VERIFY(AEE_SUCCESS == (nErr = get_domain_from_handle(local, &domain)));
+	VERIFY(AEE_SUCCESS == (nErr = get_handle_remote(local, &remote)));
+	VERIFY(AEE_SUCCESS == (nErr = remote_handle_invoke_domain(domain, remote, sc, pra)));
+bail:
+	if (nErr != AEE_SUCCESS) {
+		FARF(HIGH, "Error %x: remote handle64 invoke failed. domain %d, handle %p, sc %x, pra %p\n", nErr, domain, &local, sc, pra);
+	}
+	return nErr;
+}
+
+int listener_android_geteventfd(int domain, int *fd);
+int remote_handle_open_domain(int domain, const char* name, remote_handle *ph)
+{
+   char dlerrstr[255];
+   int dlerr = 0, nErr = AEE_SUCCESS;
+   if (!std_strncmp(name, ITRANSPORT_PREFIX "geteventfd", std_strlen(ITRANSPORT_PREFIX "geteventfd"))) {
+      FARF(HIGH, "getting event fd \n");
+      return listener_android_geteventfd(domain, (int *)ph);
+   }
+   if (!std_strncmp(name, ITRANSPORT_PREFIX "attachguestos", std_strlen(ITRANSPORT_PREFIX "attachguestos"))) {
+      FARF(HIGH, "setting attach mode to guestos : %d\n", domain);
+      VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
+      hlist[domain].dsppd = GUEST_OS;
+      return AEE_SUCCESS;
+   }
+   if (!std_strncmp(name, ITRANSPORT_PREFIX "createstaticpd", std_strlen(ITRANSPORT_PREFIX "createstaticpd"))) {
+      FARF(HIGH, "creating static pd on domain: %d\n", domain);
+      VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
+      const char *pdName = name + std_strlen(ITRANSPORT_PREFIX "createstaticpd:");
+      hlist[domain].dsppdname = (char *)malloc((std_strlen(pdName) + 1)*(sizeof(char)));
+      VERIFYC(NULL != hlist[domain].dsppdname, AEE_ENOMEMORY);
+      std_strlcpy(hlist[domain].dsppdname, pdName, std_strlen(pdName) + 1);
+      if (!std_strncmp(pdName, "audiopd", std_strlen("audiopd"))) {
+         hlist[domain].dsppd = STATIC_USER_PD;
+      } else if (!std_strncmp(pdName, "sensorspd", std_strlen("sensorspd"))) {
+         hlist[domain].dsppd = ATTACH_SENSORS_PD;
+      } else if (!std_strncmp(pdName, "rootpd", std_strlen("rootpd"))) {
+         hlist[domain].dsppd = GUEST_OS_SHARED;
+      }
+      return AEE_SUCCESS;
+   }
+   if (std_strbegins(name, ITRANSPORT_PREFIX "attachuserpd")) {
+      FARF(HIGH, "setting attach mode to userpd : %d\n", domain);
+      VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
+      hlist[domain].dsppd = USER_PD;
+      return AEE_SUCCESS;
+   }
+   VERIFYC(-1 != open_dev(domain), AEE_EINVALIDDEVICE);
+   FARF(HIGH, "Name of the shared object to open %s\n", name);
+   VERIFY(AEE_SUCCESS == (nErr = remotectl_open(name, (int*)ph, dlerrstr, sizeof(dlerrstr), &dlerr)));
+   VERIFY(AEE_SUCCESS == (nErr = dlerr));
+
+bail:
+   if(dlerr != 0) {
+      FARF(ERROR, "Error %x: remote handle open domain failed. domain %d, name %s, dlerror %s\n", nErr, domain, name, dlerrstr);
+   }
+   if (nErr != 0)
+      if (hlist[domain].dsppdname != NULL)
+      {
+         free(hlist[domain].dsppdname);
+         hlist[domain].dsppdname = NULL;
+      }
+   return nErr;
+}
+
+int remote_handle_open(const char* name, remote_handle *ph) {
+   int nErr = 0, domain;
+   domain = DEFAULT_DOMAIN_ID;
+   VERIFY(!remote_handle_open_domain(domain, name, ph));
+   hlist[domain].nondomainsupport = 1;
+bail:
+   return nErr;
+}
+
+int remote_handle64_open(const char* name, remote_handle64 *ph)
+{
+   struct handle_info* hinfo = 0;
+   remote_handle h = 0;
+   int domain, nErr = 0;
+
+   domain = get_domain_from_name(name);
+   VERIFYC(domain >= 0, AEE_EINVALIDDOMAIN);
+   VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
+   VERIFY(AEE_SUCCESS == (nErr = remote_handle_open_domain(domain, name, &h)));
+   hlist[domain].domainsupport = 1;
+   VERIFY(AEE_SUCCESS == (nErr = alloc_handle(domain, h, &hinfo)));
+   *ph = hinfo->local;
+bail:
+   if(nErr) {
+      if(h)
+         remote_handle_close(h);
+      FARF(HIGH, "Error %x: remote handle64 open failed. name %s\n", nErr, name);
+   }
+   return nErr;
+}
+
+int remote_handle_close(remote_handle h)
+{
+   char dlerrstr[255];
+   int dlerr = 0, nErr = AEE_SUCCESS;
+
+   VERIFY(AEE_SUCCESS == (nErr = remotectl_close(h, dlerrstr, sizeof(dlerrstr), &dlerr)));
+   VERIFY(AEE_SUCCESS == (nErr = dlerr));
+bail:
+   if (nErr != AEE_SUCCESS) {
+	FARF(HIGH, "Error %x: remote handle close failed. error %s\n", nErr, dlerrstr);
+   }
+   return nErr;
+}
+
+int remote_handle64_close(remote_handle64 handle) {
+   remote_handle64 remote;
+   int domain, nErr = AEE_SUCCESS;
+
+   VERIFY(AEE_SUCCESS == (nErr = get_domain_from_handle(handle, &domain)));
+   VERIFY(AEE_SUCCESS == (nErr = get_handle_remote(handle, &remote)));
+   set_thread_context(domain);
+   VERIFY(AEE_SUCCESS == (nErr = remote_handle_close((remote_handle)remote)));
+bail:
+   free_handle(handle);
+   if (is_last_handle(domain)) {
+      domain_deinit(domain);
+   }
+   if (nErr != AEE_SUCCESS) {
+	FARF(HIGH, "Error %x: remote handle64 close failed.\n", nErr);
+   }
+   return nErr;
+}
+
+int manage_pm_qos(int domain, remote_handle64 h, uint32_t enable, uint32_t latency) {
+	int nErr = AEE_SUCCESS;
+	struct fastrpc_latency *qos;
+	int state = 0;
+
+	if (h == -1) {
+		/* Handle will be -1 in non-domains invocation. Create session if necessary  */
+		if (!hlist || (hlist && hlist[domain].dev == -1))
+			VERIFYC(-1 != open_dev(domain), AEE_EINVALIDDEVICE);
+	} else {
+		/* If the multi-domain handle is valid, then verify that session is created already */
+		VERIFY(hlist[domain].dev != -1);
+	}
+	qos = &hlist[domain].qos;
+	VERIFY(qos);
+	if (qos->exit == FASTRPC_LATENCY_EXIT)
+		goto bail;
+	pthread_mutex_lock(&qos->mut);
+	state = qos->state;
+	qos->latency = latency;
+	pthread_mutex_unlock(&qos->mut);
+
+	if (!enable && state == FASTRPC_LATENCY_START) {
+		qos->exit = FASTRPC_LATENCY_EXIT;
+		pthread_mutex_lock(&qos->wmut);
+		pthread_cond_signal(&qos->cond);
+		pthread_mutex_unlock(&qos->wmut);
+	}
+
+	if (enable && state == FASTRPC_LATENCY_STOP) {
+		qos->state = FASTRPC_LATENCY_START;
+		VERIFY(AEE_SUCCESS == (nErr = pthread_create(&qos->thread, 0, fastrpc_latency_thread_handler, (void*)qos)));
+	}
+bail:
+	return nErr;
+}
+
+int manage_adaptive_qos(int domain, uint32_t enable) {
+	int nErr = AEE_SUCCESS;
+
+	VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
+
+	/* If adaptive QoS is already enabled/disabled, then just return */
+	if ((enable && hlist[domain].qos.adaptive_qos) || (!enable && !hlist[domain].qos.adaptive_qos))
+		return nErr;
+
+	if (hlist[domain].dev != -1) {
+		/* If session is already open on DSP, then make rpc call directly to user PD */
+		nErr = remotectl_set_param(FASTRPC_ADAPTIVE_QOS, &enable, 1);
+		if (nErr) {
+			FARF(ERROR, "Error: %s: remotectl_set_param failed to reset adaptive QoS on DSP to %d on domain %d",
+							__func__, enable, domain);
+			goto bail;
+		} else {
+			hlist[domain].qos.adaptive_qos = ((enable == FASTRPC_ADAPTIVE_QOS)? 1:0);
+		}
+	} else {
+		/* If session is not created already, then just process attribute */
+		hlist[domain].qos.adaptive_qos = ((enable == FASTRPC_ADAPTIVE_QOS)? 1:0);
+	}
+
+	if (enable) 
+		FARF(ALWAYS, "%s: Successfully enabled adaptive QoS on domain %d", __func__, domain);
+	else
+		FARF(ALWAYS, "%s: Disabled adaptive QoS on domain %d", __func__, domain);
+bail:
+	return nErr;
+}
+
+int remote_handle_control_domain(int domain, remote_handle64 h, uint32_t req, void* data, uint32_t len) {
+	int nErr = AEE_SUCCESS;
+
+	switch (req) {
+		case DSPRPC_CONTROL_LATENCY:
+		{
+			struct remote_rpc_control_latency *lp = (struct remote_rpc_control_latency*)data;
+			VERIFYC(lp, AEE_EBADPARM);
+			VERIFYC(len == sizeof(struct remote_rpc_control_latency), AEE_EBADPARM);
+
+			switch(lp->enable) {
+				/* Only one of PM QoS or adaptive QoS can be enabled */
+				case FASTRPC_DISABLE_QOS:
+				{
+					VERIFY(AEE_SUCCESS == (nErr = manage_adaptive_qos(domain, FASTRPC_DISABLE_QOS)));
+					VERIFY(AEE_SUCCESS == (nErr = manage_pm_qos(domain, h, FASTRPC_DISABLE_QOS, lp->latency)));
+					break;
+				}
+				case FASTRPC_PM_QOS:
+				{
+					VERIFY(AEE_SUCCESS == (nErr = manage_adaptive_qos(domain, FASTRPC_DISABLE_QOS)));
+					VERIFY(AEE_SUCCESS == (nErr = manage_pm_qos(domain, h, FASTRPC_PM_QOS, lp->latency)));
+					break;
+				}
+				case FASTRPC_ADAPTIVE_QOS:
+				{
+					/* Disable PM QoS if enabled and then enable adaptive QoS */
+					VERIFY(AEE_SUCCESS == (nErr = manage_pm_qos(domain, h, FASTRPC_DISABLE_QOS, lp->latency)));
+					VERIFY(AEE_SUCCESS == (nErr = manage_adaptive_qos(domain, FASTRPC_ADAPTIVE_QOS)));
+					break;
+				}
+				default:
+					nErr = AEE_EBADPARM;
+					FARF(ERROR, "Error: %s: Bad enable parameter %d passed for QoS control", __func__, lp->enable);
+					break;
+			}
+			break;
+		}
+		default:
+			nErr = AEE_EUNSUPPORTEDAPI;
+			FARF(ERROR, "Error: %s: remote handle control called with unsupported request ID %d", __func__, req);
+			break;
+	}
+bail:
+	if (nErr != AEE_SUCCESS)
+		FARF(ERROR, "Error 0x%x: %s failed for request ID %d on domain %d", nErr, __func__, req, domain);
+	return nErr;
+}
+
+int remote_handle_control(uint32_t req, void* data, uint32_t len) {
+	struct handle_list* list;
+	int domain = DEFAULT_DOMAIN_ID, nErr = AEE_SUCCESS;
+
+	VERIFY(AEE_SUCCESS == (nErr = remote_handle_control_domain(domain, -1, req, data, len)));
+bail:
+	if (nErr != AEE_SUCCESS)
+		FARF(ERROR, "Error 0x%x: %s failed for request ID %d", nErr, __func__, req);
+	return nErr;
+}
+
+int remote_handle64_control(remote_handle64 handle, uint32_t req, void* data, uint32_t len) {
+	int nErr = AEE_SUCCESS, domain = 0;
+
+	VERIFY(AEE_SUCCESS == (nErr = get_domain_from_handle(handle, &domain)));
+	VERIFY(AEE_SUCCESS == (nErr = remote_handle_control_domain(domain, handle, req, data, len)));
+
+bail:
+	if (nErr != AEE_SUCCESS)
+		FARF(ERROR, "Error 0x%x: %s failed for request ID %d", nErr, __func__, req);
+	return nErr;
+}
+
+static int store_domain_thread_params(int domain, struct remote_rpc_thread_params *params, uint32_t req)
+{
+	int nErr = AEE_SUCCESS;
+
+	if (hlist[domain].dev != -1) {
+		nErr = AEE_ENOTALLOWED;
+		FARF(ERROR, "%s: Session already open on domain %d ! Set parameters before making any RPC calls",
+					__func__, domain);
+		goto bail;
+	}
+	if (params->prio != -1) {
+		/* Valid QuRT thread priorities are 1 to 255 */
+		unsigned int min_prio = 1, max_prio = 255;
+
+		if ((params->prio < min_prio) || (params->prio > max_prio)) {
+			nErr = AEE_EBADPARM;
+			FARF(ERROR, "%s: Priority %d is invalid! Should be between %d and %d",
+						__func__, params->prio, min_prio, max_prio);
+			goto bail;
+		} else
+			hlist[domain].th_params.prio = (uint32_t) params->prio;
+	}
+	if (params->stack_size != -1) {
+		/* Stack size passed by user should be between 16 KB and 8 MB */
+		unsigned int min_stack_size = 16*1024, max_stack_size = 8*1024*1024;
+
+		if ((params->stack_size < min_stack_size) || (params->stack_size > max_stack_size)) {
+			nErr = AEE_EBADPARM;
+			FARF(ERROR, "%s: Stack size %d is invalid! Should be between %d and %d",
+						__func__, params->stack_size, min_stack_size, max_stack_size);
+			goto bail;
+		} else
+			hlist[domain].th_params.stack_size = (uint32_t) params->stack_size;
+	}
+	hlist[domain].th_params.reqID = req;
+bail:
+	if (nErr != AEE_SUCCESS)
+		FARF(ERROR, "Error 0x%x: %s failed for domain %d", nErr, __func__, domain);
+	return nErr;
+}
+
+/* Set remote session parameters like thread stack size, running on unsigned PD etc */
+int remote_session_control(uint32_t req, void *data, uint32_t datalen)
+{
+	int nErr = AEE_SUCCESS;
+
+	VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
+
+	switch (req) {
+		case FASTRPC_THREAD_PARAMS:
+		{
+			struct remote_rpc_thread_params *params = (struct remote_rpc_thread_params*)data;
+			if (!params) {
+				nErr = AEE_EBADPARM;
+				FARF(ERROR, "%s: Thread params struct passed is %p", __func__, params);
+				goto bail;
+			}
+			VERIFYC(datalen == sizeof(struct remote_rpc_thread_params), AEE_EINVALIDFORMAT);
+			if (params->domain != -1) {
+				if ((params->domain < 0) || (params->domain >= NUM_DOMAINS_EXTEND)) {
+					nErr = AEE_EINVALIDDOMAIN;
+					FARF(ERROR, "%s: Invalid domain ID %d passed", __func__, params->domain);
+					goto bail;
+				}
+				VERIFY(AEE_SUCCESS == (nErr = store_domain_thread_params(params->domain, params, req)));
+			} else {
+				/* If domain is -1, then set parameters for all domains */
+				for (int i = 0; i < NUM_DOMAINS_EXTEND; i++) {
+					VERIFY(AEE_SUCCESS == (nErr = store_domain_thread_params(i, params, req)));
+				}
+			}
+			break;
+		}
+		case DSPRPC_CONTROL_UNSIGNED_MODULE:
+		{
+			// Handle the unsigned module offload request
+			struct remote_rpc_control_unsigned_module *um = (struct remote_rpc_control_unsigned_module*)data;
+			VERIFYC(datalen == sizeof(struct remote_rpc_control_unsigned_module), AEE_EINVALIDFORMAT);
+			VERIFY(um != NULL);
+			FARF (HIGH, "%s Unsigned module offload enable %d for domain %d", __func__, um->enable, um->domain);
+			if (um->domain != -1) {
+				VERIFYC((um->domain >= 0) && (um->domain < NUM_DOMAINS_EXTEND), AEE_EINVALIDDOMAIN);
+				hlist[um->domain].unsigned_module = um->enable? 1 :0 ;
+			} else {
+				for (int ii = 0; ii < NUM_DOMAINS_EXTEND; ii++) {
+					hlist[ii].unsigned_module = um->enable? 1: 0;
+				}
+			}
+		}
+		break;
+		default:
+			nErr = AEE_EUNSUPPORTEDAPI;
+			FARF(ERROR, "%s: Unsupported request ID %d", __func__, req);
+			break;
+	}
+bail:
+	if (nErr != AEE_SUCCESS) {
+		FARF(ERROR, "Error 0x%x: %s failed for request ID %d", nErr, __func__, req);
+	}
+	return nErr;
+}
+
+int remote_mmap64(int fd, uint32_t flags, uint64_t vaddrin, int64_t size, uint64_t* vaddrout) {
+	struct handle_list* list;
+	struct fastrpc_ioctl_mmap mmap;
+	int dev, domain, nErr = AEE_SUCCESS;
+
+	list = (struct handle_list*)pthread_getspecific(tlsKey);
+	VERIFYC(NULL != list, AEE_EMEMPTR);
+	domain = (int)(list - &hlist[0]);
+	VERIFYC((domain >= 0) && (domain < NUM_DOMAINS_EXTEND), AEE_EINVALIDDOMAIN);
+	VERIFYC(-1 != (dev = open_dev(domain)), AEE_EINVALIDDEVICE);
+	mmap.fd  = fd;
+	mmap.flags  = flags;
+	mmap.vaddrin = vaddrin;
+	mmap.size = size;
+	FARF(HIGH, "Entering %s : fd %d, vaddrin %llx, size %llx ioctl %x\n", __func__, fd, vaddrin, size, FASTRPC_IOCTL_MMAP);
+	VERIFY(AEE_SUCCESS == (nErr = ioctl(dev, FASTRPC_IOCTL_MMAP, (unsigned long)&mmap)));
+	*vaddrout = mmap.vaddrout;
+bail:
+	if (nErr != AEE_SUCCESS) {
+		FARF(ERROR, "Error %x: remote mmap64 failed. fd %x, flags %x, vaddrin %llx, size %zx\n", nErr, fd, flags, vaddrin, size);
+	}
+	return nErr;
+}
+
+int remote_mmap(int fd, uint32_t flags, uint32_t vaddrin, int size, uint32_t* vaddrout) {
+	return remote_mmap64(fd, flags, (uintptr_t)vaddrin, (int64_t)size, (uint64_t*)vaddrout);
+}
+
+int remote_munmap64(uint64_t vaddrout, int64_t size) {
+	struct handle_list* list;
+	struct fastrpc_ioctl_munmap munmap;
+	int dev, domain, nErr = AEE_SUCCESS;
+
+	list = (struct handle_list*)pthread_getspecific(tlsKey);
+	VERIFYC(NULL != list, AEE_EMEMPTR);
+	domain = (int)(list - &hlist[0]);
+	VERIFYC((domain >= 0) && (domain < NUM_DOMAINS_EXTEND), AEE_EINVALIDDOMAIN);
+	VERIFYC(-1 != (dev = open_dev(domain)), AEE_EINVALIDDEVICE);
+	VERIFY(list->dev > 0);
+	munmap.vaddrout = vaddrout;
+	munmap.size = size;
+	FARF(HIGH, "Entering %s : vaddrin %llx, size %llx\n", __func__, vaddrout, size);
+	VERIFY(AEE_SUCCESS == (nErr = ioctl(dev, FASTRPC_IOCTL_MUNMAP, (unsigned long)&munmap)));
+bail:
+	if (nErr != AEE_SUCCESS) {
+		FARF(ERROR, "Error %x: remote munmap64 failed. vaddrout %p, size %zx\n", nErr, vaddrout, size);
+	}
+	return nErr;
+}
+
+int remote_munmap(uint32_t vaddrout, int size) {
+	return remote_munmap64((uintptr_t)vaddrout, (int64_t)size);
+}
+
+static int remote_unmap_fd(void *buf, int size, int fd, int attr) {
+   int nErr = 0;
+   int i;
+   struct fastrpc_ioctl_munmap map;
+
+   VERIFY(hlist);
+   map.vaddrout = (uintptr_t) buf;
+   map.size = size;
+   for (i = 0; i < NUM_DOMAINS; i++) {
+      pthread_mutex_lock(&hlist[i].mut);
+      if (hlist[i].dev != -1) {
+        nErr = ioctl(hlist[i].dev, FASTRPC_IOCTL_MUNMAP, (unsigned long)&map);
+	if (nErr)
+	   FARF(LOW, "unmap_fd: device found %d for domain %d returned %d", hlist[i].dev, i, nErr);
+      }
+      pthread_mutex_unlock(&hlist[i].mut);
+   }
+bail:
+   return nErr;
+}
+
+
+int remote_set_mode(uint32_t mode) {
+   int i;
+   for(i = 0; i < NUM_DOMAINS_EXTEND; i++) {
+      hlist[i].mode = mode;
+      hlist[i].setmode = 1;
+   }
+   return AEE_SUCCESS;
+}
+
+#ifdef __ANDROID__
+#include <android/log.h>
+extern const char* __progname;
+void HAP_debug(const char *msg, int level, const char *filename, int line) {
+   __android_log_print(level, __progname, "%s:%d: %s", filename, line, msg);
+}
+#else
+extern const char* __progname;
+void HAP_debug(const char *msg, int level, const char *filename, int line) {
+   printf("hello %s - %s:%d: %s", __progname, filename, line, msg);
+}    
+#endif
+
+PL_DEP(fastrpc_apps_user);
+PL_DEP(gpls);
+PL_DEP(apps_mem);
+PL_DEP(apps_std);
+PL_DEP(rpcmem);
+PL_DEP(listener_android);
+
+static int attach_guestos(int domain) {
+   int attach;
+
+   switch(domain & DOMAIN_ID_MASK) {
+      case MDSP_DOMAIN_ID:
+      case ADSP_DOMAIN_ID:
+          attach = USER_PD;
+          break;
+      case CDSP_DOMAIN_ID:
+          attach = USER_PD;
+          break;
+      default:
+          attach = GUEST_OS;
+          break;
+   }
+   return attach;
+}
+
+static void domain_deinit(int domain) {
+   QNode *pn;
+   remote_handle64 handle;
+
+   if(!hlist) {
+      return;
+   }
+
+   pthread_mutex_lock(&hlist[domain].mut);
+   FARF(HIGH, "domain_deinit for domain %d: dev %d \n", domain, hlist[domain].dev);
+   if(hlist[domain].dev != -1) {
+      handle = get_adsp_current_process1_handle(domain);
+      if(handle != INVALID_HANDLE) {
+         adsp_current_process1_exit(handle);
+      } else {
+         adsp_current_process_exit();
+      }
+
+      listener_android_domain_deinit(domain);
+      deinitFileWatcher(domain);
+      fastrpc_perf_deinit();
+      fastrpc_latency_deinit(&hlist[domain].qos);
+      while((pn = QList_Pop(&hlist[domain].ql))) {
+         struct handle_info* hi = STD_RECOVER_REC(struct handle_info, qn, pn);
+         free(hi);
+         hi = NULL;
+      }
+      hlist[domain].cphandle = 0;
+      hlist[domain].msghandle = 0;
+      hlist[domain].domainsupport = 0;
+      hlist[domain].nondomainsupport = 0;
+      hlist[domain].initialized = 0;
+      hlist[domain].dsppd = attach_guestos(domain);
+      if (hlist[domain].dsppdname != NULL)
+      {
+         free(hlist[domain].dsppdname);
+         hlist[domain].dsppdname = NULL;
+      }
+
+      FARF(HIGH, "exit: closing %d, rpc errors are expected.\n", domain);
+
+      if (close(hlist[domain].dev))
+	      FARF(ERROR, "exit: failed to close file descriptor for domain %d\n", domain);
+
+      hlist[domain].dev = -1;
+   }
+   if(hlist[domain].pdmem) {
+      rpcmem_free_internal(hlist[domain].pdmem);
+      hlist[domain].pdmem = NULL;
+   }
+   pthread_mutex_unlock(&hlist[domain].mut);
+}
+
+#define ALIGN_B(p, a)	      (((p) + ((a) - 1)) & ~((a) - 1))
+
+static const char* get_domain_name(int domain_id) {
+   const char* name;
+   int domain = domain_id & DOMAIN_ID_MASK;
+
+   switch (domain) {
+      case ADSP_DOMAIN_ID:
+         name = ADSPRPC_DEVICE;
+         break;
+      case SDSP_DOMAIN_ID:
+         name = SDSPRPC_DEVICE;
+         break;
+      case MDSP_DOMAIN_ID:
+         name = MDSPRPC_DEVICE;
+         break;
+      case CDSP_DOMAIN_ID:
+         name = CDSPRPC_DEVICE;
+         break;
+      default:
+         name = DEFAULT_DEVICE;
+         break;
+   }
+   return name;
+}
+
+/* Returns the name of the domain based on the following
+ ADSP/SLPI/MDSP - Return Secure node
+ CDSP - Return default node
+ */
+static const char* get_secure_domain_name(int domain_id) {
+   const char* name;
+   int domain = domain_id & DOMAIN_ID_MASK;
+
+   switch (domain) {
+      case ADSP_DOMAIN_ID:
+      case SDSP_DOMAIN_ID:
+      case MDSP_DOMAIN_ID:
+         name = SECURE_DEVICE;
+         break;
+      case CDSP_DOMAIN_ID:
+         // Intentional fallthrough
+      default:
+         name = DEFAULT_DEVICE;
+         break;
+   }
+   return name;
+}
+
+/* Opens device node based on the domain
+ This function takes care of the backward compatibility to open
+ approriate device for following configurations of the device nodes
+ 1. 4 different device nodes
+ 2. 1 device node (adsprpc-smd)
+ 3. 2 device nodes (adsprpc-smd, adsprpc-smd-secure)
+ Algorithm
+ For ADSP, SDSP, MDSP domains:
+   Open secure device node fist
+     if no secure device, open actual device node
+     if still no device, open default node
+     if failed to open the secure node due to permission,
+     open default node
+ For CDSP domain:
+   Open actual device node ("cdsprpc-smd")
+   if no device, open secure / default device node
+*/
+static int open_device_node_internal (int domain_id) {
+  int dev = -1;
+  int domain = domain_id & DOMAIN_ID_MASK;
+
+  switch (domain) {
+    case ADSP_DOMAIN_ID:
+    case SDSP_DOMAIN_ID:
+    case MDSP_DOMAIN_ID:
+      dev = open(get_secure_domain_name(domain), O_NONBLOCK);
+      if((dev < 0) && (errno == ENOENT)) {
+        FARF(HIGH, "Device node %s open failed for domain %d (errno %s),\n"
+                    "falling back to node %s \n",
+                    get_secure_domain_name(domain), domain, strerror(errno),
+                    get_domain_name(domain));
+        dev = open(get_domain_name(domain), O_NONBLOCK);
+        if((dev < 0) && (errno == ENOENT)) {
+          FARF(HIGH, "Device node %s open failed for domain %d (errno %s),"
+                    "falling back to node %s \n",
+                    get_domain_name(domain), domain, strerror(errno),
+                    DEFAULT_DEVICE);
+          dev = open(DEFAULT_DEVICE, O_NONBLOCK);
+        }
+      } else if ((dev < 0) && (errno == EACCES)) {
+         // Open the default device node if unable to open the
+         // secure device node due to permissions
+         FARF(HIGH, "Device node %s open failed for domain %d (errno %s),"
+                   "falling back to node %s \n",
+                   get_secure_domain_name(domain), domain, strerror(errno),
+                   DEFAULT_DEVICE);
+         dev = open(DEFAULT_DEVICE, O_NONBLOCK);
+      }
+      break;
+    case CDSP_DOMAIN_ID:
+       dev = open(get_domain_name(domain), O_NONBLOCK);
+       if((dev < 0) && (errno == ENOENT)) {
+         FARF(HIGH, "Device node %s open failed for domain %d (errno %s),"
+                   "falling back to node %s \n",
+                   get_domain_name(domain), domain, strerror(errno),
+                   get_secure_domain_name(domain));
+         dev = open(get_secure_domain_name(domain), O_NONBLOCK);
+       }
+       break;
+    default:
+      break;
+  }
+
+  if (dev < 0)
+    FARF(ERROR, "Error: Device node open failed for domain %d (errno %s)",
+         domain, strerror(errno));
+
+  return dev;
+}
+
+
+static int get_process_attrs(int domain) {
+	int nErr = 0;
+	uint64 len = 0;
+	int attrs = 0;
+
+	attrs = FASTRPC_PROPERTY_GET_INT32(FASTRPC_PROP_PROCESS, 0);
+	if (!attrs) {
+		const char *env = getenv("ADSP_PROCESS_ATTRS");
+		attrs = env == 0 ? 0 : (int)atoi(env);
+	}
+	fastrpc_trace = FASTRPC_PROPERTY_GET_INT32(FASTRPC_PROP_TRACE, 0);
+	attrs |= hlist[domain].qos.adaptive_qos ? FASTRPC_MODE_ADAPTIVE_QOS : 0;
+	attrs |= hlist[domain].unsigned_module ? FASTRPC_MODE_UNSIGNED_MODULE : 0;
+	return attrs;
+}
+
+static void get_process_testsig(apps_std_FILE *fp, uint64 *ptrlen) {
+   int nErr = 0;
+   uint64 len = 0;
+   char testsig[PROPERTY_VALUE_MAX];
+
+   if (fp == NULL || ptrlen == NULL)
+      return;
+
+   if (FASTRPC_PROPERTY_GET_STR(FASTRPC_PROP_TESTSIG, testsig, NULL)) {
+      FARF(HIGH, "testsig file loading is %s", testsig);
+      nErr = apps_std_fopen_with_env("ADSP_LIBRARY_PATH", ";", testsig, "r", fp);
+      if (nErr == AEE_SUCCESS && *fp != -1)
+         nErr = apps_std_flen(*fp, &len);
+   }
+bail:
+   if (nErr)
+      len = 0;
+   *ptrlen = len;
+   return;
+}
+
+int is_kernel_alloc_supported(int dev, int domain) {
+	return 1;
+}
+
+static int open_shell(int domain_id, apps_std_FILE *fh, int unsigned_shell) {
+   char *absName = NULL;
+   char *shell_absName = NULL;
+   char *domain_str = NULL;
+   uint16 shell_absNameLen = 0, absNameLen = 0;;
+   int nErr = AEE_SUCCESS;
+   int domain = domain_id & DOMAIN_ID_MASK;
+   const char* shell_name = SIGNED_SHELL;
+
+   if (1 == unsigned_shell) {
+     shell_name = UNSIGNED_SHELL;
+   }
+
+   if (domain == MDSP_DOMAIN_ID) {
+      return nErr;
+   }
+   VERIFYC(NULL != (domain_str = (char*)malloc(sizeof(domain))), AEE_ENOMEMORY);
+   snprintf(domain_str, sizeof(domain), "%d",domain);
+
+
+   shell_absNameLen = std_strlen(shell_name) + std_strlen(domain_str) + 1;
+
+   VERIFYC(NULL != (shell_absName = (char*)malloc(sizeof(char) * shell_absNameLen)), AEE_ENOMEMORY);
+   std_strlcpy(shell_absName, shell_name, shell_absNameLen);
+
+   std_strlcat(shell_absName, domain_str, shell_absNameLen);
+
+   absNameLen = std_strlen("/usr/lib/") + shell_absNameLen + 1;
+   VERIFYC(NULL != (absName = (char*)malloc(sizeof(char) * absNameLen)), AEE_ENOMEMORY);
+   std_strlcpy(absName, "/usr/lib/",absNameLen);
+   std_strlcat(absName, shell_absName, absNameLen);
+
+   nErr = apps_std_fopen(absName, "r", fh);
+   if (nErr) {
+      absNameLen = std_strlen("/vendor/dsp/") + shell_absNameLen + 1;
+      VERIFYC(NULL != (absName = (char*)realloc(absName, sizeof(char) * absNameLen)), AEE_ENOMEMORY);
+      std_strlcpy(absName, "/vendor/dsp/",absNameLen);
+      std_strlcat(absName, shell_absName, absNameLen);
+
+      nErr = apps_std_fopen(absName, "r", fh);
+      if (nErr) {
+        FARF(HIGH, "Searching for %s%d ...", shell_name, domain);
+        nErr = apps_std_fopen_with_env("ADSP_LIBRARY_PATH", ";", shell_absName, "r", fh);
+      }
+   }
+   FARF(HIGH, "fopen for shell returned %d", nErr);
+bail:
+   if(domain_str){
+       free(domain_str);
+       domain_str = NULL;
+   }
+   if(shell_absName){
+       free(shell_absName);
+       shell_absName = NULL;
+   }
+   if(absName){
+       free(absName);
+       absName = NULL;
+   }
+   if (nErr != AEE_SUCCESS) {
+       if (domain == SDSP_DOMAIN_ID && fh != NULL) {
+           nErr = AEE_SUCCESS;
+           *fh = -1;
+       } else {
+           FARF(ERROR, "open_shell failed with err %d domain %d\n", nErr, domain);
+       }
+   }
+   return nErr;
+}
+
+int open_device_node(int domain) {
+	int nErr=0;
+
+	VERIFY(!fastrpc_init_once());
+	
+	pthread_mutex_lock(&hlist[domain].mut);
+	if(hlist[domain].dev == -1) {
+		hlist[domain].dev = open_device_node_internal(domain);
+		/* the domain was opened but not apps initialized */
+		hlist[domain].initialized = 0;
+	}
+	pthread_mutex_unlock(&hlist[domain].mut);
+bail:
+	return hlist[domain].dev;
+}
+
+static int apps_dev_init(int domain) {
+	int nErr = AEE_SUCCESS;
+	struct fastrpc_init_create uproc = {0};
+	apps_std_FILE fh = -1;
+	int battach;
+	uint32_t info = domain & DOMAIN_ID_MASK;
+
+	FARF(HIGH, "starting %s for domain %d", __func__, domain);
+	pthread_mutex_lock(&hlist[domain].mut);
+	pthread_setspecific(tlsKey, (void*)&hlist[domain]);
+	battach = hlist[domain].dsppd;
+	if(!hlist[domain].initialized) {
+		if (hlist[domain].dev == -1)
+			hlist[domain].dev = open_device_node_internal(domain);
+
+		VERIFYC(hlist[domain].dev >= 0, AEE_EFOPEN);
+		FARF(HIGH, "%s: device %d opened with info 0x%x (attach %d)", __func__, hlist[domain].dev, hlist[domain].info, battach);
+		hlist[domain].initialized = 1;
+		//keep the memory we used to allocate
+		if (battach == GUEST_OS || battach == GUEST_OS_SHARED) {
+			FARF(HIGH, "%s: attaching to guest OS for domain %d", __func__, domain);
+			VERIFY(!ioctl(hlist[domain].dev, FASTRPC_IOCTL_INIT_ATTACH) || errno == ENOTTY);
+		} else if (battach == USER_PD) {
+			uint64 len = 0;
+			uint64 filelen = 0;
+			int readlen = 0, eof;
+			int procattr = 0;
+			apps_std_FILE fsig = -1;
+			uint64 siglen = 0;
+
+			VERIFY(0 == open_shell(domain, &fh, hlist[domain].unsigned_module));
+
+			hlist[domain].procattrs = get_process_attrs(domain);
+			if (IS_DEBUG_MODE_ENABLED(hlist[domain].procattrs))
+				get_process_testsig(&fsig, &siglen);
+
+			if (fh != -1) {
+				VERIFY(AEE_SUCCESS == (nErr = apps_std_flen(fh, &len)));
+				filelen = len + siglen;
+				VERIFYC(filelen < INT_MAX, AEE_EBADSIZE);
+				pthread_mutex_unlock(&hlist[domain].mut);
+				FARF(HIGH,"debug:file len:%llx",filelen);
+				FARF(HIGH,"debug:file len to rpc malloc:%x",filelen);
+				uproc.file = (__u64)rpcmem_alloc_internal(0, RPCMEM_HEAP_DEFAULT, (int)(filelen));
+				pthread_mutex_lock(&hlist[domain].mut);
+				VERIFYC(uproc.file, AEE_ENORPCMEMORY);
+				VERIFY(AEE_SUCCESS == (nErr = apps_std_fread(fh, (void *)uproc.file, len, &readlen, &eof)));
+				VERIFYC((int)len == readlen, AEE_EFREAD);
+				uproc.filefd = rpcmem_to_fd_internal((void *)uproc.file);
+				uproc.filelen = (int)len;
+				VERIFYC(uproc.filefd != -1, AEE_EINVALIDFD);
+			} else {
+				FARF(ERROR, "Unable to open shell file\n");
+			}
+			uproc.attrs = hlist[domain].procattrs;
+			if(siglen && fsig != -1) {
+				VERIFY(AEE_SUCCESS == (nErr = apps_std_fread(fsig, (byte*)(uproc.file + len), siglen, &readlen, &eof)));
+				VERIFYC(siglen == (uint64)readlen, AEE_EFREAD);
+				uproc.siglen = siglen;
+				uproc.filelen = len + siglen;
+			}
+			nErr = ioctl(hlist[domain].dev, FASTRPC_IOCTL_INIT_CREATE, (unsigned long)&uproc);
+			if (nErr == AEE_SUCCESS) {
+				FARF(HIGH, "Successfully created user PD on domain %d (attrs 0x%x)", domain, hlist[domain].procattrs);
+			}
+		} else {
+			FARF(ERROR, "Error: %s called for unknown mode %d", __func__, battach);
+		}
+	}
+bail:
+	pthread_mutex_unlock(&hlist[domain].mut);
+	if(uproc.file) {
+		rpcmem_free_internal((void*)uproc.file);
+	}
+	if(fh != -1) {
+		apps_std_fclose(fh);
+	}
+	if(nErr != AEE_SUCCESS) {
+		domain_deinit(domain);
+		FARF(ERROR, "Error 0x%x: %s failed for domain %d, errno %s\n", nErr, __func__, domain, strerror(errno));
+	}
+	FARF(HIGH, "Done with %s, err: 0x%x, dev: %d", __func__, nErr, hlist[domain].dev);
+	return nErr;
+}
+
+__attribute__((destructor))
+static void close_dev(void) {
+	int i;
+	for(i = 0; i < NUM_DOMAINS_EXTEND; i++) {
+		domain_deinit(i);
+	}
+	pl_deinit();
+	PL_DEINIT(fastrpc_apps_user);
+}
+
+remote_handle64 get_adsp_current_process1_handle(int domain) {
+   struct handle_info* hinfo;
+   int nErr = AEE_SUCCESS;
+
+   VERIFYC(hlist[domain].domainsupport, AEE_EBADDOMAIN);
+   if(hlist[domain].cphandle) {
+      return hlist[domain].cphandle;
+   }
+   VERIFY(AEE_SUCCESS == (nErr = alloc_handle(domain, _const_adsp_current_process1_handle, &hinfo)));
+   hlist[domain].cphandle = hinfo->local;
+   return hlist[domain].cphandle;
+bail:
+   if (nErr != AEE_SUCCESS) {
+        if (hlist[domain].domainsupport)
+		FARF(ERROR, "Error %x: adsp current process handle failed. domain %d\n", nErr, domain);
+	else if (!hlist[domain].nondomainsupport)
+		FARF(ERROR, "Error %x: adsp current process handle failed. domain %d\n", nErr, domain);
+   }
+   return INVALID_HANDLE;
+}
+
+remote_handle64 get_adspmsgd_adsp1_handle(int domain) {
+   struct handle_info* hinfo;
+   int nErr = AEE_SUCCESS;
+
+   VERIFYC(hlist[domain].domainsupport, AEE_EBADDOMAIN);
+   if(hlist[domain].msghandle) {
+      return hlist[domain].msghandle;
+   }
+   VERIFY(AEE_SUCCESS == (nErr = alloc_handle(domain, _const_adspmsgd_adsp1_handle, &hinfo)));
+   hlist[domain].msghandle = hinfo->local;
+   return hlist[domain].msghandle;
+bail:
+   if (nErr != AEE_SUCCESS) {
+        FARF(ERROR,"Error %x: get adsp msgd handle failed. domain %d\n", nErr, domain);
+   }
+   return INVALID_HANDLE;
+}
+
+static int open_dev(int domain) {
+   static pthread_once_t pl = PTHREAD_ONCE_INIT;
+   int init = 0, nErr = AEE_SUCCESS;
+
+   if(hlist && hlist[domain].dev != -1 && hlist[domain].initialized) {
+      if(0 == pthread_getspecific(tlsKey)) {
+         pthread_setspecific(tlsKey, (void*)&hlist[domain]);
+      }
+      goto bail;
+   }
+   VERIFY(AEE_SUCCESS == (nErr = fastrpc_init_once()));
+   VERIFY(AEE_SUCCESS == (nErr = pthread_once(&pl, (void*)pl_init)));
+   init = 1;
+   pthread_mutex_lock(&hlist[domain].init);
+   if(hlist && hlist[domain].dev != -1 && hlist[domain].initialized) {
+      goto bail;
+   }
+   VERIFY(AEE_SUCCESS == (nErr = apps_dev_init(domain)));
+   VERIFY(AEE_SUCCESS == (nErr = listener_android_domain_init(domain)));
+   initFileWatcher(domain); // Ignore errors
+   if(hlist){
+      fastrpc_perf_init(hlist[domain].dev);
+      VERIFY(AEE_SUCCESS == (nErr = fastrpc_latency_init(hlist[domain].dev, &hlist[domain].qos)));
+   }
+   if (hlist[domain].th_params.prio != DEFAULT_UTHREAD_PRIORITY || hlist[domain].th_params.stack_size != DEFAULT_UTHREAD_STACK_SIZE) {
+      struct fastrpc_thread_params *uthread_params = &hlist[domain].th_params;
+
+      VERIFY(AEE_SUCCESS == (nErr = pthread_create(&uthread_params->thread, NULL, fastrpc_set_remote_uthread_params, (void*)uthread_params)));
+      VERIFY(AEE_SUCCESS == (nErr = pthread_join(uthread_params->thread, NULL)));
+	  FARF(ALWAYS, "%s: Successfully set remote user thread priority to %d and stack size to %d",
+				__func__, uthread_params->prio, uthread_params->stack_size);
+   }
+
+bail:
+   if(init) {
+      pthread_mutex_unlock(&hlist[domain].init);
+   }
+   if(nErr != AEE_SUCCESS) {
+      domain_deinit(domain);
+      if(hlist)
+	  FARF(ERROR, "Error %x: open dev %d for domain %d failed\n", nErr, hlist[domain].dev, domain);
+      return -1;
+   }
+   if(hlist){
+       FARF(HIGH, "done open dev %d err %d", hlist[domain].dev, nErr);
+       return hlist[domain].dev;
+   } else {
+       return -1;
+   }
+}
+
+static void fastrpc_apps_user_deinit(void) {
+   QNode *pn;
+   int i;
+   if(tlsKey != INVALID_KEY) {
+      pthread_key_delete(tlsKey);
+      tlsKey = INVALID_KEY;
+   }
+   PL_DEINIT(apps_mem);
+   PL_DEINIT(apps_std);
+   PL_DEINIT(rpcmem);
+   if(hlist) {
+      for (i = 0; i < NUM_DOMAINS_EXTEND; i++) {
+         while((pn = QList_Pop(&hlist[i].ql))) {
+            struct handle_info* h = STD_RECOVER_REC(struct handle_info, qn, pn);
+            free(h);
+            h = NULL;
+         }
+         pthread_mutex_destroy(&hlist[i].mut);
+         pthread_mutex_destroy(&hlist[i].init);
+      }
+      free(hlist);
+      hlist = NULL;
+   }
+   pthread_mutex_destroy(&fdlist.mut);
+   return;
+}
+
+static void exit_thread(void *value)
+{
+   remote_handle64 handle;
+   struct handle_list* list = (struct handle_list*)value;
+   int domain;
+
+   if(!hlist) {
+      return;
+   }
+   domain = (int)(list - &hlist[0]);
+   if(hlist[domain].dev != -1) {
+      FARF(HIGH, "exiting thread domain: %d", domain);
+      if((domain < NUM_DOMAINS_EXTEND) &&
+         (handle = get_adsp_current_process1_handle(domain)) != INVALID_HANDLE) {
+         (void)adsp_current_process1_thread_exit(handle);
+      } else if (domain == DEFAULT_DOMAIN_ID) {
+         (void)adsp_current_process_thread_exit();
+      }
+   }
+}
+
+static int fastrpc_apps_user_init() {
+	int nErr = AEE_SUCCESS, i;
+
+	pthread_mutexattr_t attr;
+	pthread_mutexattr_init(&attr);
+	pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
+	pthread_mutex_init(&fdlist.mut, 0);
+	QList_Ctor(&fdlist.ql);
+	std_memset(dhandles, 0, sizeof(dhandles));
+	VERIFYC(NULL != (hlist = calloc(NUM_DOMAINS_EXTEND, sizeof(*hlist))), AEE_ENOMEMORY);
+	for (i = 0; i < NUM_DOMAINS_EXTEND; i++) {
+		hlist[i].dev = -1;
+		hlist[i].domainsupport = 0;
+		hlist[i].nondomainsupport = 0;
+		hlist[i].kmem_support = 0;
+		hlist[i].th_params.prio = DEFAULT_UTHREAD_PRIORITY;
+		hlist[i].th_params.stack_size = DEFAULT_UTHREAD_STACK_SIZE;
+		hlist[i].th_params.reqID = 0;
+		hlist[i].dsppd = attach_guestos(i);
+		hlist[i].dsppdname = NULL;
+		pthread_mutex_init(&hlist[i].mut, &attr);
+		pthread_mutex_init(&hlist[i].init, 0);
+		QList_Ctor(&hlist[i].ql);
+	}
+	pthread_mutexattr_destroy(&attr);
+	VERIFY(AEE_SUCCESS == (nErr = pthread_key_create(&tlsKey, exit_thread)));
+	VERIFY(AEE_SUCCESS == (nErr = PL_INIT(rpcmem)));
+	VERIFY(AEE_SUCCESS == (nErr = PL_INIT(apps_mem)));
+	VERIFY(AEE_SUCCESS == (nErr = PL_INIT(apps_std)));
+	GenCrc32Tab(POLY32, crc_table);
+bail:
+	if(nErr) {
+		FARF(ERROR, "Error %x: fastrpc_apps_user_init failed\n", nErr);
+		fastrpc_apps_user_deinit();
+	}
+	return nErr;
+}
+
+PL_DEFINE(fastrpc_apps_user, fastrpc_apps_user_init, fastrpc_apps_user_deinit);
+
+static void frpc_init(void) {
+   PL_INIT(fastrpc_apps_user);
+}
+
+static int fastrpc_init_once(void) {
+   static pthread_once_t frpc = PTHREAD_ONCE_INIT;
+   int nErr = AEE_SUCCESS;
+   VERIFY(AEE_SUCCESS == (nErr = pthread_once(&frpc, (void*)frpc_init)));
+bail:
+   if(nErr != AEE_SUCCESS) {
+	FARF(ERROR, "Error %x: fastrpc init once failed\n", nErr);
+   }
+   return nErr == AEE_SUCCESS ? _pl_fastrpc_apps_user()->nErr : nErr;
+}
+
+static int rpcmem_init_me(void) {
+   rpcmem_init();
+   return AEE_SUCCESS;
+}
+PL_DEFINE(rpcmem, rpcmem_init_me, rpcmem_deinit);
diff --git a/src/fastrpc_perf.c b/src/fastrpc_perf.c
new file mode 100644
index 0000000..415830b
--- /dev/null
+++ b/src/fastrpc_perf.c
@@ -0,0 +1,217 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#define FARF_ERROR 1
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include "HAP_farf.h"
+#include "verify.h"
+#include "remote.h"
+#include "rpcmem.h"
+#include "AEEstd.h"
+#include "adsp_perf.h"
+#include "fastrpc_perf.h"
+#include "fastrpc_internal.h"
+#include "fastrpc_apps_user.h"
+
+
+#ifdef ANDROID_P
+#define PERF_KEY_KERNEL "vendor.fastrpc.perf.kernel"
+#define PERF_KEY_ADSP   "vendor.fastrpc.perf.adsp"
+#define PERF_KEY_FREQ   "vendor.fastrpc.perf.freq"
+#else
+#define PERF_KEY_KERNEL "fastrpc.perf.kernel"
+#define PERF_KEY_ADSP   "fastrpc.perf.adsp"
+#define PERF_KEY_FREQ   "fastrpc.perf.freq"
+#endif
+
+#define PERF_MODE 2
+#define PERF_OFF 0
+#define PERF_KERNEL_MASK (0x1)
+#define PERF_ADSP_MASK (0x2)
+#define PERF_KEY_STR_MAX (2*1024)
+#define PERF_MAX_NUM_KEYS 64
+
+#define PERF_NS_TO_US(n) ((n)/1000)
+
+#define IS_KEY_ENABLED(name) (!std_strncmp((name), "perf_invoke_count", 17) || \
+                              !std_strncmp((name), "perf_mod_invoke", 15) || \
+                              !std_strncmp((name), "perf_rsp", 8) || \
+                              !std_strncmp((name), "perf_hdr_sync_flush", 19) || \
+                              !std_strncmp((name), "perf_sync_flush", 15) || \
+                              !std_strncmp((name), "perf_hdr_sync_inv", 17) || \
+                              !std_strncmp((name), "perf_sync_inv", 13)) \
+
+struct perf_keys {
+   int64 data[PERF_MAX_NUM_KEYS];
+   int numKeys;
+   int maxLen;
+   int enable;
+   char *keys;
+};
+
+struct fastrpc_perf {
+   int count;
+   int freq;
+   int perf_on;
+   struct perf_keys kernel;
+   struct perf_keys dsp;
+};
+struct fastrpc_perf gperf;
+
+static int perf_kernel_getkeys(int dev) {
+   int nErr = 0;
+bail:
+   return nErr;
+}
+
+static void get_perf_kernel(int dev, remote_handle handle, uint32_t sc) {
+bail:
+   return;
+}
+
+static void get_perf_adsp(remote_handle handle, uint32_t sc) {
+   int nErr = 0;
+   struct fastrpc_perf *p = &gperf;
+   struct perf_keys *pdsp = &gperf.dsp;
+   int ii;
+   char *token;
+
+   char *keystr = pdsp->keys;
+   VERIFY(0 == adsp_perf_get_usecs(pdsp->data, PERF_MAX_NUM_KEYS));
+   VERIFY(pdsp->maxLen < PERF_KEY_STR_MAX);
+   VERIFY(pdsp->numKeys < PERF_MAX_NUM_KEYS);
+   FARF(ALWAYS, "\nFastRPC dsp perf for handle 0x%x sc 0x%x\n", handle, sc);
+   for(ii = 0; ii < pdsp->numKeys; ii++) {
+      token = keystr;
+      keystr += strlen(token) + 1;
+      VERIFY(token);
+      if (!pdsp->data[ii])
+         continue;
+      if (!std_strncmp(token, "perf_invoke_count",17)) {
+         FARF(ALWAYS, "fastrpc.dsp.%-20s : %lld \n", token, pdsp->data[ii]);
+      } else {
+         FARF(ALWAYS, "fastrpc.dsp.%-20s : %lld us\n", token, pdsp->data[ii]);
+      }
+   }
+bail:
+   return;
+}
+
+void fastrpc_perf_update(int dev, remote_handle handle, uint32_t sc) {
+   int nErr = 0;
+   struct fastrpc_perf *p = &gperf;
+
+   if (!(p->perf_on && !IS_STATIC_HANDLE(handle) && p->freq > 0))
+      return;
+
+   p->count++;
+   if (p->count % p->freq != 0)
+      return;
+
+   if (p->kernel.enable)
+      get_perf_kernel(dev, handle, sc);
+
+   if (p->dsp.enable)
+      get_perf_adsp(handle, sc);
+bail:
+   return;
+}
+
+static int perf_dsp_enable(void) {
+   int nErr = 0;
+   int numKeys = 0, maxLen = 0;
+   char *keys = NULL;
+   int ii;
+
+   keys = (char *)rpcmem_alloc_internal(0, RPCMEM_HEAP_DEFAULT, PERF_KEY_STR_MAX);
+   VERIFY(gperf.dsp.keys = keys);
+   std_memset(keys, 0, PERF_KEY_STR_MAX);
+   
+   VERIFY(0 == adsp_perf_get_keys(keys, PERF_KEY_STR_MAX, &maxLen, &numKeys));
+   VERIFY(maxLen < PERF_KEY_STR_MAX);
+   gperf.dsp.maxLen = maxLen;
+   gperf.dsp.numKeys = numKeys;
+   for(ii = 0; ii < numKeys; ii++) {
+      char *name = keys;
+      keys += strlen(name) + 1;
+      if (IS_KEY_ENABLED(name))
+         VERIFY(0 == adsp_perf_enable(ii));
+   }
+   FARF(HIGH, "keys enable done maxLen %d numKeys %d", maxLen, numKeys);
+bail:
+   return nErr;
+}
+
+int fastrpc_perf_init(int dev) {
+   int nErr = 0;
+   struct fastrpc_perf *p = &gperf;
+   struct perf_keys *pk = &gperf.kernel;
+   struct perf_keys *pd = &gperf.dsp;
+
+   pk->enable = FASTRPC_PROPERTY_GET_INT32(PERF_KEY_KERNEL, 0);
+   pd->enable = FASTRPC_PROPERTY_GET_INT32(PERF_KEY_ADSP, 0);
+   p->perf_on = (pk->enable || pd->enable) ? PERF_MODE : PERF_OFF;
+   p->freq = FASTRPC_PROPERTY_GET_INT32(PERF_KEY_FREQ, 1000);
+   VERIFY(p->freq > 0);
+
+   p->count = 0;
+   if (pk->enable) {
+      //VERIFY(!ioctl(dev, FASTRPC_IOCTL_SETMODE, PERF_MODE));
+      VERIFY(NULL != (pk->keys = (char *)calloc(sizeof(char), PERF_KEY_STR_MAX)));
+      VERIFY(0 == perf_kernel_getkeys(dev));
+   }
+
+   if (pd->enable)
+      perf_dsp_enable();
+bail:
+   if (nErr) {
+      FARF(HIGH, "fastrpc perf init failed");
+      p->perf_on = 0;
+   }
+   return nErr;
+}
+
+void fastrpc_perf_deinit(void) {
+   struct fastrpc_perf *p = &gperf;
+   if (p->kernel.keys){
+      free(p->kernel.keys);
+      p->kernel.keys = NULL;
+   }
+   if (p->dsp.keys){
+      rpcmem_free_internal(p->dsp.keys);
+      p->dsp.keys = NULL;
+   }
+   return;
+}
+
diff --git a/src/gpls.c b/src/gpls.c
new file mode 100644
index 0000000..4e94b13
--- /dev/null
+++ b/src/gpls.c
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "HAP_farf.h"
+#include "pls.h"
+#include "HAP_pls.h"
+#include "adsp_pls.h"
+#include "platform_libs.h"
+#include "version.h"
+
+static struct pls_table gpls;
+const char pls_version[] = VERSION_STRING ;
+int gpls_init(void) {
+   pls_ctor(&gpls, 1);
+   return 0;
+}
+
+void gpls_deinit(void) {
+   pls_thread_deinit(&gpls);
+}
+
+int HAP_pls_add(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo) {
+   return pls_add(&gpls, type, key, size, ctor, ctx, dtor, ppo);
+}
+
+int HAP_pls_add_lookup(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo) {
+   return pls_add_lookup_singleton(&gpls, type, key, size, ctor, ctx, dtor, ppo);
+}
+
+int HAP_pls_lookup(uintptr_t type, uintptr_t key, void** ppo) {
+   return pls_lookup(&gpls, type, key, ppo);
+}
+
+int adsp_pls_add(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo) {
+   return pls_add(&gpls, type, key, size, ctor, ctx, dtor, ppo);
+}
+
+int adsp_pls_add_lookup(uintptr_t type, uintptr_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void*), void** ppo) {
+   return pls_add_lookup_singleton(&gpls, type, key, size, ctor, ctx, dtor, ppo);
+}
+
+int adsp_pls_lookup(uintptr_t type, uintptr_t key, void** ppo) {
+   return pls_lookup(&gpls, type, key, ppo);
+}
+
+
+PL_DEFINE(gpls, gpls_init, gpls_deinit)
diff --git a/src/listener_android.c b/src/listener_android.c
new file mode 100644
index 0000000..00729f4
--- /dev/null
+++ b/src/listener_android.c
@@ -0,0 +1,474 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+//#include "qurt_mutex.h"
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <assert.h>
+#include <pthread.h>
+#include <dlfcn.h>
+#include <stdlib.h>
+#include <sys/eventfd.h>
+
+#include "platform_libs.h"
+#include "HAP_farf.h"
+#include "verify.h"
+#include "mod_table.h"
+#include "remote_priv.h"
+#include "rpcmem.h"
+#include "adsp_listener.h"
+#include "listener_buf.h"
+#include "shared.h"
+#include "AEEstd.h"
+#include "fastrpc_apps_user.h"
+#include "AEEStdErr.h"
+
+#define LOGL(format, ...) VERIFY_PRINT_INFO(format, ##__VA_ARGS__)
+#ifndef MALLOC
+#define MALLOC malloc
+#endif
+
+#ifndef CALLOC
+#define CALLOC calloc
+#endif
+
+#ifndef FREE
+#define FREE free
+#endif
+
+#ifndef REALLOC
+#define REALLOC realloc
+#endif
+
+#ifndef FREEIF
+#define FREEIF(pv) \
+   do {\
+      if(pv) { \
+         void* tmp = (void*)pv;\
+         pv = 0;\
+         FREE(tmp);\
+      } \
+   } while(0)
+#endif
+
+#include <unistd.h>
+#include <stdio.h>
+#include <string.h>
+#include <errno.h>
+#include <unistd.h>
+#include <sys/eventfd.h>
+
+struct listener {
+   pthread_t thread;
+   int eventfd;
+};
+
+static struct listener linfo[NUM_DOMAINS_EXTEND] =
+{ [0 ... NUM_DOMAINS_EXTEND - 1] = { .thread = 0, .eventfd = -1 } };
+
+//TODO: fix this to work over any number of buffers
+//      needs qaic to support extra buffers
+#define MAX_BUFS 250
+struct invoke_bufs {
+   adsp_listener_buffer outbufs[MAX_BUFS];
+   adsp_listener_buffer inbufs[MAX_BUFS];
+   int inbufLenReqs[MAX_BUFS];
+   int outbufLenReqs[MAX_BUFS];
+   remote_arg args[2*MAX_BUFS];
+};
+
+extern void set_thread_context(int domain);
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_remotectl_open)(const char* name, uint32* handle, char* dlStr, int dlerrorLen, int* dlErr) __QAIC_IMPL_ATTRIBUTE
+{
+   return mod_table_open(name, handle, dlStr, dlerrorLen, dlErr);
+}
+
+__QAIC_IMPL_EXPORT int __QAIC_IMPL(apps_remotectl_close)(uint32 handle, char* errStr, int errStrLen, int* dlErr) __QAIC_IMPL_ATTRIBUTE
+{
+   return mod_table_close(handle, errStr, errStrLen, dlErr);
+}
+
+#define RPC_FREEIF(heapid, buf) \
+do {\
+   if(heapid == -1)  {\
+      FREEIF(buf);\
+   } else {\
+      if(buf) {\
+         rpcmem_free_internal(buf);\
+         buf = 0;\
+      }\
+   }\
+} while (0)
+
+static __inline void* rpcmem_realloc(int heapid, uint32 flags, void* buf, int oldsize, int size) {
+   if(heapid == -1) {
+      return REALLOC(buf, size);
+   } else {
+      void* bufnew = rpcmem_alloc_internal(heapid, flags, size);
+      if(buf && bufnew) {
+         memmove(bufnew, buf, oldsize);
+         rpcmem_free_internal(buf);
+         buf = NULL;
+      }
+      return bufnew;
+   }
+}
+
+static void* listener(void* arg) {
+   struct listener* me = (struct listener*)arg;
+   int numOutBufs = 0;
+   int nErr = AEE_SUCCESS;
+   adsp_listener_invoke_ctx ctx = 0;
+   struct invoke_bufs* bufs = 0;
+   boolean bNeedMore;
+   int result = -1;
+   adsp_listener_remote_handle handle;
+   uint32 sc;
+   int ii, inBufsAllocated = 0;
+   const char* eheap = getenv("ADSP_LISTENER_HEAP_ID");
+   int heapid = eheap == 0 ? 0 : (uint32)atoi(eheap);
+   const char* eflags = getenv("ADSP_LISTENER_HEAP_FLAGS");
+   uint32 flags = eflags == 0 ? RPCMEM_HEAP_DEFAULT : (uint32)atoi(eflags);
+
+   if(eheap || eflags) {
+      FARF(HIGH, "listener using ion heap: %d flags: %x\n", (int)heapid, (int)flags);
+   }
+
+   VERIFYC(NULL != (bufs = rpcmem_realloc(heapid, flags, 0, 0, sizeof(*bufs))), AEE_ENORPCMEMORY);
+   memset(bufs, 0, sizeof(*bufs));
+   set_thread_context((int)(me - &linfo[0]));
+
+   do {
+ invoke:
+      bNeedMore = FALSE;
+      sc = 0xffffffff;
+      if(result != AEE_SUCCESS) {
+         numOutBufs = 0;
+      }
+      nErr = __QAIC_HEADER(adsp_listener_next_invoke)(
+                        ctx, result, bufs->outbufs, numOutBufs, &ctx,
+                        &handle, &sc, bufs->inbufs, inBufsAllocated,
+                        bufs->inbufLenReqs, MAX_BUFS, bufs->outbufLenReqs, MAX_BUFS);
+      if(nErr) {
+         VERIFY_EPRINTF("listener protocol failure %x\n", nErr);
+         VERIFY(AEE_SUCCESS == (nErr = __QAIC_HEADER(adsp_listener_next_invoke)(
+                        ctx, nErr, 0, 0, &ctx,
+                        &handle, &sc, bufs->inbufs, inBufsAllocated,
+                        bufs->inbufLenReqs, MAX_BUFS, bufs->outbufLenReqs, MAX_BUFS)));
+      }
+
+      if(MAX_BUFS < REMOTE_SCALARS_INBUFS(sc) || MAX_BUFS < REMOTE_SCALARS_OUTBUFS(sc)) {
+         result = AEE_EMAXBUFS;
+         goto invoke;
+      }
+      for(ii = 0; ii < (int)REMOTE_SCALARS_INBUFS(sc); ++ii) {
+         if(bufs->inbufs[ii].dataLen < bufs->inbufLenReqs[ii]) {
+            if(0 != bufs->inbufLenReqs[ii]) {
+               bufs->inbufs[ii].data = rpcmem_realloc(heapid, flags, bufs->inbufs[ii].data,  bufs->inbufs[ii].dataLen, bufs->inbufLenReqs[ii]);
+               if(0 == bufs->inbufs[ii].data) {
+                  bufs->inbufs[ii].dataLen = 0;
+                  result = AEE_ENORPCMEMORY;
+                  goto invoke;
+               }
+            }
+            bufs->inbufs[ii].dataLen = bufs->inbufLenReqs[ii];
+            inBufsAllocated = STD_MAX(inBufsAllocated, ii + 1);
+            bNeedMore = TRUE;
+         }
+         bufs->args[ii].buf.pv = bufs->inbufs[ii].data;
+         bufs->args[ii].buf.nLen = bufs->inbufLenReqs[ii];
+      }
+      for(ii = 0; ii < (int)REMOTE_SCALARS_OUTBUFS(sc); ++ii) {
+         if(bufs->outbufs[ii].dataLen < bufs->outbufLenReqs[ii]) {
+            if(0 !=  bufs->outbufLenReqs[ii]) {
+               bufs->outbufs[ii].data = rpcmem_realloc(heapid, flags, bufs->outbufs[ii].data, bufs->outbufs[ii].dataLen, bufs->outbufLenReqs[ii]);
+               if(0 == bufs->outbufs[ii].data) {
+                  result = AEE_ENORPCMEMORY;
+                  goto invoke;
+               }
+            }
+            bufs->outbufs[ii].dataLen = bufs->outbufLenReqs[ii];
+         }
+         bufs->args[ii + REMOTE_SCALARS_INBUFS(sc)].buf.pv = bufs->outbufs[ii].data;
+         bufs->args[ii + REMOTE_SCALARS_INBUFS(sc)].buf.nLen = bufs->outbufLenReqs[ii];
+      }
+      numOutBufs = REMOTE_SCALARS_OUTBUFS(sc);
+      if(bNeedMore) {
+         assert(inBufsAllocated >= REMOTE_SCALARS_INBUFS(sc));
+         if(0 != (result = __QAIC_HEADER(adsp_listener_invoke_get_in_bufs)(ctx, bufs->inbufs,
+                                                                  REMOTE_SCALARS_INBUFS(sc)))) {
+            FARF(HIGH, "adsp_listener_invoke_get_in_bufs failed  %x\n", result);
+            goto invoke;
+         }
+      }
+
+      result = mod_table_invoke(handle, sc, bufs->args);
+   } while(1);
+bail:
+   for(ii = 0; ii < MAX_BUFS && bufs; ++ii) {
+      RPC_FREEIF(heapid, bufs->outbufs[ii].data);
+      RPC_FREEIF(heapid, bufs->inbufs[ii].data);
+   }
+   RPC_FREEIF(heapid, bufs);
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: listener thread exiting\n", nErr);
+   }
+   return (void*)(uintptr_t)nErr;
+}
+
+static int listener_start_thread(struct listener* me) {
+   return pthread_create(&me->thread, 0, listener, (void*)me);
+}
+#define MIN_BUF_SIZE 0x1000
+#define ALIGNB(sz) ((sz) == 0 ? MIN_BUF_SIZE : _SBUF_ALIGN((sz), MIN_BUF_SIZE))
+
+static void* listener2(void* arg) {
+   struct listener* me = (struct listener*)arg;
+   int nErr = AEE_SUCCESS;
+   adsp_listener_invoke_ctx ctx = 0;
+   uint8* outBufs = 0;
+   int outBufsLen = 0, outBufsCapacity = 0;
+   uint8* inBufs = 0;
+   int inBufsLen = 0, inBufsLenReq = 0;
+   int result = -1;
+   adsp_listener_remote_handle handle = -1;
+   uint32 sc = 0;
+   const char* eheap = getenv("ADSP_LISTENER_HEAP_ID");
+   int heapid = eheap == 0 ? -1 : atoi(eheap);
+   const char* eflags = getenv("ADSP_LISTENER_HEAP_FLAGS");
+   uint32 flags = eflags == 0 ? 0 : (uint32)atoi(eflags);
+   const char* emin = getenv("ADSP_LISTENER_MEM_CACHE_SIZE");
+   int cache_size = emin == 0 ? 0 : atoi(emin);
+   remote_arg args[512];
+   struct sbuf buf;
+   eventfd_t event = 0xff;
+
+   memset(args, 0, sizeof(args));
+   set_thread_context((int)(me - &linfo[0]));
+   if(eheap || eflags || emin) {
+      FARF(HIGH, "listener using ion heap: %d flags: %x cache: %lld\n", (int)heapid, (int)flags, cache_size);
+   }
+
+   do {
+ invoke:
+      sc = 0xffffffff;
+      if(result != 0) {
+         outBufsLen = 0;
+      }
+      FARF(HIGH, "responding message for %x %x %x %x", ctx, handle, sc, result);
+      nErr = __QAIC_HEADER(adsp_listener_next2)(
+                        ctx, result, outBufs, outBufsLen,
+                        &ctx, &handle, &sc, inBufs, inBufsLen, &inBufsLenReq);
+      FARF(HIGH, "got message for %x %x %x %x", ctx, handle, sc, nErr);
+      if(nErr) {
+         VERIFY_EPRINTF("listener protocol failure %x\n", nErr);
+         if (nErr == AEE_EINTERRUPTED) {
+            goto invoke;
+         }
+         VERIFY(0 == (nErr = __QAIC_HEADER(adsp_listener_next2)(
+                        ctx, nErr, 0, 0,
+                        &ctx, &handle, &sc, inBufs, inBufsLen,
+                        &inBufsLenReq)));
+      }
+      if(ALIGNB(inBufsLenReq * 2) < inBufsLen && inBufsLen > cache_size) {
+         void* buf;
+         int size = ALIGNB(inBufsLenReq * 2);
+         if(NULL == (buf = rpcmem_realloc(heapid, flags, inBufs, inBufsLen, size))) {
+            result = AEE_ENORPCMEMORY;
+            FARF(HIGH, "rpcmem_realloc shrink failed");
+            goto invoke;
+         }
+         inBufs = buf;
+         inBufsLen = size;
+      }
+      if(inBufsLenReq > inBufsLen) {
+         void* buf;
+         int req;
+         int oldLen = inBufsLen;
+         int size = _SBUF_ALIGN(inBufsLenReq, MIN_BUF_SIZE);
+         if(AEE_SUCCESS == (buf = rpcmem_realloc(heapid, flags, inBufs, inBufsLen, size))) {
+            result = AEE_ENORPCMEMORY;
+            FARF(ERROR, "rpcmem_realloc failed");
+            goto invoke;
+         }
+         inBufs = buf;
+         inBufsLen = size;
+         if(0 != (result = __QAIC_HEADER(adsp_listener_get_in_bufs2)(ctx, oldLen,
+                                                                     inBufs + oldLen,
+                                                                     inBufsLen - oldLen, &req))) {
+            FARF(HIGH, "adsp_listener_invoke_get_in_bufs2 failed  %x", result);
+            goto invoke;
+         }
+         if(req > inBufsLen) {
+            result = AEE_EBADSIZE;
+            FARF(HIGH, "adsp_listener_invoke_get_in_bufs2 failed  %x", result);
+            goto invoke;
+         }
+      }
+      if(REMOTE_SCALARS_INHANDLES(sc) + REMOTE_SCALARS_OUTHANDLES(sc) > 0) {
+         result = AEE_EINVARGS;
+         goto invoke;
+      }
+
+      sbuf_init(&buf, 0, inBufs, inBufsLen);
+      unpack_in_bufs(&buf, args,  REMOTE_SCALARS_INBUFS(sc));
+      unpack_out_lens(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
+
+      sbuf_init(&buf, 0, 0, 0);
+      pack_out_bufs(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
+      outBufsLen = sbuf_needed(&buf);
+
+      if(ALIGNB(outBufsLen*2) < outBufsCapacity && outBufsCapacity > cache_size) {
+         void* buf;
+         int size = ALIGNB(outBufsLen*2);
+         if(NULL == (buf = rpcmem_realloc(heapid, flags, outBufs, outBufsCapacity, size))) {
+            result = AEE_ENORPCMEMORY;
+            FARF(HIGH, "listener rpcmem_realloc shrink failed");
+            goto invoke;
+         }
+         outBufs = buf;
+         outBufsCapacity = size;
+      }
+      if(outBufsLen > outBufsCapacity) {
+         void* buf;
+         int size = ALIGNB(outBufsLen);
+         if(NULL == (buf = rpcmem_realloc(heapid, flags, outBufs, outBufsCapacity, size))) {
+            result = AEE_ENORPCMEMORY;
+            FARF(ERROR, "listener rpcmem_realloc failed");
+            goto invoke;
+         }
+         outBufs = buf;
+         outBufsLen = size;
+         outBufsCapacity = size;
+      }
+      sbuf_init(&buf, 0, outBufs, outBufsLen);
+      pack_out_bufs(&buf, args + REMOTE_SCALARS_INBUFS(sc), REMOTE_SCALARS_OUTBUFS(sc));
+
+      result = mod_table_invoke(handle, sc, args);
+   } while(1);
+bail:
+   RPC_FREEIF(heapid, outBufs);
+   RPC_FREEIF(heapid, inBufs);
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: listener thread exited", nErr);
+   }
+   eventfd_write(me->eventfd, event);
+   dlerror();
+   return (void*)(uintptr_t)nErr;
+}
+static int listener_start_thread2(struct listener* me) {
+   return pthread_create(&me->thread, 0, listener2, (void*)me);
+}
+
+extern int apps_remotectl_skel_invoke(uint32 _sc, remote_arg* _pra);
+extern int apps_std_skel_invoke(uint32 _sc, remote_arg* _pra);
+extern int apps_mem_skel_invoke(uint32 _sc, remote_arg* _pra);
+extern int adspmsgd_apps_skel_invoke(uint32_t _sc, remote_arg* _pra);
+
+#include "adsp_listener_stub.c"
+PL_DEP(mod_table)
+PL_DEP(apps_std);
+
+void listener_android_deinit(void) {
+   PL_DEINIT(mod_table);
+   PL_DEINIT(apps_std);
+}
+
+int listener_android_init(void) {
+   int nErr = 0;
+
+   VERIFY(AEE_SUCCESS == (nErr = PL_INIT(mod_table)));
+   VERIFY(AEE_SUCCESS == (nErr = PL_INIT(apps_std)));
+   VERIFY(AEE_SUCCESS == (nErr = mod_table_register_const_handle(0, "apps_remotectl", apps_remotectl_skel_invoke)));
+   VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("apps_std", apps_std_skel_invoke)));
+   VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("apps_mem", apps_mem_skel_invoke)));
+   VERIFY(AEE_SUCCESS == (nErr = mod_table_register_static("adspmsgd_apps", adspmsgd_apps_skel_invoke)));
+bail:
+   if(nErr != AEE_SUCCESS) {
+      listener_android_deinit();
+      VERIFY_EPRINTF("Error %x: fastrpc listener initialization error", nErr);
+   }
+   return nErr;
+}
+
+void listener_android_domain_deinit(int domain) {
+   struct listener* me = &linfo[domain];
+
+   FARF(HIGH, "fastrpc listener joining to exit");
+   if(me->thread) {
+      pthread_join(me->thread, 0);
+      me->thread = 0;
+   }
+   FARF(HIGH, "fastrpc listener joined");
+   if(me->eventfd != -1) {
+      close(me->eventfd);
+      me->eventfd = -1;
+   }
+}
+
+int listener_android_domain_init(int domain) {
+   struct listener* me = &linfo[domain];
+   int nErr = 0;
+
+   VERIFYC(-1 != (me->eventfd = eventfd(0, 0)), AEE_EINVALIDFD);
+   nErr = __QAIC_HEADER(adsp_listener_init2)();
+   if(AEE_EUNSUPPORTEDAPI == nErr) {
+      FARF(HIGH, "listener2 initialization error falling back to listener1 %x", nErr);
+      VERIFY(AEE_SUCCESS == (nErr = __QAIC_HEADER(adsp_listener_init)()));
+      VERIFY(AEE_SUCCESS == (nErr = listener_start_thread(me)));
+   } else if(AEE_SUCCESS == nErr) {
+      FARF(HIGH, "listener2 initialized for domain %d", domain);
+      VERIFY(AEE_SUCCESS == (nErr = listener_start_thread2(me)));
+   }
+
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: listener android domain init failed. domain %d\n", nErr, domain);
+      listener_android_domain_deinit(domain);
+   }
+   return nErr;
+}
+
+int listener_android_geteventfd(int domain, int *fd) {
+   struct listener* me = &linfo[domain];
+   int nErr = 0;
+
+   VERIFYC(-1 != me->eventfd, AEE_EINVALIDFD);
+   *fd = me->eventfd;
+bail:
+   if (nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: listener android getevent file descriptor failed for domain %d\n", nErr, domain);
+   }
+   return nErr;
+}
+
+PL_DEFINE(listener_android, listener_android_init, listener_android_deinit)
diff --git a/src/log_config.c b/src/log_config.c
new file mode 100644
index 0000000..b2ef10e
--- /dev/null
+++ b/src/log_config.c
@@ -0,0 +1,543 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 VERIFY_PRINT_ERROR
+#define VERIFY_PRINT_ERROR
+#endif // VERIFY_PRINT_ERROR
+#include <pthread.h>
+#include <unistd.h>
+#include <sys/inotify.h>
+#include <sys/eventfd.h>
+#include <poll.h>
+#include <stdio.h>
+#include <string.h>
+#include <stdlib.h>
+#include <errno.h>
+#include <limits.h>
+
+#include "apps_std.h"
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+#include "verify.h"
+#include "remote_priv.h"
+#include "adsp_current_process.h"
+#include "adsp_current_process1.h"
+#include "adspmsgd_adsp.h"
+#include "adspmsgd_adsp1.h"
+#include "rpcmem.h"
+
+#define EVENT_SIZE          ( sizeof (struct inotify_event) )
+#define EVENT_BUF_LEN       ( 1024 * ( EVENT_SIZE + 16 ) )
+#ifndef AEE_EUNSUPPORTED
+#define AEE_EUNSUPPORTED         20 // API is not supported 	50
+#endif
+#define DEFAULT_ADSPMSGD_MEMORY_SIZE     8192
+#define INVALID_HANDLE      (remote_handle64)(-1)
+#define ERRNO (errno == 0 ? -1 : errno)
+
+struct log_config_watcher_params {
+    int fd;
+    int event_fd; // Duplicate fd to quit the poll
+    _cstring1_t* paths;
+    int* wd;
+    uint32 numPaths;
+    pthread_attr_t attr;
+    pthread_t thread;
+    unsigned char stopThread;
+    int asidToWatch;
+    char* fileToWatch;
+    char* asidFileToWatch;
+    char* pidFileToWatch;
+    boolean adspmsgdEnabled;
+};
+
+static struct log_config_watcher_params log_config_watcher[NUM_DOMAINS_EXTEND];
+extern const char* __progname;
+
+const char* get_domain_str(int domain);
+remote_handle64 get_adsp_current_process1_handle(int domain);
+remote_handle64 get_adspmsgd_adsp1_handle(int domain);
+
+static int parseLogConfig(int dom, unsigned short mask, char* filenames){
+    _cstring1_t* filesToLog = NULL;
+    int filesToLogLen = 0;
+    char* tempFiles = NULL;
+    int nErr = AEE_SUCCESS;
+    char *saveptr = NULL;
+    char* path = NULL;
+    char delim[] = {','};
+    int maxPathLen = 0;
+    int i = 0;
+    remote_handle64 handle;
+
+    VERIFYC(filenames != NULL, AEE_EINVALIDFILENAME);
+
+    VERIFYC(NULL!= (tempFiles = malloc(sizeof(char) * (std_strlen(filenames) + 1))), AEE_ENOMEMORY);
+    std_strlcpy(tempFiles,filenames,std_strlen(filenames) + 1);
+
+    // Get the number of folders and max size needed
+    path = strtok_r (tempFiles, delim, &saveptr);
+    while (path != NULL){
+        maxPathLen = STD_MAX(maxPathLen, std_strlen(path)) + 1;
+        filesToLogLen++;
+        path = strtok_r (NULL, delim, &saveptr);
+    }
+
+    VERIFY_IPRINTF("%s: #files: %d max_len: %d\n", log_config_watcher[dom].fileToWatch, filesToLogLen, maxPathLen);
+
+    // Allocate memory
+    VERIFYC(NULL != (filesToLog = malloc(sizeof(_cstring1_t)*filesToLogLen)), AEE_ENOMEMORY);
+    for (i = 0; i < filesToLogLen; ++i){
+        VERIFYC(NULL != (filesToLog[i].data = malloc(sizeof(char) * maxPathLen)), AEE_ENOMEMORY);
+        filesToLog[i].dataLen = maxPathLen;
+    }
+
+    // Get the number of folders and max size needed
+    std_strlcpy(tempFiles,filenames,std_strlen(filenames) + 1);
+    i = 0;
+    path = strtok_r (tempFiles, delim, &saveptr);
+    while (path != NULL){
+        VERIFYC((filesToLog != NULL) && (filesToLog[i].data != NULL) &&
+               filesToLog[i].dataLen >= (int)strlen(path), AEE_EBADSIZE);
+        std_strlcpy(filesToLog[i].data, path, filesToLog[i].dataLen);
+        VERIFY_IPRINTF("%s: %s\n", log_config_watcher[dom].fileToWatch, filesToLog[i].data);
+        path = strtok_r (NULL, delim, &saveptr);
+        i++;
+    }
+
+    handle = get_adsp_current_process1_handle(dom);
+    if (handle != INVALID_HANDLE) {
+       VERIFY(AEE_SUCCESS == (nErr = adsp_current_process1_set_logging_params(handle, mask,filesToLog,filesToLogLen)));
+    } else {
+       VERIFY(AEE_SUCCESS == (nErr = adsp_current_process_set_logging_params(mask,filesToLog,filesToLogLen)));
+    }
+
+bail:
+    if (filesToLog){
+        for (i = 0; i < filesToLogLen; ++i){
+            if (filesToLog[i].data != NULL){
+                free (filesToLog[i].data);
+                filesToLog[i].data = NULL;
+            }
+        }
+        free(filesToLog);
+        filesToLog = NULL;
+    }
+
+    if(tempFiles){
+        free(tempFiles);
+        tempFiles = NULL;
+    }
+    if(nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: parse log config failed. domain %d, mask %x, filename %s\n", nErr, dom, mask, filenames);
+    }
+    return nErr;
+}
+// Read log config given the filename
+static int readLogConfigFromPath(int dom, const char* base, const char* file){
+    int nErr = 0;
+    apps_std_FILE fp = -1;
+    uint64 len;
+    byte* buf = NULL;
+    int readlen = 0, eof;
+    unsigned short mask = 0;
+    char* path = NULL;
+    char* filenames = NULL;
+    boolean fileExists = FALSE;
+    int buf_addr = 0;
+    remote_handle64 handle;
+
+    len = std_snprintf(0, 0, "%s/%s", base, file) + 1;
+    VERIFYC(NULL != (path =  malloc(sizeof(char) * len)), AEE_ENOMEMORY);
+    std_snprintf(path, (int)len, "%s/%s", base, file);
+    VERIFY(AEE_SUCCESS == (nErr = apps_std_fileExists(path,&fileExists)));
+    if (fileExists == FALSE){
+        VERIFY_IPRINTF("%s: Couldn't find file: %s\n",log_config_watcher[dom].fileToWatch, path);
+        nErr = AEE_ENOSUCHFILE;
+        goto bail;
+    }
+    if (log_config_watcher[dom].adspmsgdEnabled == FALSE){
+        handle = get_adspmsgd_adsp1_handle(dom);
+        if(handle != INVALID_HANDLE) {
+           adspmsgd_adsp1_init2(handle);
+        } else if(AEE_EUNSUPPORTED == (nErr = adspmsgd_adsp_init2())) {
+            nErr = adspmsgd_adsp_init(0, RPCMEM_HEAP_DEFAULT, 0, DEFAULT_ADSPMSGD_MEMORY_SIZE, &buf_addr);
+        }
+        if (nErr != AEE_SUCCESS){
+            VERIFY_EPRINTF("adspmsgd not supported. nErr=%x\n", nErr);
+        }else{
+            log_config_watcher[dom].adspmsgdEnabled = TRUE;
+        }
+        VERIFY_EPRINTF("Found %s. adspmsgd enabled \n", log_config_watcher[dom].fileToWatch);
+    }
+
+    VERIFY(AEE_SUCCESS == (nErr = apps_std_fopen(path, "r", &fp)));
+    VERIFY(AEE_SUCCESS == (nErr = apps_std_flen(fp, &len)));
+
+    VERIFYC(len < 511, AEE_EBADSIZE);
+    VERIFYC(NULL != (buf = calloc(1, sizeof(byte) * (len + 1))), AEE_ENOMEMORY); // extra 1 byte for null character
+    VERIFYC(NULL != (filenames = malloc(sizeof(byte) * len)), AEE_ENOMEMORY);
+    VERIFY(AEE_SUCCESS == (nErr = apps_std_fread(fp, buf, len, &readlen, &eof)));
+    VERIFYC((int)len == readlen, AEE_EFREAD);
+
+    VERIFY_IPRINTF("%s: Config file %s contents: %s\n", log_config_watcher[dom].fileToWatch, path, buf);
+
+    len = sscanf((const char*)buf, "0x%hx %511s", &mask, filenames);
+    switch (len){
+        case 1:
+            VERIFY_IPRINTF("%s: Setting log mask:0x%x", log_config_watcher[dom].fileToWatch, mask);
+            handle = get_adsp_current_process1_handle(dom);
+            if (handle != INVALID_HANDLE) {
+               VERIFY(AEE_SUCCESS == (nErr = adsp_current_process1_set_logging_params(handle,mask,NULL,0)));
+            } else {
+               VERIFY(AEE_SUCCESS == (nErr = adsp_current_process_set_logging_params(mask,NULL,0)));
+            }
+            break;
+        case 2:
+            VERIFY(AEE_SUCCESS == (nErr = parseLogConfig(dom, mask,filenames)));
+            VERIFY_IPRINTF("%s: Setting log mask:0x%x, filename:%s", log_config_watcher[dom].fileToWatch, mask, filenames);
+            break;
+        default:
+            VERIFY_EPRINTF("%s: No valid data found in config file %s", log_config_watcher[dom].fileToWatch, path);
+            nErr = AEE_EUNSUPPORTED;
+            goto bail;
+    }
+
+bail:
+    if (buf != NULL){
+        free(buf);
+        buf = NULL;
+    }
+
+    if (filenames != NULL){
+        free(filenames);
+        filenames = NULL;
+    }
+
+    if (fp != -1){
+        apps_std_fclose(fp);
+    }
+
+    if (path != NULL){
+        free(path);
+        path = NULL;
+    }
+
+    if(nErr != AEE_SUCCESS) {
+	VERIFY_IPRINTF("Error %x: fopen failed for %s/%s. (%s)\n", nErr, base, file, strerror(ERRNO));
+    }
+    return nErr;
+}
+
+
+// Read log config given the watch descriptor
+static int readLogConfigFromEvent(int dom, struct inotify_event *event){
+    int i = 0;
+
+    // Ensure we are looking at the right file
+    for (i = 0; i < (int)log_config_watcher[dom].numPaths; ++i){
+        if (log_config_watcher[dom].wd[i] == event->wd ){
+            if(std_strcmp(log_config_watcher[dom].fileToWatch, event->name) == 0){
+                return readLogConfigFromPath(dom, log_config_watcher[dom].paths[i].data, log_config_watcher[dom].fileToWatch);
+            }else if (std_strcmp(log_config_watcher[dom].asidFileToWatch, event->name) == 0) {
+                return readLogConfigFromPath(dom, log_config_watcher[dom].paths[i].data, log_config_watcher[dom].asidFileToWatch);
+            }else if (std_strcmp(log_config_watcher[dom].pidFileToWatch, event->name) == 0){
+                return readLogConfigFromPath(dom, log_config_watcher[dom].paths[i].data, log_config_watcher[dom].pidFileToWatch);
+            }
+        }
+    }
+    VERIFY_IPRINTF("%s: Watch descriptor %d not valid for current process", log_config_watcher[dom].fileToWatch, event->wd);
+    return AEE_SUCCESS;
+}
+
+
+// Read log config given the watch descriptor
+static int resetLogConfigFromEvent(int dom, struct inotify_event *event) {
+    int i = 0;
+    remote_handle64 handle;
+
+    // Ensure we are looking at the right file
+    for (i = 0; i < (int)log_config_watcher[dom].numPaths; ++i){
+        if (log_config_watcher[dom].wd[i] == event->wd ){
+            if( (std_strcmp(log_config_watcher[dom].fileToWatch, event->name) == 0)||
+                (std_strcmp(log_config_watcher[dom].asidFileToWatch, event->name) == 0) ||
+                (std_strcmp(log_config_watcher[dom].pidFileToWatch, event->name) == 0) ) {
+                if (log_config_watcher[dom].adspmsgdEnabled == TRUE){
+                   handle = get_adspmsgd_adsp1_handle(dom);
+                   if(handle != INVALID_HANDLE) {
+                      adspmsgd_adsp1_deinit(handle);
+                   } else {
+                      adspmsgd_adsp_deinit();
+                   }
+                }
+                handle = get_adsp_current_process1_handle(dom);
+                if (handle != INVALID_HANDLE) {
+                   return adsp_current_process1_set_logging_params(handle,0,NULL,0);
+                } else {
+                   return adsp_current_process_set_logging_params(0,NULL,0);
+                }
+            }
+        }
+    }
+    VERIFY_IPRINTF("%s: Watch descriptor %d not valid for current process", log_config_watcher[dom].fileToWatch, event->wd);
+    return AEE_SUCCESS;
+}
+
+
+static void* file_watcher_thread(void *arg) {
+    int dom = (int)(uintptr_t)arg;
+    int ret = 0;
+    int length = 0;
+    int nErr = AEE_SUCCESS;
+    int i = 0;
+    char buffer[EVENT_BUF_LEN];
+    struct pollfd pfd[] = {
+        {log_config_watcher[dom].fd,     POLLIN, 0},
+        {log_config_watcher[dom].event_fd, POLLIN, 0}
+     };
+    const char* fileExtension = ".farf";
+    int len = 0;
+    remote_handle64 handle;
+
+    // Check for the presence of the <process_name>.farf file at bootup
+    for (i = 0; i < (int)log_config_watcher[dom].numPaths; ++i){
+        if (0 == readLogConfigFromPath(dom, log_config_watcher[dom].paths[i].data, log_config_watcher[dom].fileToWatch)){
+            VERIFY_IPRINTF("%s: Log config File %s found.\n", log_config_watcher[dom].fileToWatch, log_config_watcher[dom].paths[i].data );
+        }
+    }
+
+    while(log_config_watcher[dom].stopThread == 0){
+        // Block forever
+        ret = poll(pfd, 2, -1);
+        if(ret < 0){
+            VERIFY_EPRINTF("%s: Error polling for file change. Runtime FARF will not work for this process. errno=%x !", log_config_watcher[dom].fileToWatch, errno);
+            break;
+        } else if (pfd[1].revents & POLLIN) { // Check for exit
+            VERIFY_IPRINTF("Received exit.\n");
+            break;
+        } else {
+            length = read( log_config_watcher[dom].fd, buffer, EVENT_BUF_LEN );
+            i = 0;
+            while ( i < length ) {
+                struct inotify_event *event = ( struct inotify_event * ) &buffer[ i ];
+                if ( event->len ) {
+                    // Get the asiD for the current process
+                    // Do it once only
+                    if (log_config_watcher[dom].asidToWatch == -1){
+                        handle = get_adsp_current_process1_handle(dom);
+                        if (handle != INVALID_HANDLE) {
+                           VERIFY(AEE_SUCCESS == (nErr = adsp_current_process1_getASID(handle,(unsigned int*)&log_config_watcher[dom].asidToWatch )));
+                        } else {
+                           VERIFY(AEE_SUCCESS == (nErr = adsp_current_process_getASID((unsigned int*)&log_config_watcher[dom].asidToWatch )));
+                        }
+                        len = strlen(fileExtension) + strlen(__TOSTR__(INT_MAX));
+                        VERIFYC(NULL != (log_config_watcher[dom].asidFileToWatch = malloc(sizeof(char) * len)), AEE_ENOMEMORY);
+                        snprintf(log_config_watcher[dom].asidFileToWatch, len, "%d%s", log_config_watcher[dom].asidToWatch, fileExtension);
+                        VERIFY_IPRINTF("%s: Watching ASID file %s\n", log_config_watcher[dom].fileToWatch, log_config_watcher[dom].asidFileToWatch);
+                    }
+
+                    VERIFY_IPRINTF("%s: %s %d.\n", log_config_watcher[dom].fileToWatch, event->name, event->mask );
+                    if ( (event->mask & IN_CREATE) || (event->mask & IN_MODIFY)) {
+                        VERIFY_IPRINTF("%s: File %s created.\n", log_config_watcher[dom].fileToWatch, event->name );
+                        if (0 != readLogConfigFromEvent(dom, event)){
+                            VERIFY_EPRINTF("%s: Error reading config file %s", log_config_watcher[dom].fileToWatch, log_config_watcher[dom].paths[i].data);
+                        }
+                    }
+                    else if ( event->mask & IN_DELETE ) {
+                        VERIFY_IPRINTF("%s: File %s deleted.\n", log_config_watcher[dom].fileToWatch, event->name );
+                        if (0 != resetLogConfigFromEvent(dom, event)){
+                            VERIFY_EPRINTF("%s: Error resetting FARF runtime log config" ,log_config_watcher[dom].fileToWatch);
+                        }
+                    }
+                }
+
+                i += EVENT_SIZE + event->len;
+            }
+        }
+    }
+bail:
+    if (nErr != AEE_SUCCESS){
+        VERIFY_EPRINTF("Error %x: file watcher thread exited. Runtime FARF will not work for this process. filename %s\n", nErr, log_config_watcher[dom].fileToWatch);
+    }
+    return NULL;
+}
+
+void deinitFileWatcher(int dom) {
+    int i = 0;
+    uint64 stop = 10;
+    remote_handle64 handle;
+
+    log_config_watcher[dom].stopThread = 1;
+    if (0 < log_config_watcher[dom].event_fd) {
+       if (write(log_config_watcher[dom].event_fd, &stop, sizeof(uint64)) != sizeof(uint64)) {
+         VERIFY_EPRINTF("Error: write failed: Cannot set exit flag to watcher thread.\n");
+	}
+    }
+    if (log_config_watcher[dom].thread) {
+        pthread_join(log_config_watcher[dom].thread, NULL);
+	log_config_watcher[dom].thread = 0;
+    }
+    if (log_config_watcher[dom].fileToWatch){
+        free (log_config_watcher[dom].fileToWatch);
+	log_config_watcher[dom].fileToWatch = 0;
+    }
+    if (log_config_watcher[dom].asidFileToWatch){
+        free (log_config_watcher[dom].asidFileToWatch);
+	log_config_watcher[dom].asidFileToWatch = 0;
+    }
+    if (log_config_watcher[dom].pidFileToWatch){
+        free (log_config_watcher[dom].pidFileToWatch);
+	log_config_watcher[dom].pidFileToWatch = 0;
+    }
+    if (log_config_watcher[dom].wd){
+        for (i = 0; i < (int)log_config_watcher[dom].numPaths; ++i){
+            if (log_config_watcher[dom].wd[i] != 0){
+                inotify_rm_watch( log_config_watcher[dom].fd, log_config_watcher[dom].wd[i] );
+            }
+        }
+        free(log_config_watcher[dom].wd);
+        log_config_watcher[dom].wd = NULL;
+    }
+    if (log_config_watcher[dom].paths){
+        for (i = 0; i < (int)log_config_watcher[dom].numPaths; ++i){
+            if (log_config_watcher[dom].paths[i].data){
+                free(log_config_watcher[dom].paths[i].data);
+                log_config_watcher[dom].paths[i].data = NULL;
+            }
+        }
+        free(log_config_watcher[dom].paths);
+        log_config_watcher[dom].paths = NULL;
+    }
+    if(log_config_watcher[dom].fd != 0){
+        close(log_config_watcher[dom].fd);
+        log_config_watcher[dom].fd = 0;
+    }
+    if (log_config_watcher[dom].adspmsgdEnabled == TRUE){
+        handle = get_adspmsgd_adsp1_handle(dom);
+        if (handle != INVALID_HANDLE) {
+           adspmsgd_adsp1_deinit(handle);
+        } else {
+           adspmsgd_adsp_deinit();
+        }
+	log_config_watcher[dom].adspmsgdEnabled = FALSE;
+    }
+
+    if(log_config_watcher[dom].event_fd != 0){
+	close(log_config_watcher[dom].event_fd);
+	log_config_watcher[dom].event_fd = 0;
+    }
+
+    log_config_watcher[dom].numPaths = 0;
+}
+
+int initFileWatcher(int dom) {
+    int nErr = AEE_SUCCESS;
+    const char* fileExtension = ".farf";
+    uint32 len = 0;
+    uint16 maxPathLen = 0;
+    int i = 0;
+    char* name = NULL;
+
+    memset(&log_config_watcher[dom], 0, sizeof(struct log_config_watcher_params));
+    log_config_watcher[dom].asidToWatch = 0;
+
+    VERIFYC(NULL != (name = std_basename(__progname)), AEE_EINVALIDPROCNAME);
+
+    len = strlen(name) + strlen(fileExtension) + 1;
+    VERIFYC(NULL != (log_config_watcher[dom].fileToWatch = malloc(sizeof(char) * len)), AEE_ENOMEMORY);
+    snprintf(log_config_watcher[dom].fileToWatch, len, "%s%s", name, fileExtension);
+
+    len = strlen(fileExtension) + strlen(__TOSTR__(INT_MAX));
+    VERIFYC(NULL != (log_config_watcher[dom].pidFileToWatch = malloc(sizeof(char) * len)), AEE_ENOMEMORY);
+    snprintf(log_config_watcher[dom].pidFileToWatch, len, "%d%s", getpid(), fileExtension);
+
+    VERIFY_IPRINTF("%s: Watching PID file: %s\n", log_config_watcher[dom].fileToWatch, log_config_watcher[dom].pidFileToWatch);
+
+    log_config_watcher[dom].fd = inotify_init();
+    if (log_config_watcher[dom].fd < 0){
+        nErr = AEE_EINVALIDFD;
+        VERIFY_EPRINTF("Error %x: inotify_init failed. errno = %s\n", nErr, strerror(errno));
+        goto bail;
+    }
+
+    // Duplicate the fd, so we can use it to quit polling
+    log_config_watcher[dom].event_fd = eventfd(0, 0);
+    if (log_config_watcher[dom].event_fd < 0){
+        nErr = AEE_EINVALIDFD;
+        VERIFY_EPRINTF("Error %x: eventfd in dup failed. errno %s\n", nErr, strerror(errno));
+        goto bail;
+    }
+    VERIFY_IPRINTF("fd = %d dupfd=%d\n", log_config_watcher[dom].fd, log_config_watcher[dom].event_fd);
+
+    // Get the required size
+    apps_std_get_search_paths_with_env("ADSP_LIBRARY_PATH", ";", NULL, 0,
+        &log_config_watcher[dom].numPaths, &maxPathLen);
+
+    maxPathLen += + 1;
+
+    // Allocate memory
+    VERIFYC(NULL != (log_config_watcher[dom].paths
+           = malloc(sizeof(_cstring1_t) * log_config_watcher[dom].numPaths)), AEE_ENOMEMORY);
+    VERIFYC(NULL != (log_config_watcher[dom].wd
+           = malloc(sizeof(int) * log_config_watcher[dom].numPaths)), AEE_ENOMEMORY);
+
+    for (i = 0; i < (int)log_config_watcher[dom].numPaths; ++i){
+        VERIFYC( NULL != (log_config_watcher[dom].paths[i].data
+               = malloc(sizeof(char) * maxPathLen)), AEE_ENOMEMORY);
+        log_config_watcher[dom].paths[i].dataLen = maxPathLen;
+    }
+
+    // Get the paths
+    VERIFY(AEE_SUCCESS == (nErr = apps_std_get_search_paths_with_env("ADSP_LIBRARY_PATH", ";",
+           log_config_watcher[dom].paths, log_config_watcher[dom].numPaths, &len, &maxPathLen)));
+
+    maxPathLen += 1;
+
+    VERIFY_IPRINTF("%s: Watching folders:\n", log_config_watcher[dom].fileToWatch);
+    for (i = 0; i < (int)log_config_watcher[dom].numPaths; ++i){
+        // Watch for creation, deletion and modification of files in path
+	VERIFY_IPRINTF("log file watcher: %s: %s\n",log_config_watcher[dom].fileToWatch, log_config_watcher[dom].paths[i].data);
+	if((log_config_watcher[dom].wd[i] = inotify_add_watch (log_config_watcher[dom].fd,
+				log_config_watcher[dom].paths[i].data,  IN_CREATE | IN_DELETE)) < 0) {
+		VERIFY_EPRINTF("Unable to add watcher for folder %s : errno is %s\n", log_config_watcher[dom].paths[i].data, strerror(ERRNO));
+	}
+    }
+
+    // Create a thread to watch for file changes
+    log_config_watcher[dom].asidToWatch = -1;
+    log_config_watcher[dom].stopThread = 0;
+    pthread_create(&log_config_watcher[dom].thread, NULL, file_watcher_thread, (void*)(uintptr_t)dom);
+bail:
+    if (nErr!=AEE_SUCCESS){
+        VERIFY_EPRINTF("Error %x: Failed to register with inotify file %s. Runtime FARF will not work for the process %s!", nErr, log_config_watcher[dom].fileToWatch, name);
+        deinitFileWatcher(dom);
+    }
+
+    return nErr;
+}
diff --git a/src/mod_table.c b/src/mod_table.c
new file mode 100644
index 0000000..7c92d84
--- /dev/null
+++ b/src/mod_table.c
@@ -0,0 +1,865 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 FARF_ERROR
+#define FARF_ERROR 1
+#endif
+
+#include <assert.h>
+#include "verify.h"
+#include "HAP_farf.h"
+#include "HAP_pls.h"
+#include "mutex.h"
+#include "mod_table.h"
+#include "platform_libs.h"
+#include "remote64.h"
+#include "uthash.h"
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+#include "sbuf_parser.h"
+
+#include <dlfcn.h>
+
+#define DLOPEN  dlopen
+#define DLCLOSE dlclose
+#define DLSYM   dlsym
+#define DLERROR dlerror
+
+/**
+ * structure for the mod table
+ *
+ * you need to define a rw_mutex type and its read/write lock/unlock api's
+ * which are under the RW_MUTEX namespace.
+ *
+ * this library defines 2 functions for opening modules, open_static and
+ * open_dynamic.  Both return a handle that should be closed via close.
+ *
+ * you can also register a const handle, an invoke function for a known handle
+ * value.  since handle keys are allocated, you should pick handle values that are
+ * not going to be returned by malloc (0, or odd).
+ */
+struct static_mod_table {
+   RW_MUTEX_T mut;
+   struct static_mod* staticModOverrides;
+   struct static_mod* staticMods;
+   struct const_mod* constMods;
+   boolean bInit;
+};
+
+struct open_mod_table {
+   RW_MUTEX_T mut;
+   struct open_mod* openMods;
+   struct static_mod_table* smt;
+};
+
+typedef int (*invoke_fn)(uint32, remote_arg*);
+typedef int (*handle_invoke_fn)(remote_handle64, uint32, remote_arg*);
+struct static_mod {
+   invoke_fn         invoke;
+   handle_invoke_fn  handle_invoke;
+   UT_hash_handle    hh;
+   char              uri[1];
+};
+
+struct const_mod {
+   invoke_fn         invoke;
+   handle_invoke_fn  handle_invoke;
+   uint32            key;
+   remote_handle64   h64;
+   UT_hash_handle    hh;
+   char              uri[1];
+};
+
+struct parsed_uri {
+   const char *file;
+   int filelen;
+   const char *sym;
+   int symlen;
+   const char *ver;
+   int verlen;
+};
+
+struct open_mod {
+   void*             dlhandle;
+   invoke_fn         invoke;
+   handle_invoke_fn  handle_invoke;
+   uint64            key;
+   UT_hash_handle    hh;
+   remote_handle64   h64;
+   int               refs;
+   struct parsed_uri vals;
+   char              uri[1];
+};
+
+static int static_mod_table_ctor(struct static_mod_table* me) {
+   if(me->bInit == 0) {
+      RW_MUTEX_CTOR(me->mut);
+      me->staticMods = 0;
+      me->staticModOverrides = 0;
+      me->bInit = 1;
+   }
+   return 0;
+}
+
+static void static_mod_table_dtor_imp(struct static_mod_table* me) {
+   struct static_mod *sm, *stmp;
+   struct const_mod *dm, *ftmp;
+   if(me->bInit != 0) {
+      if( me->staticMods || me->constMods || me->staticModOverrides) {
+         RW_MUTEX_LOCK_WRITE(me->mut);
+         HASH_ITER(hh, me->staticMods, sm, stmp) {
+            if(me->staticMods) {
+               HASH_DEL(me->staticMods,sm);
+            }
+            free(sm);
+            sm = NULL;
+         }
+         HASH_ITER(hh, me->staticModOverrides, sm, stmp) {
+            if(me->staticModOverrides) {
+               HASH_DEL(me->staticModOverrides,sm);
+            }
+            free(sm);
+            sm = NULL;
+         }
+         HASH_ITER(hh, me->constMods, dm, ftmp) {
+            if(me->constMods) {
+               HASH_DEL(me->constMods,dm);
+            }
+            free(dm);
+            dm = NULL;
+         }
+         RW_MUTEX_UNLOCK_WRITE(me->mut);
+      }
+      RW_MUTEX_DTOR(me->mut);
+      me->staticMods = 0;
+      me->staticModOverrides = 0;
+      me->bInit = 0;
+   }
+}
+
+static int open_mod_table_ctor_imp(void* ctx, void* data) {
+   struct open_mod_table* me = (struct open_mod_table*)data;
+   RW_MUTEX_CTOR(me->mut);
+   me->openMods = 0;
+   me->smt = (struct static_mod_table*) ctx;
+   return 0;
+}
+
+static int open_mod_handle_close(struct open_mod *mod, remote_handle64 h);
+
+static void open_mod_table_dtor_imp(void* data) {
+   struct open_mod_table* me = (struct open_mod_table*)data;
+   struct open_mod *dm, *ftmp;
+   if( me->openMods) {
+      RW_MUTEX_LOCK_WRITE(me->mut);
+      HASH_ITER(hh, me->openMods, dm, ftmp) {
+         if(me->openMods) {
+            HASH_DEL(me->openMods,dm);
+         }
+         if(dm->h64) {
+            (void)open_mod_handle_close(dm, dm->h64);
+         }
+         if(dm->dlhandle) {
+            DLCLOSE(dm->dlhandle);
+         }
+         free(dm);
+      }
+      RW_MUTEX_UNLOCK_WRITE(me->mut);
+   }
+   RW_MUTEX_DTOR(me->mut);
+   me->openMods = 0;
+}
+static int open_mod_table_open_from_static(struct open_mod_table* me,
+                                           struct static_mod** tbl,
+                                           const char* uri,
+                                           remote_handle* handle);
+
+static int open_mod_table_open_static_override(struct open_mod_table* me, const char* uri, remote_handle* handle) {
+   FARF(HIGH, "open_mod_table_open_static_override");
+   return open_mod_table_open_from_static(me, &me->smt->staticModOverrides, uri, handle);
+}
+
+
+static int open_mod_table_open_static(struct open_mod_table* me, const char* uri, remote_handle* handle) {
+   FARF(HIGH, "open_mod_table_open_static");
+   return open_mod_table_open_from_static(me, &me->smt->staticMods, uri, handle);
+}
+
+static int static_mod_add(struct static_mod_table* me, struct static_mod** tbl, const char* uri,
+                          int(*invoke)(uint32 sc, remote_arg* pra),
+                          int(*handle_invoke)(remote_handle64, uint32 sc, remote_arg* pra)) {
+   int nErr = AEE_SUCCESS;
+   struct static_mod *sm = 0;
+   int len = std_strlen(uri) + 1;
+   VERIFYC(NULL != (sm = ((struct static_mod*)calloc(1, sizeof(struct static_mod) + len))), AEE_ENOMEMORY);
+   std_strlcpy(sm->uri, uri, len);
+   sm->invoke = invoke;
+   sm->handle_invoke = handle_invoke;
+   RW_MUTEX_LOCK_WRITE(me->mut);
+	HASH_ADD_STR(*tbl, uri, sm);
+   RW_MUTEX_UNLOCK_WRITE(me->mut);
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: static module addition failed\n", nErr);
+      if(sm) {
+         free(sm);
+         sm = NULL;
+      }
+   }
+   return nErr;
+}
+
+static int static_mod_table_register_static_override(struct static_mod_table* me, const char* uri, int(*pfn)(uint32 sc, remote_arg* pra)) {
+   return static_mod_add(me, &me->staticModOverrides, uri, pfn, 0);
+}
+static int static_mod_table_register_static_override1(struct static_mod_table* me, const char* uri, int(*pfn)(remote_handle64, uint32 sc, remote_arg* pra)) {
+   return static_mod_add(me, &me->staticModOverrides, uri, 0, pfn);
+}
+static int static_mod_table_register_static(struct static_mod_table* me, const char* uri, int(*pfn)(uint32 sc, remote_arg* pra)) {
+   return static_mod_add(me, &me->staticMods, uri, pfn, 0);
+}
+static int static_mod_table_register_static1(struct static_mod_table* me, const char* uri, int(*pfn)(remote_handle64,uint32 sc, remote_arg* pra)) {
+   return static_mod_add(me, &me->staticMods, uri, 0, pfn);
+}
+
+
+static int static_mod_table_register_const_handle(struct static_mod_table* me, remote_handle local,
+                                                  remote_handle64 remote, const char* uri,
+                                                  int(*invoke)(uint32 sc, remote_arg* pra),
+                                                  int(*handle_invoke)(remote_handle64, uint32 sc, remote_arg* pra)
+                                                  ) {
+   int nErr = AEE_SUCCESS;
+   int len = std_strlen(uri) + 1;
+   struct const_mod *dm = 0, *dmOld;
+   VERIFYC(NULL != (dm = ((struct const_mod*)calloc(1, sizeof(struct open_mod) + len))), AEE_ENOMEMORY);
+   dm->key = local;
+   dm->invoke = invoke;
+   dm->handle_invoke = handle_invoke;
+   dm->h64 = remote;
+   std_strlcpy(dm->uri, uri, len);
+
+   RW_MUTEX_LOCK_WRITE(me->mut);
+   HASH_FIND_INT(me->constMods, &local, dmOld);
+   if(dmOld == 0) {
+	   HASH_ADD_INT(me->constMods, key, dm);
+   }
+   RW_MUTEX_UNLOCK_WRITE(me->mut);
+   nErr = dmOld != 0 ? -1 : nErr;
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: failed to register const handle in modtable\n", nErr);
+      if(dm) {
+         free(dm);
+         dm = NULL;
+      }
+   }
+   return nErr;
+}
+
+static int open_mod_handle_open(struct open_mod *mod, const char* name,
+                                remote_handle64 *ph) {
+   int nErr = AEE_SUCCESS;
+   remote_arg args[3];
+   int32_t len = strlen(name) + 1;
+   args[0].buf.pv = &len;
+   args[0].buf.nLen = sizeof(len);
+   args[1].buf.pv = (void*)name;
+   args[1].buf.nLen = len;
+   nErr = mod->handle_invoke(0,REMOTE_SCALARS_MAKEX(0,0,2,0,0,1),args);
+   if(!nErr) {
+      *ph = args[2].h64;
+   }
+   FARF(HIGH, "allocated %x", *ph);
+   return nErr;
+}
+
+static int open_mod_handle_close(struct open_mod *mod, remote_handle64 h) {
+   int nErr;
+   remote_arg args[1];
+   args[0].h64 = h;
+   FARF(HIGH, "releasing %x", h);
+   nErr = mod->handle_invoke(0,REMOTE_SCALARS_MAKEX(0,1,0,0,1,0),args);
+   return nErr;
+}
+
+static int notqmark(struct sbuf *buf) {
+   return sbuf_notchar(buf, '?');
+}
+static int notandoreq(struct sbuf *buf) {
+   return sbuf_notchars(buf, "&=");
+}
+static int notand(struct sbuf *buf) {
+   return sbuf_notchar(buf, '&');
+}
+
+static int parse_uri(const char *uri, int urilen, struct parsed_uri *out) {
+// "file:///librhtest_skel.so?rhtest_skel_handle_invoke&_modver=1.0"
+   int nErr = 0;
+   char *name, *value;
+   int nameLen, valueLen;
+   struct sbuf buf;
+   FARF(HIGH, "parse_uri %s %d", uri, urilen);
+   memset(out, 0, sizeof(*out));
+   //initialize
+   sbuf_parser_init(&buf, uri, urilen);
+
+   //parse until question mark
+   VERIFYC(sbuf_string(&buf, "file://"), AEE_EINVALIDFORMAT);
+
+   //ignore the starting /
+   (void)sbuf_string(&buf, "/");
+
+   out->file = sbuf_cur(&buf);
+   VERIFY(sbuf_many1(&buf, notqmark));
+   out->filelen = sbuf_cur(&buf) - out->file;
+   FARF(HIGH, "file:%.*s %d", out->filelen, out->file, out->filelen);
+   VERIFY(sbuf_char(&buf, '?'));
+   out->sym = sbuf_cur(&buf);
+   VERIFY(sbuf_many1(&buf, notand));
+   out->symlen = sbuf_cur(&buf) - out->sym;
+   assert(out->sym + out->symlen <= uri + urilen);
+   FARF(HIGH, "sym:%.*s %d", out->symlen, out->sym, out->symlen);
+
+   if(!sbuf_end(&buf) && sbuf_char(&buf, '&')) {
+     //parse each query
+     while(!sbuf_end(&buf)) {
+        //record where the name starts
+        name = sbuf_cur(&buf);
+
+        //name is valid until '=' or '&'
+        VERIFY(sbuf_many1(&buf, notandoreq));
+        nameLen = sbuf_cur(&buf) - name;
+
+        value = 0;
+        valueLen = 0;
+        //if the next char is a '=' then we also get a value
+        if(sbuf_char(&buf, '=')) {
+           value = sbuf_cur(&buf);
+
+           //value is until the next query that starts with '&'
+           VERIFY(sbuf_many1(&buf, notand));
+           valueLen = sbuf_cur(&buf) - value;
+        }
+        //expect '&' or end
+        sbuf_char(&buf, '&');
+        if(!std_strncmp(name, "_modver", nameLen)) {
+           out->ver = value;
+           out->verlen = valueLen;
+        }
+     }
+   }
+bail:
+   if(out->filelen) {
+      FARF(HIGH, "parse_uri file: %.*s", out->filelen, out->file);
+   }
+   if(out->symlen) {
+      FARF(HIGH, "parse_uri sym: %.*s", out->symlen, out->sym);
+   }
+   if(out->verlen) {
+      FARF(HIGH, "parse_uri version: %.*s", out->verlen, out->ver);
+   }
+   FARF(HIGH, "parse_uri done: %s %d err:%x", uri, urilen, nErr);
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: parseuri failed for uri %s, urilen %d\n", nErr, uri, urilen);
+   }
+   return nErr;
+}
+
+static int open_mod_table_open_dynamic(struct open_mod_table* me, const char* uri, remote_handle* handle, char* dlStr, int dlerrorLen, int* pdlErr)
+{
+   int nErr = AEE_SUCCESS, dlErr = 0;
+   struct open_mod *dm = 0, *dmOld;
+   int len = strlen(uri);
+   int tmplen = len*2 + sizeof("file:///lib_skel.so?_skel_handle_invoke&_modver=1.0") + 1;
+   char *tmp = 0;
+   FARF(HIGH, "open_mod_table_open_dynamic");
+   VERIFYC(NULL != (tmp = calloc(1, tmplen)), AEE_ENOMEMORY);
+   VERIFYC(NULL != (dm = ((struct open_mod*)calloc(1, sizeof(struct open_mod) + len + 1))), AEE_ENOMEMORY);
+   std_memmove(dm->uri, uri, len + 1);
+   FARF(HIGH, "calling parse_uri");
+   (void)parse_uri(dm->uri, len, &dm->vals);
+   FARF(HIGH, "done calling parse_uri");
+   FARF(HIGH, "vals %d %d %d", dm->vals.filelen, dm->vals.symlen, dm->vals.verlen);
+   if(dm->vals.filelen) {
+      int rv = std_snprintf(tmp, tmplen, "%.*s", dm->vals.filelen, dm->vals.file);
+      VERIFYC(tmplen >= rv, AEE_EBADSIZE);
+   } else {
+      int rv;
+      rv = std_snprintf(tmp, tmplen, "lib%s_skel.so", uri);
+      VERIFYC(tmplen >= rv, AEE_EBADSIZE);
+   }
+   FARF(HIGH, "calling dlopen for %s", tmp);
+   dm->dlhandle = DLOPEN(tmp,RTLD_NOW);
+   FARF(HIGH, "got %p for dlopen %s", dm->dlhandle, tmp);
+   VERIFY(!(nErr = (dlErr = dm->dlhandle == 0 ? -5 : 0)));
+
+   if(dm->vals.symlen) {
+      int rv = std_snprintf(tmp, tmplen, "%.*s", dm->vals.symlen, dm->vals.sym);
+      VERIFYC(tmplen >= rv, AEE_EBADSIZE);
+   } else {
+      int rv = std_snprintf(tmp, tmplen, "%s_skel_invoke", uri);
+      VERIFYC(tmplen >= rv, AEE_EBADSIZE);
+   }
+
+   FARF(HIGH, "calling dlsym for %s", tmp);
+   if(dm->vals.verlen && 0 == std_strncmp(dm->vals.ver, "1.0", dm->vals.verlen)) {
+      dm->handle_invoke = (handle_invoke_fn) DLSYM(dm->dlhandle, tmp);
+   } else {
+      dm->invoke = (invoke_fn) DLSYM(dm->dlhandle, tmp);
+   }
+   FARF(HIGH, "dlsym returned %p %p", dm->invoke, dm->handle_invoke);
+   VERIFYC(!(dlErr = dm->invoke || dm->handle_invoke ? 0 : AEE_ENOSUCHSYMBOL), AEE_ENOSUCHSYMBOL);
+
+   dm->key = (uint32)(uintptr_t)dm;
+   dm->refs = 1;
+   if(dm->handle_invoke) {
+      VERIFY(AEE_SUCCESS == (nErr = open_mod_handle_open(dm, uri, &dm->h64)));
+   }
+   RW_MUTEX_LOCK_WRITE(me->mut);
+      do {
+         HASH_FIND_INT(me->openMods, &dm->key, dmOld);
+         if(dmOld) {
+            dm->key++;
+         }
+      } while(dmOld);
+      RW_MUTEX_LOCK_WRITE(me->smt->mut);
+      HASH_FIND_INT(me->smt->constMods, &dm->key, dmOld);
+      RW_MUTEX_UNLOCK_WRITE(me->smt->mut);
+      if(dmOld == 0) {
+         HASH_ADD_INT(me->openMods, key, dm);
+      }
+   RW_MUTEX_UNLOCK_WRITE(me->mut);
+   nErr = dmOld != 0 ? -1 : nErr;
+   if(nErr == 0) {
+      *handle = dm->key;
+   }
+bail:
+   if (nErr != AEE_SUCCESS) {
+      if(dlErr) {
+         const char* dlerr = DLERROR();
+         if(dlerr != 0){
+            std_strlcpy(dlStr,dlerr,dlerrorLen);
+         }
+         FARF(HIGH, "dlerror:%x:%s", dlErr, dlerr == 0 ? "" : dlerr);
+         nErr = 0;
+      }
+      if(pdlErr) {
+         *pdlErr = dlErr;
+      }
+      if(dm && dm->h64) {
+         (void)open_mod_handle_close(dm, dm->h64);
+      }
+      if(dm && dm->dlhandle) {
+         DLCLOSE(dm->dlhandle);
+      }
+      if(dm) {
+         free(dm);
+         dm = NULL;
+      }
+      VERIFY_EPRINTF("Error %x: open modtable dynamic failed. dlerr %x\n", nErr, dlErr);
+   }
+   FARF(HIGH, "done open_mod_table_open_dynamic for %s rv %x handle: %p %x", uri, nErr, *handle, dlErr);
+   if(tmp) {
+      free(tmp);
+      tmp = NULL;
+   }
+   return nErr;
+}
+
+static int open_mod_table_open_from_static(struct open_mod_table* me,
+                                           struct static_mod** tbl,
+                                           const char* uri,
+                                           remote_handle* handle)
+{
+   int nErr = AEE_SUCCESS;
+   struct static_mod *sm = 0;
+   struct open_mod *dm = 0, *dmOld = 0;
+   int len = std_strlen(uri);
+   int sz = len*2 + sizeof("file:///lib_skel.so?_skel_handle_invoke&_modver=1.0") + 1;
+   char *tmp = 0;
+   VERIFYC(NULL != (dm = ((struct open_mod*)calloc(1, sizeof(*dm) + sz))), AEE_ENOMEMORY);
+   RW_MUTEX_LOCK_READ(me->mut);
+	HASH_FIND_STR(*tbl, uri, sm);
+   RW_MUTEX_UNLOCK_READ(me->mut);
+   std_memmove(dm->uri, uri, len);
+   if(sm == 0) {
+      VERIFY(AEE_SUCCESS == (nErr = parse_uri(uri, len, &dm->vals)));
+      FARF(HIGH, "file %.*s %d", dm->vals.filelen, dm->vals.file, dm->vals.filelen);
+      FARF(HIGH, "sym %.*s %d", dm->vals.symlen, dm->vals.sym, dm->vals.symlen);
+      FARF(HIGH, "version %.*s %d", dm->vals.verlen, dm->vals.ver, dm->vals.verlen);
+      if(dm->vals.verlen) {
+         int rv = std_snprintf(dm->uri, sz, "file:///%.*s?%.*s&_modver=%.*s",
+               dm->vals.filelen, dm->vals.file,
+               dm->vals.symlen,  dm->vals.sym,
+               dm->vals.verlen,  dm->vals.ver);
+         VERIFYC(sz >= rv, AEE_EBADSIZE);
+      } else {
+         int rv = std_snprintf(dm->uri, sz, "file://%.*s?%.*s",
+               dm->vals.filelen, dm->vals.file,
+               dm->vals.symlen,  dm->vals.sym);
+         VERIFYC(sz >= rv, AEE_EBADSIZE);
+      }
+      FARF(HIGH, "dm->uri:%s", dm->uri);
+
+      RW_MUTEX_LOCK_READ(me->mut);
+	   HASH_FIND_STR(*tbl, dm->uri, sm);
+      RW_MUTEX_UNLOCK_READ(me->mut);
+   }
+   VERIFYC(0 != sm, AEE_ENOTINITIALIZED);
+   assert(sm->handle_invoke || sm->invoke);
+   dm->handle_invoke = sm->handle_invoke;
+   dm->invoke = sm->invoke;
+   dm->key = (uint32)(uintptr_t)dm;
+   dm->refs = 1;
+   if(dm->handle_invoke) {
+      VERIFY(AEE_SUCCESS == (nErr = open_mod_handle_open(dm, uri, &dm->h64)));
+   }
+
+   RW_MUTEX_LOCK_WRITE(me->mut);
+      do {
+         HASH_FIND_INT(me->openMods, &dm->key, dmOld);
+         if(dmOld) {
+            dm->key++;
+         }
+      } while(dmOld);
+      HASH_ADD_INT(me->openMods, key, dm);
+   RW_MUTEX_UNLOCK_WRITE(me->mut);
+
+   *handle = dm->key;
+bail:
+   if(tmp) {
+      free(tmp);
+      tmp = NULL;
+   }
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: modtable open from static failed.\n", nErr);
+   }
+   if(nErr && dm) {
+      if(dm->h64) {
+         (void)open_mod_handle_close(dm, dm->h64);
+      }
+      free(dm);
+      dm = NULL;
+   }
+   return nErr;
+}
+
+static int open_mod_table_open(struct open_mod_table* me, const char* uri, remote_handle* handle, char* dlerr, int dlerrorLen, int* pdlErr)
+{
+   int nErr = AEE_SUCCESS, dlErr = 0;
+   if(pdlErr) {
+      *pdlErr = 0;
+   }
+   if(0 != open_mod_table_open_static_override(me, uri, handle)) {
+      VERIFY(AEE_SUCCESS == (nErr = open_mod_table_open_dynamic(me, uri, handle, dlerr, dlerrorLen, &dlErr)));
+      if(dlErr != 0) {
+         FARF(HIGH, "dynammic open failed, trying static");
+         if(0 != open_mod_table_open_static(me, uri, handle)) {
+            if(pdlErr) {
+               *pdlErr = dlErr;
+            }
+         }
+      }
+   }
+bail:
+   FARF(HIGH, "done open for %s rv %d handle: %p", uri, nErr, *handle);
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: open modtable failed\n", nErr);
+   }
+   return nErr;
+}
+
+static void open_mod_close(struct open_mod_table *me, struct open_mod* dm) {
+   RW_MUTEX_LOCK_WRITE(me->mut);
+   dm->refs--;
+   if(dm->refs <= 0) {
+      HASH_DEL(me->openMods,dm);
+   } else {
+      dm = 0;
+   }
+   RW_MUTEX_UNLOCK_WRITE(me->mut);
+   if(dm) {
+      if(dm->h64) {
+         (void)open_mod_handle_close(dm, dm->h64);
+      }
+      if(dm->dlhandle) {
+         DLCLOSE(dm->dlhandle);
+      }
+      free(dm);
+      dm = NULL;
+   }
+}
+static int open_mod_table_close(struct open_mod_table* me, remote_handle64 handle, char* errStr, int errStrLen, int* pdlErr)
+{
+   int nErr = AEE_SUCCESS;
+   struct open_mod *dm, *del = 0;;
+   int dlErr = 0;
+   // First ensure that the handle is valid
+   RW_MUTEX_LOCK_WRITE(me->mut);
+   HASH_FIND_INT(me->openMods, &handle, dm);
+   if(dm) {
+      dm->refs--;
+      if(dm->refs <= 0) {
+         del = dm;
+         FARF(HIGH, "deleting %s %p", del->uri, del);
+         HASH_DEL(me->openMods,dm);
+      } else {
+         FARF(HIGH, "leaked %s", dm->uri);
+         dm = 0;
+      }
+   }
+   RW_MUTEX_UNLOCK_WRITE(me->mut);
+   if(del) {
+      if(del->h64) {
+         (void)open_mod_handle_close(dm, dm->h64);
+      }
+      if(del->dlhandle) {
+         dlErr = DLCLOSE(del->dlhandle);
+      }
+      FARF(HIGH, "free %s %p", del->uri, del);
+      free(del);
+      del = NULL;
+   }
+   VERIFY(del);
+
+bail:
+   if(dlErr) {
+      const char* error = DLERROR();
+      nErr = dlErr;
+      if(error != 0){
+         std_strlcpy(errStr,error,errStrLen);
+      }
+      VERIFY_EPRINTF("Error %x: open modtable close failed. dlerr %s\n", nErr, error);
+   }
+   if(pdlErr) {
+      *pdlErr = dlErr;
+   }
+   return nErr;
+}
+
+static struct open_mod* open_mod_table_get_open(struct open_mod_table* me, remote_handle handle) {
+   struct open_mod* om = 0;
+   RW_MUTEX_LOCK_READ(me->mut);
+   HASH_FIND_INT(me->openMods, &handle, om);
+   if(0 != om) {
+      om->refs++;
+   }
+   RW_MUTEX_UNLOCK_READ(me->mut);
+   return om;
+}
+static struct const_mod* open_mod_table_get_const(struct open_mod_table* me, remote_handle handle) {
+   struct const_mod* cm = 0;
+   RW_MUTEX_LOCK_READ(me->smt->mut);
+   HASH_FIND_INT(me->smt->constMods, &handle, cm);
+   RW_MUTEX_UNLOCK_READ(me->smt->mut);
+   return cm;
+}
+
+static int open_mod_table_handle_invoke(struct open_mod_table* me, remote_handle handle, uint32 sc, remote_arg* pra) {
+   int nErr = AEE_SUCCESS;
+   struct open_mod* om = 0;
+   struct const_mod* cm = 0;
+   remote_handle64 h = 0;
+   invoke_fn invoke = 0;
+   handle_invoke_fn handle_invoke = 0;
+   cm = open_mod_table_get_const(me, handle);
+   if(cm) {
+      invoke = cm->invoke;
+      handle_invoke = cm->handle_invoke;
+      h = cm->h64;
+   } else {
+      VERIFYC(0 != (om = open_mod_table_get_open(me, handle)), AEE_ENOSUCHMOD);
+      invoke = om->invoke;
+      handle_invoke = om->handle_invoke;
+      h = om->h64;
+   }
+   if(invoke) {
+      VERIFY(AEE_SUCCESS == (nErr = invoke(sc, pra)));
+   } else {
+      VERIFY(AEE_SUCCESS == (nErr = handle_invoke(h, sc, pra)));
+   }
+bail:
+   if(om) {
+      open_mod_close(me, om);
+   }
+   FARF(HIGH, "invoke rv %p %x %x", handle, sc, nErr);
+   return nErr;
+}
+
+struct mod_table {
+   struct static_mod_table smt;
+   struct open_mod_table omt;
+};
+
+// mod_table object
+static struct static_mod_table static_mod_table_obj;
+
+
+/**
+  * register a static component for invocations
+  * this can be called at any time including from a static constructor
+  *
+  * overrides will be tried first, then dynamic modules, then regular
+  * static modules.
+  *
+  * name, name of the interface to register
+  * pfn, function pointer to the skel invoke function
+  *
+  * for example:
+  *   __attribute__((constructor)) static void my_module_ctor(void) {
+  *      mod_table_register_static("my_module", my_module_skel_invoke);
+  *   }
+  *
+  */
+int mod_table_register_static_override(const char* name, int(*pfn)(uint32 sc, remote_arg* pra)) {
+   if(0 == static_mod_table_ctor(&static_mod_table_obj)) {
+      return static_mod_table_register_static_override(&static_mod_table_obj, name, pfn);
+   }
+   return AEE_EUNKNOWN;
+}
+
+int mod_table_register_static_override1(const char* name, int(*pfn)(remote_handle64, uint32 sc, remote_arg* pra)) {
+   if(0 == static_mod_table_ctor(&static_mod_table_obj)) {
+      return static_mod_table_register_static_override1(&static_mod_table_obj, name, pfn);
+   }
+   return AEE_EUNKNOWN;
+}
+
+
+/**
+  * register a static component for invocations
+  * this can be called at any time including from a static constructor
+  *
+  * name, name of the interface to register
+  * pfn, function pointer to the skel invoke function
+  *
+  * for example:
+  *   __attribute__((constructor)) static void my_module_ctor(void) {
+  *      mod_table_register_static("my_module", my_module_skel_invoke);
+  *   }
+  *
+  */
+int mod_table_register_static(const char* name, int(*pfn)(uint32 sc, remote_arg* pra)) {
+   if(0 == static_mod_table_ctor(&static_mod_table_obj)) {
+      return static_mod_table_register_static(&static_mod_table_obj, name, pfn);
+   }
+   return AEE_EUNKNOWN;
+}
+
+int mod_table_register_static1(const char* name, int(*pfn)(remote_handle64, uint32 sc, remote_arg* pra)) {
+   if(0 == static_mod_table_ctor(&static_mod_table_obj)) {
+      return static_mod_table_register_static1(&static_mod_table_obj, name, pfn);
+   }
+   return AEE_EUNKNOWN;
+}
+
+
+/**
+ * Open a module and get a handle to it
+ *
+ * uri, name of module to open
+ * handle, Output handle
+ * dlerr, Error String (if an error occurs)
+ * dlerrorLen, Length of error String (if an error occurs)
+ * pdlErr, Error identifier
+ */
+int mod_table_open(const char* uri, remote_handle* handle, char* dlerr, int dlerrorLen, int* pdlErr) {
+   int nErr = AEE_SUCCESS;
+   struct open_mod_table* pomt = 0;
+   FARF(HIGH, "mod_table_open for %s", uri);
+   VERIFY(AEE_SUCCESS == (nErr = HAP_pls_add_lookup((uintptr_t)open_mod_table_ctor_imp, 0, sizeof(*pomt), open_mod_table_ctor_imp, (void*)&static_mod_table_obj, open_mod_table_dtor_imp, (void**)&pomt)));
+   VERIFY(AEE_SUCCESS == (nErr = open_mod_table_open(pomt,uri,handle,dlerr,dlerrorLen,pdlErr)));
+bail:
+   FARF(HIGH, "mod_table_open for %s nErr: %x", uri, nErr);
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: modtable open failed\n", nErr);
+   }
+   return nErr;
+}
+/**
+ * invoke a handle in the mod table
+ *
+ * handle, handle to invoke
+ * sc, scalars, see remote.h for documentation.
+ * pra, args, see remote.h for documentation.
+ */
+int mod_table_invoke(remote_handle handle, uint32 sc, remote_arg* pra) {
+   int nErr = AEE_SUCCESS;
+   struct open_mod_table* pomt = 0;
+   VERIFY(AEE_SUCCESS == (nErr = HAP_pls_add_lookup((uintptr_t)open_mod_table_ctor_imp, 0, sizeof(*pomt), open_mod_table_ctor_imp, (void*)&static_mod_table_obj, open_mod_table_dtor_imp, (void**)&pomt)));
+   VERIFY(AEE_SUCCESS == (nErr = open_mod_table_handle_invoke(pomt, handle, sc, pra)));
+bail:
+   return nErr;
+}
+
+/**
+ * Closes a handle in the mod table
+ *
+ * handle, handle to close
+ * errStr, Error String (if an error occurs)
+ * errStrLen, Length of error String (if an error occurs)
+ * pdlErr, Error identifier
+ */
+int mod_table_close(remote_handle handle, char* errStr, int errStrLen, int* pdlErr) {
+   int nErr = AEE_SUCCESS;
+   struct open_mod_table* pomt = 0;
+   VERIFY(AEE_SUCCESS == (nErr = HAP_pls_lookup((uintptr_t)open_mod_table_ctor_imp, 0, (void**)&pomt)));
+   VERIFY(AEE_SUCCESS == (nErr = open_mod_table_close(pomt, handle, errStr,errStrLen,pdlErr)));
+bail:
+   if(nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: modtable close failed\n", nErr);
+   }
+   return nErr;
+}
+
+/**
+ * internal use only
+ */
+int mod_table_register_const_handle(remote_handle remote, const char* uri, int(*pfn)(uint32 sc, remote_arg* pra)) {
+   if(0 == static_mod_table_ctor(&static_mod_table_obj)) {
+      return static_mod_table_register_const_handle(&static_mod_table_obj, remote, 0, uri, pfn, 0);
+   }
+   return AEE_EUNKNOWN;
+}
+int mod_table_register_const_handle1(remote_handle remote, remote_handle64 local, const char* uri, int(*pfn)(remote_handle64, uint32 sc, remote_arg* pra)) {
+   if(0 == static_mod_table_ctor(&static_mod_table_obj)) {
+      return static_mod_table_register_const_handle(&static_mod_table_obj, remote, local, uri, 0, pfn);
+   }
+   return AEE_EUNKNOWN;
+}
+
+// Constructor and destructor
+static int mod_table_ctor(void) {
+	return static_mod_table_ctor(&static_mod_table_obj);
+}
+static void mod_table_dtor(void) {
+	static_mod_table_dtor_imp(&static_mod_table_obj);
+	return;
+}
+
+PL_DEFINE(mod_table, mod_table_ctor, mod_table_dtor);
diff --git a/src/pl_list.c b/src/pl_list.c
new file mode 100644
index 0000000..fc2dd90
--- /dev/null
+++ b/src/pl_list.c
@@ -0,0 +1,40 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "platform_libs.h"
+
+PL_DEP(gpls)
+PL_DEP(listener_android)
+
+struct platform_lib* (*pl_list[])(void) = {
+   PL_ENTRY(gpls),
+   PL_ENTRY(listener_android),
+   0
+};
+
+
diff --git a/src/platform_libs.c b/src/platform_libs.c
new file mode 100644
index 0000000..4cd576b
--- /dev/null
+++ b/src/platform_libs.c
@@ -0,0 +1,121 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#define FARF_ERROR 1
+#include "HAP_farf.h"
+#include "platform_libs.h"
+#include "AEEatomic.h"
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+#include <stdio.h>
+#include <assert.h>
+#include "verify.h"
+
+extern struct platform_lib* (*pl_list[])(void);
+static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd);
+
+int pl_lib_init(struct platform_lib* (*plf)(void)) {
+   int nErr = AEE_SUCCESS;
+   struct platform_lib* pl = plf();
+   if(1 == atomic_Add(&pl->uRefs, 1)) {
+      if(pl->init) {
+         FARF(HIGH, "calling init for %s",pl->name);
+         nErr = pl->init();
+         FARF(HIGH, "init for %s returned %x",pl->name, nErr);
+      }
+      pl->nErr = nErr;
+   }
+   if(pl->nErr != AEE_SUCCESS) {
+      VERIFY_EPRINTF("Error %x: %s init failed", nErr, pl->name);
+   }
+   return pl->nErr;
+}
+
+void pl_lib_deinit(struct platform_lib* (*plf)(void)) {
+   struct platform_lib* pl = plf();
+   if(1 == atomic_IfNotThenAdd(&pl->uRefs, 0, -1)) {
+      if(pl->deinit && pl->nErr == 0) {
+         pl->deinit();
+      }
+   }
+   return;
+}
+
+static int pl_init_lst(struct platform_lib* (*lst[])(void)) {
+   int nErr = AEE_SUCCESS;
+   int ii;
+   for(ii = 0; lst[ii] != 0; ++ii) {
+      nErr = pl_lib_init(lst[ii]);
+      if(nErr != 0) {
+         break;
+      }
+   }
+   if(nErr != AEE_SUCCESS) {
+	VERIFY_EPRINTF("Error %x: plinit failed\n", nErr);
+   }
+   return nErr;
+
+}
+int pl_init(void) {
+   int nErr = pl_init_lst(pl_list);
+   return nErr;
+}
+
+static void pl_deinit_lst(struct platform_lib* (*lst[])(void)) {
+   int size, ii;
+   for(size = 0; lst[size] != 0; ++size) {;}
+   for(ii = size - 1; ii >= 0; --ii) {
+      pl_lib_deinit(lst[ii]);
+   }
+   return;
+}
+
+
+void pl_deinit(void) {
+   pl_deinit_lst(pl_list);
+   return;
+}
+
+static uint32 atomic_IfNotThenAdd(uint32* volatile puDest, uint32 uCompare, int nAdd)
+{
+   uint32 uPrev;
+   uint32 uCurr;
+   do {
+      //check puDest
+      uCurr = *puDest;
+      uPrev = uCurr;
+      //see if we need to update it
+      if(uCurr != uCompare) {
+         //update it
+         uPrev = atomic_CompareAndExchange(puDest, uCurr + nAdd, uCurr);
+      }
+      //verify that the value was the same during the update as when we decided to update
+   } while(uCurr != uPrev);
+   return uPrev;
+}
+
diff --git a/src/remote_priv.h b/src/remote_priv.h
new file mode 100644
index 0000000..60b4cd2
--- /dev/null
+++ b/src/remote_priv.h
@@ -0,0 +1,42 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 REMOTE_PRIV_H
+#define REMOTE_PRIV_H
+
+#include "remote64.h"
+
+// Number of domains extended to include sessions
+// Domain ID extended (0 - 3): Domain id (0 - 3), session id 0
+// Domain ID extended (4 - 7): Domain id (0 - 3), session id 1
+#define NUM_DOMAINS_EXTEND (NUM_DOMAINS * NUM_SESSIONS)
+
+#define FASTRPC_SESSION_ID1  (4)
+#define FASTRPC_SESSION_URI "&_session=1"
+
+#endif // REMOTE_PRIV_H
diff --git a/src/remotectl_stub.c b/src/remotectl_stub.c
new file mode 100644
index 0000000..eabb7da
--- /dev/null
+++ b/src/remotectl_stub.c
@@ -0,0 +1,656 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 _REMOTECTL_STUB_H
+#define _REMOTECTL_STUB_H
+#include "remotectl.h"
+#ifndef _QAIC_ENV_H
+#define _QAIC_ENV_H
+
+#ifdef __GNUC__
+#ifdef __clang__
+#pragma GCC diagnostic ignored "-Wunknown-pragmas"
+#else
+#pragma GCC diagnostic ignored "-Wpragmas"
+#endif
+#pragma GCC diagnostic ignored "-Wuninitialized"
+#pragma GCC diagnostic ignored "-Wunused-parameter"
+#pragma GCC diagnostic ignored "-Wunused-function"
+#endif
+
+#ifndef _ATTRIBUTE_UNUSED
+
+#ifdef _WIN32
+#define _ATTRIBUTE_UNUSED
+#else
+#define _ATTRIBUTE_UNUSED __attribute__ ((unused))
+#endif
+
+#endif // _ATTRIBUTE_UNUSED
+
+#ifndef __QAIC_REMOTE
+#define __QAIC_REMOTE(ff) ff
+#endif //__QAIC_REMOTE
+
+#ifndef __QAIC_HEADER
+#define __QAIC_HEADER(ff) ff
+#endif //__QAIC_HEADER
+
+#ifndef __QAIC_HEADER_EXPORT
+#define __QAIC_HEADER_EXPORT
+#endif // __QAIC_HEADER_EXPORT
+
+#ifndef __QAIC_HEADER_ATTRIBUTE
+#define __QAIC_HEADER_ATTRIBUTE
+#endif // __QAIC_HEADER_ATTRIBUTE
+
+#ifndef __QAIC_IMPL
+#define __QAIC_IMPL(ff) ff
+#endif //__QAIC_IMPL
+
+#ifndef __QAIC_IMPL_EXPORT
+#define __QAIC_IMPL_EXPORT
+#endif // __QAIC_IMPL_EXPORT
+
+#ifndef __QAIC_IMPL_ATTRIBUTE
+#define __QAIC_IMPL_ATTRIBUTE
+#endif // __QAIC_IMPL_ATTRIBUTE
+
+#ifndef __QAIC_STUB
+#define __QAIC_STUB(ff) ff
+#endif //__QAIC_STUB
+
+#ifndef __QAIC_STUB_EXPORT
+#define __QAIC_STUB_EXPORT
+#endif // __QAIC_STUB_EXPORT
+
+#ifndef __QAIC_STUB_ATTRIBUTE
+#define __QAIC_STUB_ATTRIBUTE
+#endif // __QAIC_STUB_ATTRIBUTE
+
+#ifndef __QAIC_SKEL
+#define __QAIC_SKEL(ff) ff
+#endif //__QAIC_SKEL__
+
+#ifndef __QAIC_SKEL_EXPORT
+#define __QAIC_SKEL_EXPORT
+#endif // __QAIC_SKEL_EXPORT
+
+#ifndef __QAIC_SKEL_ATTRIBUTE
+#define __QAIC_SKEL_ATTRIBUTE
+#endif // __QAIC_SKEL_ATTRIBUTE
+
+#ifdef __QAIC_DEBUG__
+   #ifndef __QAIC_DBG_PRINTF__
+   #include <stdio.h>
+   #define __QAIC_DBG_PRINTF__( ee ) do { printf ee ; } while(0)
+   #endif
+#else
+   #define __QAIC_DBG_PRINTF__( ee ) (void)0
+#endif
+
+
+#define _OFFSET(src, sof)  ((void*)(((char*)(src)) + (sof)))
+
+#define _COPY(dst, dof, src, sof, sz)  \
+   do {\
+         struct __copy { \
+            char ar[sz]; \
+         };\
+         *(struct __copy*)_OFFSET(dst, dof) = *(struct __copy*)_OFFSET(src, sof);\
+   } while (0)
+
+#define _COPYIF(dst, dof, src, sof, sz)  \
+   do {\
+      if(_OFFSET(dst, dof) != _OFFSET(src, sof)) {\
+         _COPY(dst, dof, src, sof, sz); \
+      } \
+   } while (0)
+
+_ATTRIBUTE_UNUSED
+static __inline void _qaic_memmove(void* dst, void* src, int size) {
+   int i;
+   for(i = 0; i < size; ++i) {
+      ((char*)dst)[i] = ((char*)src)[i];
+   }
+}
+
+#define _MEMMOVEIF(dst, src, sz)  \
+   do {\
+      if(dst != src) {\
+         _qaic_memmove(dst, src, sz);\
+      } \
+   } while (0)
+
+
+#define _ASSIGN(dst, src, sof)  \
+   do {\
+      dst = OFFSET(src, sof); \
+   } while (0)
+
+#define _STD_STRLEN_IF(str) (str == 0 ? 0 : strlen(str))
+
+#include "AEEStdErr.h"
+
+#define _TRY(ee, func) \
+   do { \
+      if (AEE_SUCCESS != ((ee) = func)) {\
+         __QAIC_DBG_PRINTF__((__FILE__ ":%d:error:%d:%s\n", __LINE__, (int)(ee),#func));\
+         goto ee##bail;\
+      } \
+   } while (0)
+
+#define _CATCH(exception) exception##bail: if (exception != AEE_SUCCESS)
+
+#define _ASSERT(nErr, ff) _TRY(nErr, 0 == (ff) ? AEE_EBADPARM : AEE_SUCCESS)
+
+#ifdef __QAIC_DEBUG__
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, __FILE_LINE__, size, alignment, (void**)&pv))
+#else
+#define _ALLOCATE(nErr, pal, size, alignment, pv) _TRY(nErr, _allocator_alloc(pal, 0, size, alignment, (void**)&pv))
+#endif
+
+
+#endif // _QAIC_ENV_H
+
+#include "remote.h"
+#include <string.h>
+#ifndef _ALLOCATOR_H
+#define _ALLOCATOR_H
+
+#include <stdlib.h>
+#include <stdint.h>
+
+typedef struct _heap _heap;
+struct _heap {
+   _heap* pPrev;
+   const char* loc;
+   uint64_t buf;
+};
+
+typedef struct _allocator {
+   _heap* pheap;
+   uint8_t* stack;
+   uint8_t* stackEnd;
+   int nSize;
+} _allocator;
+
+_ATTRIBUTE_UNUSED
+static __inline int _heap_alloc(_heap** ppa, const char* loc, int size, void** ppbuf) {
+   _heap* pn = 0;
+   pn = malloc(size + sizeof(_heap) - sizeof(uint64_t));
+   if(pn != 0) {
+      pn->pPrev = *ppa;
+      pn->loc = loc;
+      *ppa = pn;
+      *ppbuf = (void*)&(pn->buf);
+      return 0;
+   } else {
+      return -1;
+   }
+}
+#define _ALIGN_SIZE(x, y) (((x) + (y-1)) & ~(y-1))
+
+_ATTRIBUTE_UNUSED
+static __inline int _allocator_alloc(_allocator* me,
+                                    const char* loc,
+                                    int size,
+                                    unsigned int al,
+                                    void** ppbuf) {
+   if(size < 0) {
+      return -1;
+   } else if (size == 0) {
+      *ppbuf = 0;
+      return 0;
+   }
+   if((_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size) < (uintptr_t)me->stack + me->nSize) {
+      *ppbuf = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al);
+      me->stackEnd = (uint8_t*)_ALIGN_SIZE((uintptr_t)me->stackEnd, al) + size;
+      return 0;
+   } else {
+      return _heap_alloc(&me->pheap, loc, size, ppbuf);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_deinit(_allocator* me) {
+   _heap* pa = me->pheap;
+   while(pa != 0) {
+      _heap* pn = pa;
+      const char* loc = pn->loc;
+      (void)loc;
+      pa = pn->pPrev;
+      free(pn);
+   }
+}
+
+_ATTRIBUTE_UNUSED
+static __inline void _allocator_init(_allocator* me, uint8_t* stack, int stackSize) {
+   me->stack =  stack;
+   me->stackEnd =  stack + stackSize;
+   me->nSize = stackSize;
+   me->pheap = 0;
+}
+
+
+#endif // _ALLOCATOR_H
+
+#ifndef SLIM_H
+#define SLIM_H
+
+#include <stdint.h>
+
+//a C data structure for the idl types that can be used to implement
+//static and dynamic language bindings fairly efficiently.
+//
+//the goal is to have a minimal ROM and RAM footprint and without
+//doing too many allocations.  A good way to package these things seemed
+//like the module boundary, so all the idls within  one module can share
+//all the type references.
+
+
+#define PARAMETER_IN       0x0
+#define PARAMETER_OUT      0x1
+#define PARAMETER_INOUT    0x2
+#define PARAMETER_ROUT     0x3
+#define PARAMETER_INROUT   0x4
+
+//the types that we get from idl
+#define TYPE_OBJECT             0x0
+#define TYPE_INTERFACE          0x1
+#define TYPE_PRIMITIVE          0x2
+#define TYPE_ENUM               0x3
+#define TYPE_STRING             0x4
+#define TYPE_WSTRING            0x5
+#define TYPE_STRUCTURE          0x6
+#define TYPE_UNION              0x7
+#define TYPE_ARRAY              0x8
+#define TYPE_SEQUENCE           0x9
+
+//these require the pack/unpack to recurse
+//so it's a hint to those languages that can optimize in cases where
+//recursion isn't necessary.
+#define TYPE_COMPLEX_STRUCTURE  (0x10 | TYPE_STRUCTURE)
+#define TYPE_COMPLEX_UNION      (0x10 | TYPE_UNION)
+#define TYPE_COMPLEX_ARRAY      (0x10 | TYPE_ARRAY)
+#define TYPE_COMPLEX_SEQUENCE   (0x10 | TYPE_SEQUENCE)
+
+
+typedef struct Type Type;
+
+#define INHERIT_TYPE\
+   int32_t nativeSize;                /*in the simple case its the same as wire size and alignment*/\
+   union {\
+      struct {\
+         const uintptr_t         p1;\
+         const uintptr_t         p2;\
+      } _cast;\
+      struct {\
+         uint32_t  iid;\
+         uint32_t  bNotNil;\
+      } object;\
+      struct {\
+         const Type  *arrayType;\
+         int32_t      nItems;\
+      } array;\
+      struct {\
+         const Type *seqType;\
+         int32_t      nMaxLen;\
+      } seqSimple; \
+      struct {\
+         uint32_t bFloating;\
+         uint32_t bSigned;\
+      } prim; \
+      const SequenceType* seqComplex;\
+      const UnionType  *unionType;\
+      const StructType *structType;\
+      int32_t         stringMaxLen;\
+      uint8_t        bInterfaceNotNil;\
+   } param;\
+   uint8_t    type;\
+   uint8_t    nativeAlignment\
+
+typedef struct UnionType UnionType;
+typedef struct StructType StructType;
+typedef struct SequenceType SequenceType;
+struct Type {
+   INHERIT_TYPE;
+};
+
+struct SequenceType {
+   const Type *         seqType;
+   uint32_t               nMaxLen;
+   uint32_t               inSize;
+   uint32_t               routSizePrimIn;
+   uint32_t               routSizePrimROut;
+};
+
+//byte offset from the start of the case values for
+//this unions case value array.  it MUST be aligned
+//at the alignment requrements for the descriptor
+//
+//if negative it means that the unions cases are
+//simple enumerators, so the value read from the descriptor
+//can be used directly to find the correct case
+typedef union CaseValuePtr CaseValuePtr;
+union CaseValuePtr {
+   const uint8_t*   value8s;
+   const uint16_t*  value16s;
+   const uint32_t*  value32s;
+   const uint64_t*  value64s;
+};
+
+//these are only used in complex cases
+//so I pulled them out of the type definition as references to make
+//the type smaller
+struct UnionType {
+   const Type           *descriptor;
+   uint32_t               nCases;
+   const CaseValuePtr   caseValues;
+   const Type * const   *cases;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+   uint8_t                inCaseAlignment;
+   uint8_t                routCaseAlignmentPrimIn;
+   uint8_t                routCaseAlignmentPrimROut;
+   uint8_t                nativeCaseAlignment;
+   uint8_t              bDefaultCase;
+};
+
+struct StructType {
+   uint32_t               nMembers;
+   const Type * const   *members;
+   int32_t               inSize;
+   int32_t               routSizePrimIn;
+   int32_t               routSizePrimROut;
+   uint8_t                inAlignment;
+   uint8_t                routAlignmentPrimIn;
+   uint8_t                routAlignmentPrimROut;
+};
+
+typedef struct Parameter Parameter;
+struct Parameter {
+   INHERIT_TYPE;
+   uint8_t    mode;
+   uint8_t  bNotNil;
+};
+
+#define SLIM_IFPTR32(is32,is64) (sizeof(uintptr_t) == 4 ? (is32) : (is64))
+#define SLIM_SCALARS_IS_DYNAMIC(u) (((u) & 0x00ffffff) == 0x00ffffff)
+
+typedef struct Method Method;
+struct Method {
+   uint32_t                    uScalars;            //no method index
+   int32_t                     primInSize;
+   int32_t                     primROutSize;
+   int                         maxArgs;
+   int                         numParams;
+   const Parameter * const     *params;
+   uint8_t                       primInAlignment;
+   uint8_t                       primROutAlignment;
+};
+
+typedef struct Interface Interface;
+
+struct Interface {
+   int                            nMethods;
+   const Method  * const          *methodArray;
+   int                            nIIds;
+   const uint32_t                   *iids;
+   const uint16_t*                  methodStringArray;
+   const uint16_t*                  methodStrings;
+   const char*                    strings;
+};
+
+
+#endif //SLIM_H
+
+
+#ifndef _REMOTECTL_SLIM_H
+#define _REMOTECTL_SLIM_H
+#include "remote.h"
+#include <stdint.h>
+
+#ifndef __QAIC_SLIM
+#define __QAIC_SLIM(ff) ff
+#endif
+#ifndef __QAIC_SLIM_EXPORT
+#define __QAIC_SLIM_EXPORT
+#endif
+
+static const Type types[2];
+static const Type types[2] = {{0x1,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x1},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4}};
+static const Parameter parameters[6] = {{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)0x0,0}}, 4,SLIM_IFPTR32(0x4,0x8),0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,3,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(types[0]),(const uintptr_t)0x0}}, 9,SLIM_IFPTR32(0x4,0x8),3,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)1}}, 2,0x4,0,0},{0x4,{{(const uintptr_t)0,(const uintptr_t)0}}, 2,0x4,0,0},{SLIM_IFPTR32(0x8,0x10),{{(const uintptr_t)&(types[1]),(const uintptr_t)0x0}}, 9,SLIM_IFPTR32(0x4,0x8),0,0}};
+static const Parameter* const parameterArrays[11] = {(&(parameters[0])),(&(parameters[1])),(&(parameters[2])),(&(parameters[1])),(&(parameters[3])),(&(parameters[2])),(&(parameters[1])),(&(parameters[3])),(&(parameters[5])),(&(parameters[4])),(&(parameters[4]))};
+static const Method methods[4] = {{REMOTE_SCALARS_MAKEX(0,0,0x2,0x2,0x0,0x0),0x8,0x8,6,4,(&(parameterArrays[0])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x2,0x0,0x0),0x8,0x4,5,3,(&(parameterArrays[4])),0x4,0x4},{REMOTE_SCALARS_MAKEX(0,0,0x1,0x0,0x0,0x0),0x8,0x0,2,2,(&(parameterArrays[9])),0x4,0x0},{REMOTE_SCALARS_MAKEX(0,0,0x2,0x0,0x0,0x0),0x8,0x0,3,2,(&(parameterArrays[7])),0x4,0x0}};
+static const Method* const methodArrays[4] = {&(methods[0]),&(methods[1]),&(methods[2]),&(methods[3])};
+static const char strings[83] = "set_param\0grow_heap\0phyAddr\0dlerror\0params\0handle\0reqID\0nSize\0close\0nErr\0name\0open\0";
+static const uint16_t methodStrings[15] = {78,73,43,28,68,62,43,28,68,0,50,36,10,20,56};
+static const uint16_t methodStringsArrays[4] = {0,5,12,9};
+__QAIC_SLIM_EXPORT const Interface __QAIC_SLIM(remotectl_slim) = {4,&(methodArrays[0]),0,0,&(methodStringsArrays [0]),methodStrings,strings};
+#endif //_REMOTECTL_SLIM_H
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifndef _const_remotectl_handle
+#define _const_remotectl_handle ((remote_handle)-1)
+#endif //_const_remotectl_handle
+
+static void _remotectl_pls_dtor(void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   if(_const_remotectl_handle != *ph) {
+      (void)__QAIC_REMOTE(remote_handle_close)(*ph);
+      *ph = _const_remotectl_handle;
+   }
+}
+
+static int _remotectl_pls_ctor(void* ctx, void* data) {
+   remote_handle* ph = (remote_handle*)data;
+   *ph = _const_remotectl_handle;
+   if(*ph == (remote_handle)-1) {
+      return __QAIC_REMOTE(remote_handle_open)((const char*)ctx, ph);
+   }
+   return 0;
+}
+
+#if (defined __qdsp6__) || (defined __hexagon__)
+#pragma weak  adsp_pls_add_lookup
+extern int adsp_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+#pragma weak  HAP_pls_add_lookup
+extern int HAP_pls_add_lookup(uint32_t type, uint32_t key, int size, int (*ctor)(void* ctx, void* data), void* ctx, void (*dtor)(void* ctx), void** ppo);
+
+__QAIC_STUB_EXPORT remote_handle _remotectl_handle(void) {
+   remote_handle* ph;
+   if(adsp_pls_add_lookup) {
+      if(0 == adsp_pls_add_lookup((uint32_t)_remotectl_handle, 0, sizeof(*ph),  _remotectl_pls_ctor, "remotectl",  _remotectl_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   } else if(HAP_pls_add_lookup) {
+      if(0 == HAP_pls_add_lookup((uint32_t)_remotectl_handle, 0, sizeof(*ph),  _remotectl_pls_ctor, "remotectl",  _remotectl_pls_dtor, (void**)&ph))  {
+         return *ph;
+      }
+      return (remote_handle)-1;
+   }
+   return(remote_handle)-1;
+}
+
+#else //__qdsp6__ || __hexagon__
+
+uint32_t _remotectl_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare);
+
+#ifdef _WIN32
+#include "Windows.h"
+uint32_t _remotectl_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return (uint32_t)InterlockedCompareExchange((volatile LONG*)puDest, (LONG)uExchange, (LONG)uCompare);
+}
+#elif __GNUC__
+uint32_t _remotectl_atomic_CompareAndExchange(uint32_t * volatile puDest, uint32_t uExchange, uint32_t uCompare) {
+   return __sync_val_compare_and_swap(puDest, uCompare, uExchange);
+}
+#endif //_WIN32
+
+
+__QAIC_STUB_EXPORT remote_handle _remotectl_handle(void) {
+   static remote_handle handle = _const_remotectl_handle;
+   if((remote_handle)-1 != handle) {
+      return handle;
+   } else {
+      remote_handle tmp;
+      int nErr = _remotectl_pls_ctor("remotectl", (void*)&tmp);
+      if(nErr) {
+         return (remote_handle)-1;
+      }
+      if(((remote_handle)-1 != handle) || ((remote_handle)-1 != (remote_handle)_remotectl_atomic_CompareAndExchange((uint32_t*)&handle, (uint32_t)tmp, (uint32_t)-1))) {
+         _remotectl_pls_dtor(&tmp);
+      }
+      return handle;
+   }
+}
+
+#endif //__qdsp6__
+
+__QAIC_STUB_EXPORT int __QAIC_STUB(remotectl_skel_invoke)(uint32_t _sc, remote_arg* _pra) __QAIC_STUB_ATTRIBUTE {
+   return __QAIC_REMOTE(remote_handle_invoke)(_remotectl_handle(), _sc, _pra);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+extern int remote_register_dma_handle(int, uint32_t);
+static __inline int _stub_method(remote_handle _handle, uint32_t _mid, char* _in0[1], uint32_t _rout1[1], char* _rout2[1], uint32_t _rout2Len[1], uint32_t _rout3[1]) {
+   uint32_t _in0Len[1];
+   int _numIn[1];
+   remote_arg _pra[4];
+   uint32_t _primIn[2];
+   uint32_t _primROut[2];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _numIn[0] = 1;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _pra[(_numIn[0] + 1)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 1)].buf.nLen = sizeof(_primROut);
+   _in0Len[0] = (1 + strlen(_in0[0]));
+   _COPY(_primIn, 0, _in0Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praIn[0].buf.pv = _in0[0];
+   _praIn[0].buf.nLen = (1 * _in0Len[0]);
+   _COPY(_primIn, 4, _rout2Len, 0, 4);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _praROut[0].buf.pv = _rout2[0];
+   _praROut[0].buf.nLen = (1 * _rout2Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 2, 2, 0, 0), _pra));
+   _COPY(_rout1, 0, _primROut, 0, 4);
+   _COPY(_rout3, 0, _primROut, 4, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(remotectl_open)(const char* name, int* handle, char* dlerror, int dlerrorLen, int* nErr) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 0;
+   return _stub_method(_remotectl_handle(), _mid, (char**)&name, (uint32_t*)handle, (char**)&dlerror, (uint32_t*)&dlerrorLen, (uint32_t*)nErr);
+}
+static __inline int _stub_method_1(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], char* _rout1[1], uint32_t _rout1Len[1], uint32_t _rout2[1]) {
+   int _numIn[1];
+   remote_arg _pra[3];
+   uint32_t _primIn[2];
+   uint32_t _primROut[1];
+   remote_arg* _praIn;
+   remote_arg* _praROut;
+   int _nErr = 0;
+   _numIn[0] = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _pra[(_numIn[0] + 1)].buf.pv = (void*)_primROut;
+   _pra[(_numIn[0] + 1)].buf.nLen = sizeof(_primROut);
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _rout1Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praROut = (_praIn + _numIn[0] + 1);
+   _praROut[0].buf.pv = _rout1[0];
+   _praROut[0].buf.nLen = (1 * _rout1Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 1, 2, 0, 0), _pra));
+   _COPY(_rout2, 0, _primROut, 0, 4);
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(remotectl_close)(int handle, char* dlerror, int dlerrorLen, int* nErr) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 1;
+   return _stub_method_1(_remotectl_handle(), _mid, (uint32_t*)&handle, (char**)&dlerror, (uint32_t*)&dlerrorLen, (uint32_t*)nErr);
+}
+static __inline int _stub_method_2(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], uint32_t _in1[1]) {
+   remote_arg _pra[1];
+   uint32_t _primIn[2];
+   int _nErr = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _in1, 0, 4);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 1, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(remotectl_grow_heap)(uint32 phyAddr, uint32 nSize) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 2;
+   return _stub_method_2(_remotectl_handle(), _mid, (uint32_t*)&phyAddr, (uint32_t*)&nSize);
+}
+static __inline int _stub_method_3(remote_handle _handle, uint32_t _mid, uint32_t _in0[1], char* _in1[1], uint32_t _in1Len[1]) {
+   remote_arg _pra[2];
+   uint32_t _primIn[2];
+   remote_arg* _praIn;
+   int _nErr = 0;
+   _pra[0].buf.pv = (void*)_primIn;
+   _pra[0].buf.nLen = sizeof(_primIn);
+   _COPY(_primIn, 0, _in0, 0, 4);
+   _COPY(_primIn, 4, _in1Len, 0, 4);
+   _praIn = (_pra + 1);
+   _praIn[0].buf.pv = _in1[0];
+   _praIn[0].buf.nLen = (4 * _in1Len[0]);
+   _TRY(_nErr, __QAIC_REMOTE(remote_handle_invoke)(_handle, REMOTE_SCALARS_MAKEX(0, _mid, 2, 0, 0, 0), _pra));
+   _CATCH(_nErr) {}
+   return _nErr;
+}
+__QAIC_STUB_EXPORT int __QAIC_STUB(remotectl_set_param)(int reqID, const uint32* params, int paramsLen) __QAIC_STUB_ATTRIBUTE {
+   uint32_t _mid = 3;
+   return _stub_method_3(_remotectl_handle(), _mid, (uint32_t*)&reqID, (char**)&params, (uint32_t*)&paramsLen);
+}
+#ifdef __cplusplus
+}
+#endif
+#endif //_REMOTECTL_STUB_H
diff --git a/src/rpcmem_android.c b/src/rpcmem_android.c
new file mode 100644
index 0000000..ecac123
--- /dev/null
+++ b/src/rpcmem_android.c
@@ -0,0 +1,183 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include "rpcmem.h"
+#include "verify.h"
+#include "fastrpc_internal.h"
+#include "AEEQList.h"
+#include "AEEstd.h"
+#include "apps_std.h"
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <fcntl.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <errno.h>
+
+#define PAGE_SIZE 4096
+#define PAGE_MASK ~((uintptr_t)PAGE_SIZE - 1)
+
+static QList rpclst;
+static pthread_mutex_t rpcmt;
+struct rpc_info
+{
+	QNode qn;
+	void *buf;
+	void *aligned_buf;
+	int size;
+	int fd;
+};
+
+extern int open_device_node(int domain);
+static int rpcmem_open_dev()
+{
+	return open_device_node(3);
+}
+
+void rpcmem_init()
+{
+	int fd;
+	QList_Ctor(&rpclst);
+	pthread_mutex_init(&rpcmt, 0);
+}
+
+void rpcmem_deinit()
+{
+	pthread_mutex_destroy(&rpcmt);
+}
+
+int rpcmem_to_fd_internal(void *po) {
+	struct rpc_info *rinfo, *rfree = 0;
+	QNode *pn, *pnn;
+
+	pthread_mutex_lock(&rpcmt);
+	QLIST_NEXTSAFE_FOR_ALL(&rpclst, pn, pnn)
+	{
+		rinfo = STD_RECOVER_REC(struct rpc_info, qn, pn);
+		if (rinfo->aligned_buf == po)
+		{
+			rfree = rinfo;
+			break;
+		}
+	}
+	pthread_mutex_unlock(&rpcmt);
+
+	if (rfree)
+		return rfree->fd;
+
+	return -1;
+}
+
+int rpcmem_to_fd(void *po) {
+	return rpcmem_to_fd_internal(po);
+}
+
+
+void *rpcmem_alloc_internal(int heapid, uint32 flags, int size)
+{
+	struct rpc_info *rinfo;
+	struct fastrpc_alloc_dma_buf buf;
+	int nErr = 0;
+	(void)heapid;
+	(void)flags;
+	int dev = rpcmem_open_dev();
+
+	VERIFY(0 != (rinfo = calloc(1, sizeof(*rinfo))));
+
+	buf.size = size + PAGE_SIZE;
+	buf.fd = -1;
+	buf.flags = 0;
+
+	VERIFY((0 == ioctl(dev, FASTRPC_IOCTL_ALLOC_DMA_BUFF, (unsigned long)&buf)) || errno == ENOTTY);
+	VERIFY(0 != (rinfo->buf = mmap(0, size, PROT_READ | PROT_WRITE, MAP_SHARED, buf.fd, 0)));
+	rinfo->fd = buf.fd;
+	rinfo->aligned_buf = (void *)(((uintptr_t)rinfo->buf /*+ PAGE_SIZE*/) & PAGE_MASK);
+	rinfo->aligned_buf = rinfo->buf;
+	rinfo->size = size;
+	pthread_mutex_lock(&rpcmt);
+	QList_AppendNode(&rpclst, &rinfo->qn);
+	pthread_mutex_unlock(&rpcmt);
+
+	return rinfo->aligned_buf;
+bail:
+	if (nErr)
+	{
+		if (rinfo)
+		{
+			if (rinfo->buf)
+			{
+				free(rinfo->buf);
+			}
+			free(rinfo);
+		}
+	}
+	return 0;
+}
+
+void rpcmem_free_internal(void *po)
+{
+	struct rpc_info *rinfo, *rfree = 0;
+	QNode *pn, *pnn;
+	int nErr = 0;
+
+	pthread_mutex_lock(&rpcmt);
+	QLIST_NEXTSAFE_FOR_ALL(&rpclst, pn, pnn)
+	{
+		rinfo = STD_RECOVER_REC(struct rpc_info, qn, pn);
+		if (rinfo->aligned_buf == po)
+		{
+			rfree = rinfo;
+			QNode_Dequeue(&rinfo->qn);
+			break;
+		}
+	}
+	pthread_mutex_unlock(&rpcmt);
+	if (rfree)
+	{
+		int dev = rpcmem_open_dev();
+
+		munmap(rfree->buf, rfree->size);
+		free(rfree);
+	}
+bail:
+	return;
+
+}
+
+void rpcmem_free(void* po) {
+    rpcmem_free_internal(po);
+}
+
+void* rpcmem_alloc(int heapid, uint32 flags, int size) {
+	return rpcmem_alloc_internal(heapid, flags, size);
+}
diff --git a/src/smath.c b/src/smath.c
new file mode 100644
index 0000000..f7fb28b
--- /dev/null
+++ b/src/smath.c
@@ -0,0 +1,54 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include "AEEStdDef.h"
+#include "AEEsmath.h"
+
+
+static int32 ToInt(int64 a)
+{
+   return (a > MAX_INT32 ? MAX_INT32 :
+           a < MIN_INT32 ? MIN_INT32 :
+           (int32)a);
+}
+
+int smath_Add(int a, int b)
+{
+   return ToInt((int64)a + (int64)b);
+}
+
+int smath_Sub(int a, int b)
+{
+   return ToInt((int64)a - (int64)b);
+}
+
+int smath_Mul(int a, int b)
+{
+   return ToInt((int64)a * (int64)b);
+}
diff --git a/src/std.c b/src/std.c
new file mode 100644
index 0000000..d369d99
--- /dev/null
+++ b/src/std.c
@@ -0,0 +1,570 @@
+/**
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+ 
+/*
+=======================================================================
+
+FILE:         std.c
+
+SERVICES:     apiOne std lib string stuff
+
+=======================================================================
+*/
+
+//
+// someday, drop this #include, implement our own memmove()
+//
+#include <stddef.h>
+#include "AEEstd.h"
+#include "version.h"
+
+int  std_getversion(char *pcDst, int nDestSize)
+{
+   return std_strlcpy(pcDst, VERSION_STRING, nDestSize);
+}
+
+
+char std_tolower(char c)
+{
+   if ((c >= 'A') && (c <= 'Z')) {
+      c |= 32;
+   }
+   return c;
+}
+
+char std_toupper(char c)
+{
+   if ((c >= 'a') && (c <= 'z')) {
+      c &= ~32;
+   }
+   return c;
+}
+
+
+static __inline int x_casecmp(unsigned char c1, unsigned char c2)
+{
+   int diff = c1 - c2;
+   if (c1 >= 'A' && c1 <= 'Z') {
+      diff += 32;
+   }
+   if (c2 >= 'A' && c2 <= 'Z') {
+      diff -= 32;
+   }
+   return diff;
+}
+
+
+int std_strncmp(const char* s1, const char* s2, int n)
+{
+   if (n > 0) {
+      int i = 0;
+
+      do {
+         unsigned char c1 = (unsigned char)s1[i];
+         unsigned char c2 = (unsigned char)s2[i];
+         int  diff = c1 - c2;
+
+         if (diff) {
+            return diff;
+         }
+
+         if ('\0' == c1) {
+            break;
+         }
+         i++;
+      } while (i < n);
+   }
+
+   return 0;
+}
+
+int std_strcmp(const char* s1, const char* s2)
+{
+   return std_strncmp(s1, s2, MAX_INT32);
+}
+
+int std_strnicmp(const char* s1, const char* s2, int n)
+{
+   if (n > 0) {
+      int i = -n;
+
+      s1 += n;
+      s2 += n;
+
+      do {
+         unsigned char c1 = (unsigned char)s1[i];
+         unsigned char c2 = (unsigned char)s2[i];
+
+         int diff = x_casecmp(c1,c2);
+         if (diff) {
+            return diff;
+         }
+         if ('\0' == c1) {
+            break;
+         }
+      } while (++i);
+   }
+   return 0;
+}
+
+int std_stricmp(const char* s1, const char* s2)
+{
+   return std_strnicmp(s1, s2, MAX_INT32);
+}
+
+int std_strlcpy(char* pcDst, const char* cpszSrc, int nDestSize)
+{
+   int nLen = std_strlen(cpszSrc);
+
+   if (0 < nDestSize) {
+      int n;
+
+      n = STD_MIN(nLen, nDestSize - 1);
+      (void)std_memmove(pcDst, cpszSrc, n);
+
+      pcDst[n] = 0;
+   }
+
+   return nLen;
+}
+
+int std_strlcat(char* pcDst, const char* cpszSrc, int nDestSize)
+{
+   int nLen = 0;
+
+   while ((nLen < nDestSize) && (0 != pcDst[nLen])) {
+      ++nLen;
+   }
+
+   return nLen + std_strlcpy(pcDst+nLen, cpszSrc, nDestSize-nLen);
+}
+
+char* std_strstr(const char* cpszHaystack, const char* cpszNeedle)
+{
+   /* Check the empty needle string as a special case */
+   if ('\0' == *cpszNeedle ) {
+      return (char*)cpszHaystack;
+   }
+
+   while ('\0' != *cpszHaystack) {
+      /* Find the first character of the needle string in the haystack string */
+      if (*cpszHaystack == *cpszNeedle) {
+         /* check if the rest of the string matches */
+         const char* pHaystack = cpszHaystack;
+         const char* pNeedle = cpszNeedle;
+         do {
+            if ('\0' == *++pNeedle) {
+               /* Found a match */
+               return (char*)cpszHaystack;
+            }
+         } while (*++pHaystack == *pNeedle);
+      }
+      cpszHaystack++;
+   }
+
+   return 0;
+}
+
+
+int std_memcmp(const void* p1, const void* p2, int length)
+{
+   const unsigned char *cpc1 = p1;
+   const unsigned char *cpc2 = p2;
+
+   while (length-- > 0) {
+      int diff = *cpc1++ - *cpc2++;
+
+      if (0 != diff) {
+         return diff;
+      }
+   }
+   return 0;
+}
+
+int std_wstrlen(const AECHAR* s)
+{
+   const AECHAR *sEnd = s;
+
+   if (! *sEnd)
+      return 0;
+
+   do {
+      ++sEnd;
+   } while (*sEnd);
+
+   return sEnd - s;
+}
+
+
+int std_wstrlcpy(AECHAR* pwcDst, const AECHAR* cpwszSrc, int nDestSize)
+{
+   int nLen = std_wstrlen(cpwszSrc);
+
+   if (0 < nDestSize) {
+      int n;
+
+      n = STD_MIN(nLen, nDestSize - 1);
+      /* call memmove, in case n is larger than 1G */
+      (void)std_memsmove(pwcDst, nDestSize*sizeof(AECHAR),
+                     cpwszSrc, ((size_t)n)*sizeof(AECHAR));
+
+      pwcDst[n] = 0;
+   }
+
+   return nLen;
+}
+
+int std_wstrlcat(AECHAR* pwcDst, const AECHAR* cpwszSrc, int nDestSize)
+{
+   int nLen = 0;
+
+   while ((nLen < nDestSize) && (0 != pwcDst[nLen])) {
+      ++nLen;
+   }
+
+   return nLen + std_wstrlcpy(pwcDst+nLen, cpwszSrc, nDestSize-nLen);
+}
+
+char* std_strchrend(const char* cpsz, char c)
+{
+   while (*cpsz && *cpsz != c) {
+      ++cpsz;
+   }
+   return (char*)cpsz;
+}
+
+char* std_strchr(const char* cpszSrch, int c)
+{
+   const char *pc = std_strchrend(cpszSrch, (char)c);
+
+   return (*pc == c ? (char*)pc : 0);
+}
+
+void* std_memstr(const char* cpHaystack, const char* cpszNeedle,
+                 int nHaystackLen)
+{
+   int nLen = 0;
+
+   /* Handle empty needle string as a special case */
+   if ('\0' == *cpszNeedle ) {
+      return (char*)cpHaystack;
+   }
+
+   /* Find the first character of the needle string in the haystack string */
+   while (nLen < nHaystackLen) {
+      if (cpHaystack[nLen] == *cpszNeedle) {
+         /* check if the rest of the string matches */
+         const char* cpNeedle = cpszNeedle;
+         int nRetIndex = nLen;
+         do {
+            if ('\0' == *++cpNeedle) {
+               /* Found a match */
+               return (void*)(cpHaystack + nRetIndex);
+            }
+            nLen++;
+         } while(cpHaystack[nLen] == *cpNeedle);
+      }
+      else {
+         nLen++;
+      }
+   }
+
+   return 0;
+}
+
+void* std_memchrend(const void* p, int c, int nLen)
+{
+   const char* cpc = (const char*)p + nLen;
+   int i = -nLen;
+
+   if (nLen > 0) {
+      do {
+         if (cpc[i] == c) {
+            break;
+         }
+      } while (++i);
+   }
+   return (void*) (cpc + i);
+}
+
+void* std_memchr(const void* s, int c, int n)
+{
+   const char *pEnd = (const char*)std_memchrend(s,c,n);
+   int nEnd = pEnd - (const char*)s;
+
+   if (nEnd < n) {
+      return (void*)pEnd;
+   }
+   return 0;
+}
+
+void* std_memrchr(const void* p, int c, int nLen)
+{
+   const char* cpc = (const char*)p - 1;
+
+   if (nLen > 0) {
+      do {
+         if (cpc[nLen] == c) {
+            return (void*) (cpc + nLen);
+         }
+      } while (--nLen);
+   }
+
+   return 0;
+}
+
+
+char* std_strrchr(const char* cpsz, int c)
+{
+   return std_memrchr(cpsz, c, std_strlen(cpsz) + 1);
+}
+
+
+void* std_memrchrbegin(const void* p, int c, int n)
+{
+   void *pOut = std_memrchr(p, c, n);
+
+   return (pOut ? pOut : (void*)p);
+}
+
+
+// x_scanbytes: internal function;  WARNING:  nLen must be >0
+//
+// cStop = character at which to stop (in addition to cpszChars[...])
+//
+// Using a bit mask provides a constant-time check for a terminating
+// character: 10 instructions for inner loop on ADS12arm9.  Initialization
+// overhead is increased, but this is quickly made up for as searching begins.
+//
+//
+static char *x_scanbytes(const char *pcBuf, const char* cpszChars,
+                         int nLen, unsigned char cStop, boolean bTestEqual)
+{
+   int n;
+   unsigned a[8];
+
+   // Initialize bit mask based on the input flag that specifies whether
+   // we are looking for a character that matches "any" or "none"
+   // of the characters in the search string
+
+   #define ENTRY(c)   a[((c)&7)]   // c's bit lives here
+   #define SHIFT(c)   ((c)>>3)     // c's bit is shifted by this much
+
+   if (bTestEqual) {
+      std_memset(a, 0, STD_SIZEOF(a));
+      do {
+         ENTRY(cStop) |= (0x80000000U >> SHIFT(cStop));
+         cStop = (unsigned char)*cpszChars++;
+      } while (cStop);
+   }
+   else {
+      std_memset(a, 0xFF, STD_SIZEOF(a));
+
+      while (0 != (cStop = (unsigned char)*cpszChars++)) {
+         ENTRY(cStop) ^= (0x80000000U >> SHIFT(cStop));
+      }
+   }
+
+
+   // Search buffer
+
+   pcBuf += nLen;
+   n = -nLen;
+   do {
+      unsigned char uc = (unsigned char)pcBuf[n];
+      // testing for negative after shift is quicker than comparison
+      if ( (int)(ENTRY(uc) << SHIFT(uc)) < 0) {
+         break;
+      }
+   } while (++n);
+
+   return (char*)(pcBuf+n);
+}
+
+
+void* std_memchrsend(const void* pBuf, const char* cpszChars, int nLen)
+{
+   if (nLen <= 0) {
+      return (void*)pBuf;
+   }
+   if ('\0' == *cpszChars) {
+      return (char*)pBuf + nLen;
+   }
+
+   return x_scanbytes((const char*)pBuf, cpszChars+1, nLen,
+                      (unsigned char)*cpszChars, TRUE);
+}
+
+
+char* std_strchrsend(const char* cpszSrch, const char* cpszChars)
+{
+   return x_scanbytes(cpszSrch, cpszChars, MAX_INT32, '\0', TRUE);
+}
+
+
+char *std_strchrs(const char* cpszSrch, const char* cpszChars)
+{
+   const char *pc = std_strchrsend(cpszSrch, cpszChars);
+
+   return (*pc ? (char*)pc : 0);
+}
+
+
+char* std_striends(const char* cpsz, const char* cpszSuffix)
+{
+   int nOffset = std_strlen(cpsz) - std_strlen(cpszSuffix);
+
+   if ((0 <= nOffset) &&
+       (0 == std_stricmp(cpsz+nOffset, cpszSuffix))) {
+
+      return (char*)(cpsz+nOffset);
+   }
+
+   return 0;
+}
+
+
+char* std_strends(const char* cpsz, const char* cpszSuffix)
+{
+   int nOffset = std_strlen(cpsz) - std_strlen(cpszSuffix);
+
+   if ((0 <= nOffset) &&
+       (0 == std_strcmp(cpsz+nOffset, cpszSuffix))) {
+
+      return (char*)(cpsz + nOffset);
+   }
+
+   return 0;
+}
+
+char* std_strbegins(const char* cpsz, const char* cpszPrefix)
+{
+   for (;;) {
+      if ('\0' == *cpszPrefix) {
+         return (char*)cpsz;
+      }
+
+      if (*cpszPrefix != *cpsz) {
+         return 0;
+      }
+
+      ++cpszPrefix;
+      ++cpsz;
+   }
+   // not reached
+}
+
+char* std_stribegins(const char* cpsz, const char* cpszPrefix)
+{
+   for (;;) {
+      if ('\0' == *cpszPrefix) {
+         return (char*)cpsz;
+      }
+
+      if (x_casecmp((unsigned char)*cpszPrefix, (unsigned char)*cpsz)) {
+         return 0;
+      }
+
+      ++cpszPrefix;
+      ++cpsz;
+   }
+   // not reached
+}
+
+int std_strcspn(const char* cpszSrch, const char* cpszChars)
+{
+   const char *pc = x_scanbytes(cpszSrch, cpszChars, MAX_INT32, '\0', TRUE);
+
+   return (pc - cpszSrch);
+}
+
+int std_strspn(const char* cpszSrch, const char* cpszChars)
+{
+   const char *pc = x_scanbytes(cpszSrch, cpszChars, MAX_INT32, '\0', FALSE);
+
+   return (pc - cpszSrch);
+}
+
+int std_wstrncmp(const AECHAR* s1, const AECHAR* s2, int nLen)
+{
+   if (nLen > 0) {
+      int i;
+
+      s1 += nLen;
+      s2 += nLen;
+      i = -nLen;
+      do {
+         AECHAR c1 = s1[i];
+         AECHAR c2 = s2[i];
+         int  diff = c1 - c2;
+
+         if (diff) {
+            return diff;
+         }
+
+         if ('\0' == c1) {
+            break;
+         }
+      } while (++i);
+   }
+
+   return 0;
+}
+
+int std_wstrcmp(const AECHAR* s1, const AECHAR* s2)
+{
+   return std_wstrncmp(s1, s2, MAX_INT32);
+}
+
+AECHAR* std_wstrchr(const AECHAR* cpwszText, AECHAR ch)
+{
+   for (; ; cpwszText++) {
+      AECHAR chn = *cpwszText;
+
+      if (chn == ch) {
+         return (AECHAR *)cpwszText;
+      }
+      else if ( chn == (AECHAR)0 ) {
+         return 0;
+      }
+   }
+}
+
+AECHAR* std_wstrrchr(const AECHAR* cpwszText, AECHAR ch)
+{
+   const AECHAR* p = 0;
+
+   do {
+      if (*cpwszText == ch) {
+         p = cpwszText;
+      }
+   } while (*cpwszText++ != (AECHAR)0);
+
+   return (AECHAR*)p;
+}
diff --git a/src/std_SwapBytes.c b/src/std_SwapBytes.c
new file mode 100644
index 0000000..7caf5db
--- /dev/null
+++ b/src/std_SwapBytes.c
@@ -0,0 +1,194 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+#include "AEEstd.h"
+#include "AEEsmath.h"
+
+
+
+static int xMinSize(int a, int b)
+{
+   if (b < a) {
+      a = b;
+   }
+   return (a >= 0 ? a : 0);
+}
+
+
+static void xMoveBytes(byte *pbDest, const byte *pbSrc, int cb)
+{
+   if (pbDest != pbSrc) {
+      (void) std_memmove(pbDest, pbSrc, cb);
+   }
+}
+
+
+#ifdef AEE_BIGENDIAN
+#  define STD_COPY       std_CopyBE
+#  define STD_COPY_SWAP  std_CopyLE
+#else
+#  define STD_COPY       std_CopyLE
+#  define STD_COPY_SWAP  std_CopyBE
+#endif
+
+
+// See std_CopyLE/BE for documentation.  This function implements the case
+// where host ordering != target byte ordering.
+//
+int STD_COPY_SWAP(void *      pvDest, int nDestSize,
+                  const void *pvSrc,  int nSrcSize,
+                  const char *pszFields)
+{
+   byte* pbDest = (byte*)pvDest;
+   byte* pbSrc  = (byte*)pvSrc;
+   int cbCopied = xMinSize(nDestSize, nSrcSize);
+   const char * pszNextField;
+   int cb, nSize;
+
+   nSize = 0;  // avoid warning when using RVCT2.2 with -O1
+
+   pszNextField = pszFields;
+
+   for (cb = cbCopied; cb > 0; cb -= nSize) {
+      char  ch;
+
+      ch = *pszNextField++;
+      if ('\0' == ch) {
+         ch = *pszFields;
+         pszNextField = pszFields+1;
+      }
+
+      if (ch == 'S') {
+
+         // S = 2 bytes
+
+         nSize = 2;
+         if (cb < nSize) {
+            break;
+         } else {
+            byte by   = pbSrc[0];
+            pbDest[0] = pbSrc[1];
+            pbDest[1] = by;
+         }
+      } else if (ch == 'L') {
+
+         // L = 4 bytes
+
+         nSize = 4;
+         if (cb < nSize) {
+            break;
+         } else {
+            byte by   = pbSrc[0];
+            pbDest[0] = pbSrc[3];
+            pbDest[3] = by;
+            by        = pbSrc[1];
+            pbDest[1] = pbSrc[2];
+            pbDest[2] = by;
+         }
+      } else if (ch == 'Q') {
+
+         // Q = 8 bytes
+
+         nSize = 8;
+         if (cb < nSize) {
+            break;
+         } else {
+            byte by   = pbSrc[0];
+            pbDest[0] = pbSrc[7];
+            pbDest[7] = by;
+            by        = pbSrc[1];
+            pbDest[1] = pbSrc[6];
+            pbDest[6] = by;
+            by        = pbSrc[2];
+            pbDest[2] = pbSrc[5];
+            pbDest[5] = by;
+            by        = pbSrc[3];
+            pbDest[3] = pbSrc[4];
+            pbDest[4] = by;
+         }
+      } else {
+
+         // None of the above => read decimal and copy without swap
+
+         if (ch >= '0' && ch <= '9') {
+            nSize = (int) (ch - '0');
+            while ( (ch = *pszNextField) >= '0' && ch <= '9') {
+               nSize = nSize*10 + (int)(ch - '0');
+               ++pszNextField;
+            }
+            // Check bounds & ensure progress
+            if (nSize > cb || nSize <= 0) {
+               nSize = cb;
+            }
+         } else {
+            // Unexpected character: copy rest of data
+            nSize = cb;
+         }
+
+         xMoveBytes(pbDest, pbSrc, nSize);
+      }
+
+      pbDest += nSize;
+      pbSrc += nSize;
+   }
+
+   if (cb > 0) {
+
+      // Swap could not be completed:  0 < cb < nSize <= 8
+
+      byte byBuf[8];
+
+      // If entire value is available in source, use swapped version
+      if (nSrcSize - (pbSrc - (byte*)pvSrc) >= nSize) {
+         int i;
+         for (i=0; i<cb; ++i) {
+            byBuf[i] = pbSrc[nSize-1-i];
+         }
+         pbSrc = byBuf;
+      }
+      std_memmove(pbDest, pbSrc, cb);
+   }
+
+   return cbCopied;
+}
+
+
+// See std_CopyLE/BE for documentation.  This function implements the case
+// where host ordering == target byte ordering.
+//
+int STD_COPY(void *pvDest, int nDestSize,
+             const void *pvSrc,  int nSrcSize,
+             const char *pszFields)
+{
+   int cb = xMinSize(nDestSize, nSrcSize);
+   (void)pszFields;
+   xMoveBytes(pvDest, pvSrc, cb);
+   return cb;
+}
+
+
diff --git a/src/std_dtoa.c b/src/std_dtoa.c
new file mode 100644
index 0000000..943be3b
--- /dev/null
+++ b/src/std_dtoa.c
@@ -0,0 +1,504 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+ 
+#include "AEEStdDef.h"
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+#include "std_dtoa.h"
+#include "math.h"
+
+//
+//  Useful Macros
+//
+#define  FAILED(b)               ( (b) != AEE_SUCCESS ? TRUE : FALSE )
+#define  CLEANUP_ON_ERROR(b,l)   if( FAILED( b ) ) { goto l; }
+#define  FP_POW_10(n)            fp_pow_10(n)
+
+static __inline
+uint32 std_dtoa_clz32( uint32 ulVal )
+//
+// This function returns the number of leading zeroes in a uint32.
+// This is a naive implementation that uses binary search. This could be
+// replaced by an optimized inline assembly code.
+//
+{
+   if( (int)ulVal <= 0 )
+   {
+      return ( ulVal == 0 ) ? 32 : 0;
+   }
+   else
+   {
+      uint32 uRet = 28;
+      uint32 uTmp = 0;
+      uTmp = ( ulVal > 0xFFFF ) * 16; ulVal >>= uTmp, uRet -= uTmp;
+      uTmp = ( ulVal > 0xFF ) * 8; ulVal >>= uTmp, uRet -= uTmp;
+      uTmp = ( ulVal > 0xF ) * 4; ulVal >>= uTmp, uRet -= uTmp;
+      return uRet + ( ( 0x55AF >> ( ulVal * 2 ) ) & 3 );
+   }
+}
+
+static __inline
+uint32 std_dtoa_clz64( uint64 ulVal )
+//
+// This function returns the number of leading zeroes in a uint64.
+//
+{
+    uint32 ulCount = 0;
+
+    if( !( ulVal >> 32 ) )
+    {
+        ulCount += 32;
+    }
+    else
+    {
+        ulVal >>= 32;
+    }
+
+    return ulCount + std_dtoa_clz32( (uint32)ulVal );
+}
+
+double fp_pow_10( int nPow )
+{
+   double dRet = 1.0;
+   int nI = 0;
+   boolean bNegative = FALSE;
+   double aTablePos[] = { 0, 1e1, 1e2, 1e4, 1e8, 1e16, 1e32, 1e64, 1e128,
+                          1e256 };
+   double aTableNeg[] = { 0, 1e-1, 1e-2, 1e-4, 1e-8, 1e-16, 1e-32, 1e-64, 1e-128,
+                          1e-256 };
+   double* pTable = aTablePos;
+   int nTableSize = STD_ARRAY_SIZE( aTablePos );
+
+   if( 0 == nPow )
+   {
+      return 1.0;
+   }
+
+   if( nPow < 0 )
+   {
+      bNegative = TRUE;
+      nPow = -nPow;
+      pTable = aTableNeg;
+      nTableSize = STD_ARRAY_SIZE( aTableNeg );
+   }
+
+   for( nI = 1; nPow && (nI < nTableSize); nI++ )
+   {
+      if( nPow & 1 )
+      {
+         dRet *= pTable[nI];
+      }
+
+      nPow >>= 1;
+   }
+
+   if( nPow )
+   {
+      // Overflow. Trying to compute a large power value.
+      uint64 ulInf = STD_DTOA_FP_POSITIVE_INF;
+      dRet = bNegative ? 0 : UINT64_TO_DOUBLE( ulInf );
+   }
+
+   return dRet;
+}
+
+double fp_round( double dNumber, int nPrecision )
+//
+// This functions rounds dNumber to the specified precision nPrecision.
+// For example:
+//    fp_round(2.34553, 3) = 2.346
+//    fp_round(2.34553, 4) = 2.3455
+//
+{
+   double dResult = dNumber;
+   double dRoundingFactor = FP_POW_10( -nPrecision ) * 0.5;
+
+   if( dNumber < 0 )
+   {
+      dResult = dNumber - dRoundingFactor;
+   }
+   else
+   {
+      dResult = dNumber + dRoundingFactor;
+   }
+
+   return dResult;
+}
+
+int fp_log_10( double dNumber )
+//
+// This function finds the integer part of the log_10( dNumber ).
+// The function assumes that dNumber != 0.
+//
+{
+   // Absorb the negative sign
+   if( dNumber < 0 )
+   {
+      dNumber = -dNumber;
+   }
+
+   return (int)( floor( log10( dNumber ) ) );
+}
+
+int fp_check_special_cases( double dNumber, FloatingPointType* pNumberType )
+//
+// This function evaluates the input floating-point number dNumber to check for
+// following special cases: NaN, +/-Infinity.
+// The evaluation is based on the IEEE Standard 754 for Floating Point Numbers
+//
+{
+   int nError = AEE_SUCCESS;
+   FloatingPointType NumberType = FP_TYPE_UNKOWN;
+   uint64 ullValue = 0;
+   uint64 ullSign = 0;
+   int64 n64Exponent = 0;
+   uint64 ullMantissa = 0;
+
+   ullValue = DOUBLE_TO_UINT64( dNumber );
+
+   // Extract the sign, exponent and mantissa
+   ullSign = FP_SIGN( ullValue );
+   n64Exponent = FP_EXPONENT_BIASED( ullValue );
+   ullMantissa = FP_MANTISSA_DENORM( ullValue );
+
+   //
+   // Rules for special cases are listed below:
+   // For Infinity, the following needs to be true:
+   // 1. Exponent should have all bits set to 1.
+   // 2. Mantissa should have all bits set to 0.
+   //
+   // For NaN, the following needs to be true:
+   // 1. Exponent should have all bits set to 1.
+   // 2. Mantissa should be non-zero.
+   // Note that we do not differentiate between QNaNs and SNaNs.
+   //
+   if( STD_DTOA_DP_INFINITY_EXPONENT_ID == n64Exponent )
+   {
+      if( 0 == ullMantissa )
+      {
+         // Inifinity.
+         if( ullSign )
+         {
+            NumberType = FP_TYPE_NEGATIVE_INF;
+         }
+         else
+         {
+            NumberType = FP_TYPE_POSITIVE_INF;
+         }
+      }
+      else
+      {
+         // NaN
+         NumberType = FP_TYPE_NAN;
+      }
+   }
+   else
+   {
+      // A normal number
+      NumberType = FP_TYPE_GENERAL;
+   }
+
+   // Set the output value
+   *pNumberType = NumberType;
+
+   return nError;
+}
+
+int std_dtoa_decimal( double dNumber, int nPrecision,
+                      char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ],
+                      char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ] )
+{
+   int nError = AEE_SUCCESS;
+   boolean bNegativeNumber = FALSE;
+   double dIntegerPart = 0.0;
+   double dFractionPart = 0.0;
+   double dTempIp = 0.0;
+   double dTempFp = 0.0;
+   int nMaxIntDigs = STD_DTOA_FORMAT_INTEGER_SIZE;
+   uint32 ulI = 0;
+   int nIntStartPos = 0;
+
+   // Optimization: Special case an input of 0
+   if( 0.0 == dNumber )
+   {
+      acIntegerPart[0] = '0';
+      acIntegerPart[1] = '\0';
+
+      for( ulI = 0; (ulI < STD_DTOA_FORMAT_FRACTION_SIZE - 1) && (nPrecision > 0);
+           ulI++, nPrecision-- )
+      {
+         acFractionPart[ulI] = '0';
+      }
+      acFractionPart[ ulI ] = '\0';
+
+      goto bail;
+   }
+
+   // Absorb the negative sign
+   if( dNumber < 0 )
+   {
+      acIntegerPart[0] = '-';
+      nIntStartPos = 1;
+      dNumber = -dNumber;
+      bNegativeNumber = TRUE;
+   }
+
+   // Split the input number into it's integer and fraction parts
+   dFractionPart = modf( dNumber, &dIntegerPart );
+
+   // First up, convert the integer part
+   if( 0.0 == dIntegerPart )
+   {
+      acIntegerPart[ nIntStartPos ] = '0';
+   }
+   else
+   {
+      double dRoundingConst = FP_POW_10( -STD_DTOA_PRECISION_ROUNDING_VALUE );
+      int nIntDigs = 0;
+      int nI = 0;
+
+      // Compute the number of digits in the integer part of the number
+      nIntDigs = fp_log_10( dIntegerPart ) + 1;
+
+      // For negative numbers, a '-' sign has already been written.
+      if( TRUE == bNegativeNumber )
+      {
+         nIntDigs++;
+      }
+
+      // Check for overflow
+      if( nIntDigs >= nMaxIntDigs )
+      {
+         // Overflow!
+         // Note that currently, we return a simple AEE_EFAILED for all
+         // errors.
+         nError = AEE_EFAILED;
+         goto bail;
+      }
+
+      // Null Terminate the string
+      acIntegerPart[ nIntDigs ] = '\0';
+
+      for( nI = nIntDigs - 1; nI >= nIntStartPos; nI-- )
+      {
+         dIntegerPart = dIntegerPart / 10.0;
+         dTempFp = modf( dIntegerPart, &dTempIp );
+
+         // Round it to the a specific precision
+         dTempFp = dTempFp + dRoundingConst;
+
+         // Convert the digit to a character
+         acIntegerPart[ nI ] = (int)( dTempFp * 10 ) + '0';
+         if( !MY_ISDIGIT( acIntegerPart[ nI ] ) )
+         {
+            // Overflow!
+            // Note that currently, we return a simple AEE_EFAILED for all
+            // errors.
+            nError = AEE_EFAILED;
+            goto bail;
+         }
+         dIntegerPart = dTempIp;
+      }
+   }
+
+   // Just a double check for integrity sake. This should ideally never happen.
+   // Out of bounds scenario. That is, the integer part of the input number is
+   // too large.
+   if( dIntegerPart !=  0.0 )
+   {
+      // Note that currently, we return a simple AEE_EFAILED for all
+      // errors.
+      nError = AEE_EFAILED;
+      goto bail;
+   }
+
+   // Now, convert the fraction part
+   for( ulI = 0; ( nPrecision > 0 ) && ( ulI < STD_DTOA_FORMAT_FRACTION_SIZE - 1 );
+        nPrecision--, ulI++ )
+   {
+      if( 0.0 == dFractionPart )
+      {
+         acFractionPart[ ulI ] = '0';
+      }
+      else
+      {
+         double dRoundingValue = FP_POW_10( -( nPrecision +
+                                               STD_DTOA_PRECISION_ROUNDING_VALUE ) );
+         acFractionPart[ ulI ] = (int)( ( dFractionPart + dRoundingValue ) * 10.0 ) + '0';
+         if( !MY_ISDIGIT( acFractionPart[ ulI ] ) )
+         {
+            // Overflow!
+            // Note that currently, we return a simple AEE_EFAILED for all
+            // errors.
+            nError = AEE_EFAILED;
+            goto bail;
+         }
+
+         dFractionPart = ( dFractionPart * 10.0 ) -
+                         (int)( ( dFractionPart + FP_POW_10( -nPrecision - 6 ) ) * 10.0 );
+      }
+   }
+
+
+bail:
+
+   return nError;
+}
+
+int std_dtoa_hex( double dNumber, int nPrecision, char cFormat,
+                  char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ],
+                  char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ],
+                  int* pnExponent )
+{
+   int nError = AEE_SUCCESS;
+   uint64 ullMantissa = 0;
+   uint64 ullSign = 0;
+   int64 n64Exponent = 0;
+   static const char HexDigitsU[] = "0123456789ABCDEF";
+   static const char HexDigitsL[] = "0123456789abcde";
+   boolean bFirstDigit = TRUE;
+   int nI = 0;
+   int nF = 0;
+   uint64 ullValue = DOUBLE_TO_UINT64( dNumber );
+   int nManShift = 0;
+   const char *pcDigitArray = ( cFormat == 'A' ) ? HexDigitsU : HexDigitsL;
+   boolean bPrecisionSpecified = TRUE;
+
+   // If no precision is specified, then set the precision to be fairly
+   // large.
+   if( nPrecision < 0 )
+   {
+      nPrecision = STD_DTOA_FORMAT_FRACTION_SIZE;
+      bPrecisionSpecified = FALSE;
+   }
+   else
+   {
+      bPrecisionSpecified = TRUE;
+   }
+
+   // Extract the sign, exponent and mantissa
+   ullSign = FP_SIGN( ullValue );
+   n64Exponent = FP_EXPONENT( ullValue );
+   ullMantissa = FP_MANTISSA( ullValue );
+
+   // Write out the sign
+   if( ullSign )
+   {
+      acIntegerPart[ nI++ ] = '-';
+   }
+
+   // Optimization: Special case an input of 0
+   if( 0.0 == dNumber )
+   {
+      acIntegerPart[0] = '0';
+      acIntegerPart[1] = '\0';
+
+      for( nF = 0; (nF < STD_DTOA_FORMAT_FRACTION_SIZE - 1) && (nPrecision > 0);
+           nF++, nPrecision-- )
+      {
+         acFractionPart[nF] = '0';
+      }
+      acFractionPart[nF] = '\0';
+
+      goto bail;
+   }
+
+   // The mantissa is in lower 53 bits (52 bits + an implicit 1).
+   // If we are dealing with a denormalized number, then the implicit 1
+   // is absent. The above macros would have then set that bit to 0.
+   // Shift the mantisaa on to the highest bits.
+
+   if( 0 == ( n64Exponent + STD_DTOA_DP_EXPONENT_BIAS ) )
+   {
+      // DENORMALIZED NUMBER.
+      // A denormalized number is of the form:
+      //       0.bbb...bbb x 2^Exponent
+      // Shift the mantissa to the higher bits while discarding the leading 0
+      ullMantissa <<= 12;
+
+      // Lets update the exponent so as to make sure that the first hex value
+      // in the mantissa is non-zero, i.e., at least one of the first 4 bits is
+      // non-zero.
+      nManShift = std_dtoa_clz64( ullMantissa ) - 3;
+      if( nManShift > 0 )
+      {
+         ullMantissa <<= nManShift;
+         n64Exponent -= nManShift;
+      }
+   }
+   else
+   {
+      // NORMALIZED NUMBER.
+      // A normalized number has the following form:
+      //       1.bbb...bbb x 2^Exponent
+      // Shift the mantissa to the higher bits while retaining the leading 1
+      ullMantissa <<= 11;
+   }
+
+   // Now, lets get the decimal point out of the picture by shifting the
+   // exponent by 1.
+   n64Exponent++;
+
+   // Read the mantissa four bits at a time to form the hex output
+   for( nI = 0, nF = 0, bFirstDigit = TRUE; ullMantissa != 0;
+        ullMantissa <<= 4 )
+   {
+      uint64 ulHexVal = ullMantissa & 0xF000000000000000uLL;
+      ulHexVal >>= 60;
+      if( bFirstDigit )
+      {
+         // Write to the integral part of the number
+         acIntegerPart[ nI++ ] = pcDigitArray[ulHexVal];
+         bFirstDigit = FALSE;
+      }
+      else if( nF < nPrecision )
+      {
+         // Write to the fractional part of the number
+         acFractionPart[ nF++ ] = pcDigitArray[ulHexVal];
+      }
+   }
+
+   // Pad the fraction with trailing zeroes upto the specified precision
+   for( ; bPrecisionSpecified && (nF < nPrecision); nF++ )
+   {
+      acFractionPart[ nF ] = '0';
+   }
+
+   // Now the output is of the form;
+   //       h.hhh x 2^Exponent
+   // where h is a non-zero hexadecimal number.
+   // But we were dealing with a binary fraction 0.bbb...bbb x 2^Exponent.
+   // Therefore, we need to subtract 4 from the exponent (since the shift
+   // was to the base 16 and the exponent is to the base 2).
+   n64Exponent -= 4;
+   *pnExponent = (int)n64Exponent;
+
+bail:
+   return nError;
+}
diff --git a/src/std_dtoa.h b/src/std_dtoa.h
new file mode 100644
index 0000000..cea00c4
--- /dev/null
+++ b/src/std_dtoa.h
@@ -0,0 +1,137 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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 STD_DTOA_H
+#define STD_DTOA_H
+
+//
+// Constant Definitions
+//
+
+// For floating point numbers, the range of a double precision number is
+// approximately +/- 10 ^ 308.25 as per the IEEE Standard 754.
+// As such, the maximum size of the integer portion of the
+// string is assumed to be 311 (309 + sign + \0). The maximum
+// size of the fractional part is assumed to be 100. Thus, the
+// maximum size of the string that would contain the number
+// after conversion is safely assumed to be 420 (including any
+// prefix, the null character and exponent specifiers 'e').
+//
+// The buffers that contain the converted integer and the fraction parts of
+// the float are safely assumed to be of size 310.
+#define STD_DTOA_FORMAT_FLOAT_SIZE           420
+#define STD_DTOA_FORMAT_INTEGER_SIZE         311
+#define STD_DTOA_FORMAT_FRACTION_SIZE        100
+
+// Constants for operations on the IEEE 754 representation of double
+// precision floating point numbers.
+#define STD_DTOA_DP_SIGN_SHIFT_COUNT         63
+#define STD_DTOA_DP_EXPONENT_SHIFT_COUNT     52
+#define STD_DTOA_DP_EXPONENT_MASK            0x7ff
+#define STD_DTOA_DP_EXPONENT_BIAS            1023
+#define STD_DTOA_DP_MANTISSA_MASK            ( ( (uint64)1 << 52 ) - 1 )
+#define STD_DTOA_DP_INFINITY_EXPONENT_ID     0x7FF
+#define STD_DTOA_DP_MAX_EXPONENT             1023
+#define STD_DTOA_DP_MIN_EXPONENT_NORM        -1022
+#define STD_DTOA_DP_MIN_EXPONENT_DENORM      -1074
+#define STD_DTOA_DP_MAX_EXPONENT_DEC         308
+#define STD_DTOA_DP_MIN_EXPONENT_DEC_DENORM  -323
+
+#define STD_DTOA_PRECISION_ROUNDING_VALUE    4
+#define STD_DTOA_DEFAULT_FLOAT_PRECISION     6
+
+#define STD_DTOA_NEGATIVE_INF_UPPER_CASE     "-INF"
+#define STD_DTOA_NEGATIVE_INF_LOWER_CASE     "-inf"
+#define STD_DTOA_POSITIVE_INF_UPPER_CASE     "INF"
+#define STD_DTOA_POSITIVE_INF_LOWER_CASE     "inf"
+#define STD_DTOA_NAN_UPPER_CASE              "NAN"
+#define STD_DTOA_NAN_LOWER_CASE              "nan"
+#define STD_DTOA_FP_POSITIVE_INF             0x7FF0000000000000uLL
+#define STD_DTOA_FP_NEGATIVE_INF             0xFFF0000000000000uLL
+#define STD_DTOA_FP_SNAN                     0xFFF0000000000001uLL
+#define STD_DTOA_FP_QNAN                     0xFFFFFFFFFFFFFFFFuLL
+
+//
+// Useful Macros
+//
+
+#define MY_ISDIGIT(c)            ( ( (c) >= '0' ) && ( (c) <= '9' ) )
+#define FP_EXPONENT(u)           ( ( ( (u) >> STD_DTOA_DP_EXPONENT_SHIFT_COUNT ) \
+                                    & STD_DTOA_DP_EXPONENT_MASK ) - STD_DTOA_DP_EXPONENT_BIAS )
+#define FP_EXPONENT_BIASED(u)    ( ( (u) >> STD_DTOA_DP_EXPONENT_SHIFT_COUNT ) \
+                                    & STD_DTOA_DP_EXPONENT_MASK )
+#define FP_MANTISSA_NORM(u)      ( ( (u) & STD_DTOA_DP_MANTISSA_MASK ) | \
+                                    ( (uint64)1 << STD_DTOA_DP_EXPONENT_SHIFT_COUNT ) )
+#define FP_MANTISSA_DENORM(u)    ( (u) & STD_DTOA_DP_MANTISSA_MASK )
+#define FP_MANTISSA(u)           ( FP_EXPONENT_BIASED(u) ? FP_MANTISSA_NORM(u) : \
+                                    FP_MANTISSA_DENORM(u) )
+#define FP_SIGN(u)               ( (u) >> STD_DTOA_DP_SIGN_SHIFT_COUNT )
+#define DOUBLE_TO_UINT64(d)      ( *( (uint64*) &(d) ) )
+#define DOUBLE_TO_INT64(d)       ( *( (int64*) &(d) ) )
+#define UINT64_TO_DOUBLE(u)      ( *( (double*) &(u) ) )
+
+//
+// Type Definitions
+//
+
+typedef enum
+{
+   FP_TYPE_UNKOWN = 0,
+   FP_TYPE_NEGATIVE_INF,
+   FP_TYPE_POSITIVE_INF,
+   FP_TYPE_NAN,
+   FP_TYPE_GENERAL,
+} FloatingPointType;
+
+//
+// Function Declarations
+//
+
+#ifdef __cplusplus
+extern "C" {
+#endif // #ifdef __cplusplus
+
+double fp_pow_10( int nPow );
+double fp_round( double dNumber, int nPrecision );
+int fp_log_10( double dNumber );
+int fp_check_special_cases( double dNumber, FloatingPointType* pNumberType );
+int std_dtoa_decimal( double dNumber, int nPrecision,
+                      char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ],
+                      char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ] );
+int std_dtoa_hex( double dNumber, int nPrecision, char cFormat,
+                  char acIntegerPart[ STD_DTOA_FORMAT_INTEGER_SIZE ],
+                  char acFractionPart[ STD_DTOA_FORMAT_FRACTION_SIZE ],
+                  int* pnExponent );
+
+#ifdef __cplusplus
+}
+#endif // #ifdef __cplusplus
+
+#endif   // STD_DTOA_H
+
diff --git a/src/std_mem.c b/src/std_mem.c
new file mode 100644
index 0000000..abe45ed
--- /dev/null
+++ b/src/std_mem.c
@@ -0,0 +1,107 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+/*
+=======================================================================
+
+FILE:         std_mem.c
+
+SERVICES:     apiOne std lib memory operations stuff
+
+*/
+
+#include <string.h>
+#include "AEEstd.h"
+#include "AEEStdErr.h"
+
+#if defined __hexagon__
+#include "stringl/stringl.h"
+
+//Add a weak reference so shared objects work with older images
+#pragma weak memscpy
+#pragma weak memsmove
+#endif /*__hexagon__*/
+
+void* std_memset(void* p, int c, int nLen)
+{
+   if (nLen < 0) {
+      return p;
+   }
+   return memset(p, c, (size_t)nLen);
+}
+
+void* std_memmove(void* pTo, const void* cpFrom, int nLen)
+{
+   if (nLen <= 0) {
+      return pTo;
+   }
+#ifdef __hexagon__
+   std_memsmove(pTo, (size_t)nLen, cpFrom, (size_t)nLen);
+   return pTo;
+#else
+   return memmove(pTo, cpFrom, (size_t)nLen);
+#endif
+}
+
+int std_memscpy(void *dst, int dst_size, const void *src, int src_size){
+    size_t copy_size = 0;
+
+    if(dst_size <0 || src_size <0){
+        return AEE_EBADSIZE;
+    }
+
+#if defined (__hexagon__)
+    if (memscpy){
+        return memscpy(dst,dst_size,src,src_size);
+    }
+#endif
+
+    copy_size = (dst_size <= src_size)? dst_size : src_size;
+    memcpy(dst, src, copy_size);
+    return copy_size;
+}
+
+int std_memsmove(void *dst, int dst_size, const void *src, int src_size){
+    size_t copy_size = 0;
+
+    if(dst_size <0 || src_size <0){
+        return AEE_EBADSIZE;
+    }
+
+#if defined (__hexagon__)
+    if (memsmove){
+        return memsmove(dst,dst_size,src,src_size);
+    }
+#endif
+
+    copy_size = (dst_size <= src_size)? dst_size : src_size;
+    memmove(dst, src, copy_size);
+    return copy_size;
+}
+
diff --git a/src/std_path.c b/src/std_path.c
new file mode 100644
index 0000000..b8e1d3f
--- /dev/null
+++ b/src/std_path.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+/*
+=======================================================================
+
+FILE:         std_path.c
+
+=======================================================================
+=======================================================================
+*/
+
+#include "AEEstd.h"
+#include "AEEBufBound.h"
+#include <string.h>
+/*===========================================================================
+
+===========================================================================*/
+int std_makepath(const char* cpszDir, const char* cpszFile,
+                 char* pszOut, int nOutLen)
+{
+   BufBound bb;
+
+   BufBound_Init(&bb, pszOut, nOutLen);
+
+   BufBound_Puts(&bb, cpszDir);
+
+   if (('\0' != cpszDir[0]) &&    /* non-empty dir */
+       ('/' != cpszDir[std_strlen(cpszDir)-1])) { /* no slash at end of dir */
+      BufBound_Putc(&bb, '/');
+   }
+   if ('/' == cpszFile[0]) {
+      cpszFile++;
+   }
+
+   BufBound_Puts(&bb, cpszFile);
+
+   BufBound_ForceNullTerm(&bb);
+
+   return BufBound_Wrote(&bb) - 1;
+
+}
+
+/*===========================================================================
+
+===========================================================================*/
+char* std_splitpath(const char* cpszPath, const char* cpszDir)
+{
+   const char* cpsz = cpszPath;
+
+   while ( ! ('\0' == cpszDir[0] ||
+              ('/' == cpszDir[0] && '\0' == cpszDir[1])) ){
+
+      if (*cpszDir != *cpsz) {
+         return 0;
+      }
+
+      ++cpsz;
+      ++cpszDir;
+   }
+
+   /* Found the filename part of the path.
+      It should begin with a '/' unless there is no filename */
+   if ('/' == *cpsz) {
+      cpsz++;
+   }
+   else if ('\0' != *cpsz) {
+      cpsz = 0;
+   }
+
+   return (char*)cpsz;
+}
+
+char* std_cleanpath(char* pszPath)
+{
+   char* pszStart = pszPath;
+   char* pc;
+   char* pcEnd = pszStart+std_strlen(pszStart);
+
+   /* preserve leading slash */
+   if ('/' == pszStart[0]) {
+      pszStart++;
+   }
+
+   pc = pszStart;
+
+   while ((char*)0 != (pc = std_strstr(pc, "/."))) {
+      char* pcDelFrom;
+
+      if ('/' == pc[2] || '\0' == pc[2]) {
+         /*  delete "/." */
+         pcDelFrom = pc;
+         pc += 2;
+      } else if ('.' == pc[2] && ('/' == pc[3] || '\0' == pc[3])) {
+            /*  delete  "/element/.." */
+         pcDelFrom = std_memrchrbegin(pszStart, '/', pc - pszStart);
+         pc += 3;
+      } else {
+         pc += 2;
+         continue;
+      }
+
+      std_memmove(pcDelFrom, pc, pcEnd-pcDelFrom);
+
+      pc = pcDelFrom;
+   }
+
+   /* eliminate leading "../" */
+   while (pszStart == std_strstr(pszStart, "../")) {
+      std_memmove(pszStart, pszStart+2, pcEnd-pszStart);
+   }
+
+   /* eliminate leading "./" */
+   while (pszStart == std_strstr(pszStart, "./")) {
+      std_memmove(pszStart, pszStart+1, pcEnd-pszStart);
+   }
+
+   if (!strncmp(pszStart,"..",2) || !strncmp(pszStart,".",1)) {
+      pszStart[0] = '\0';
+   }
+
+   /* whack double '/' */
+   while ((char*)0 != (pc = std_strstr(pszPath, "//"))) {
+      std_memmove(pc, pc+1, pcEnd-pc);
+   }
+
+   return pszPath;
+}
+
+char* std_basename(const char* cpszFile)
+{
+   const char* cpsz;
+
+   if ((char*)0 != (cpsz = std_strrchr(cpszFile,'/'))) {
+      cpszFile = cpsz+1;
+   }
+
+   return (char*)cpszFile;
+}
diff --git a/src/std_strlprintf.c b/src/std_strlprintf.c
new file mode 100644
index 0000000..c927dc8
--- /dev/null
+++ b/src/std_strlprintf.c
@@ -0,0 +1,759 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+
+#include "AEEstd.h"
+#include "AEEBufBound.h"
+#include "AEEsmath.h"
+#include "AEEStdErr.h"
+#include "std_dtoa.h"
+//#include "math.h"
+
+//==============================================================================
+//   Macro definitions
+//==============================================================================
+
+#define  ISDIGIT(c)              ( (c) >= '0' && (c) <= '9')
+#define  TOLOWER(c)              ( (c) | 32 )   // works only for letters
+#define  FAILED(b)               ( (b) != AEE_SUCCESS ? TRUE : FALSE )
+#define  CLEANUP_ON_ERROR(b,l)   if( FAILED( b ) ) { goto l; }
+#define  ROUND(d, p)             fp_round( d, p )
+#define  FP_POW_10(n)            fp_pow_10(n)
+
+//==============================================================================
+//   Type definitions
+//==============================================================================
+
+
+// Formatting flags
+
+#define FF_PLUS     1    // '+'
+#define FF_MINUS    2    // '-'
+#define FF_POUND    4    // '#'
+#define FF_BLANK    8    // ' '
+#define FF_ZERO    16    // '0'
+
+typedef struct {
+
+   // Parsed values (from "%..." expression)
+
+   int      flags;          // FF_PLUS, FF_MINUS, etc.
+   char     cType;          // d, s, c, x, X, etc.
+   int32    nWidth;         // number preceding '.' : controls padding
+   int32    nPrecision;     // number following '.'  (-1 if not given)
+
+   // Computed values
+
+   const char *  pszStr;         // string holding prefix + value
+   int           nPrefix;        // # of numeric prefix bytes in pszStr[]
+   int           nLen;           // length of string (after prefix)
+   int           nNumWidth;      // minimum numeric value size (pad with '0')
+
+} FieldFormat;
+
+typedef int (*pfnFormatFloat)(FieldFormat* me, double dNumber, char* pcBuffer);
+
+//==============================================================================
+//   Function definitions
+//==============================================================================
+
+// Read an unsigned decimal integer
+//
+static int ScanDecimal(const char **ppsz)
+{
+   int n = 0;
+   const char *psz;
+
+   for (psz = *ppsz; ISDIGIT(*psz); ++psz) {
+      n = n*10 + (int) (*psz - '0');
+   }
+   *ppsz = psz;
+   return n;
+}
+
+
+#define FORMATNUMBER_SIZE   24   // octal: 22 + '0' + null ;  decimal: 20 + sign + null
+
+
+// Convert number to string, setting computed fields in FieldFormat.
+//
+//  pcBuf[] must have room for at least FORMATNUMBER_SIZE characters
+//  return value: length of string.
+//
+static __inline void
+FormatNumber(FieldFormat *me, char pcBuf[FORMATNUMBER_SIZE], uint64 uNum64)
+{
+   char cType = me->cType;
+   const char *cpszDigits;
+   char *pc = pcBuf;
+   int nBase;
+   char *pcRev;
+
+   if (cType == 'p') {
+      cType = 'X';
+      me->nPrecision = 8;
+   }
+
+   if (me->nPrecision >= 0) {
+      me->nNumWidth = me->nPrecision;
+      // Odd thing: '0' flag is ignored for numbers when precision is
+      // specified.
+      me->flags &= ~FF_ZERO;
+   } else {
+      me->nNumWidth = 1;
+   }
+
+   // Output prefix
+
+   if (( 'd' == cType || 'i' == cType)) {
+      if ((int64)uNum64 < 0) {
+         *pc++ = '-';
+         uNum64 = (uint64)-(int64)uNum64;
+      } else if (me->flags & FF_PLUS) {
+         *pc++ = '+';
+      } else if (me->flags & FF_BLANK) {
+         *pc++ = ' ';
+      }
+   }
+
+   if ((me->flags & FF_POUND) && 0 != uNum64) {
+      if ('x' == TOLOWER(cType)) {
+         *pc++ = '0';
+         *pc++ = cType;
+      } else if ('o' == cType) {
+         *pc++ = '0';
+         // Odd thing about libc printf: "0" prefix counts as part of minimum
+         // width, but "0x" prefix does not.
+         --me->nNumWidth;
+      }
+   }
+   me->nPrefix = pc - pcBuf;
+
+   // Output unsigned numeric value
+
+   nBase = ('o' == cType          ? 8 :
+            'x' == TOLOWER(cType) ? 16 :
+            10);
+   cpszDigits = ((cType == 'X') ? "0123456789ABCDEF"
+                                : "0123456789abcdef");
+
+   pcRev = pc;
+
+   while (uNum64) {
+      *pc++ = cpszDigits[uNum64 % (unsigned)nBase];
+      uNum64 /= (unsigned)nBase;
+   }
+
+   *pc = '\0';
+
+   me->pszStr = pcBuf;
+   me->nLen = pc - pcRev;
+
+   // Reverse string
+
+   --pc;
+   for (; pcRev < pc; ++pcRev, --pc) {
+      char c = *pc;
+      *pc = *pcRev;
+      *pcRev = c;
+   }
+}
+
+//
+// This function converts the input floating point number dNumber to an
+// ASCII string using either %f or %F formatting. This functions assumes
+// that dNumer is a valid floating point number (i.e., dNumber is NOT
+// +/-INF or NaN). The size of the output buffer pcBuffer should be at
+// least STD_DTOA_FORMAT_FLOAT_SIZE.
+//
+static int ConvertFloat(FieldFormat* me, double dNumber, char* pcBuffer,
+                        int nBufSize)
+{
+   int nError = AEE_SUCCESS;
+   int32 nPrecision = 0;
+   int nIndex = 0;
+   BufBound OutBuf;
+   char szIntegerPart[STD_DTOA_FORMAT_INTEGER_SIZE] = {0};
+   char szFractionPart[STD_DTOA_FORMAT_FRACTION_SIZE] = {0};
+   int nExponent = 0;
+   char cType = TOLOWER(me->cType);
+
+   // Set the precision for conversion
+   nPrecision = me->nPrecision;
+   if (nPrecision < 0) {
+      // No precision was specified, set it to the default value if the
+      // format specifier is not %a
+      if (cType != 'a') {
+         nPrecision = STD_DTOA_DEFAULT_FLOAT_PRECISION;
+      }
+   }
+   else if ((0 == nPrecision) && ('g' == cType)) {
+      nPrecision = 1;
+   }
+
+   if (cType != 'a') {
+      // For %g, check whether to use %e of %f formatting style.
+      // Also, set the precision value accordingly since in this case the user
+      // specified value is really the number of significant digits.
+      // These next few steps should be skipped if the input number is 0.
+      if (dNumber != 0.0) {
+         nExponent = fp_log_10(dNumber);
+         if ('g' == cType) {
+            if ((nExponent < -4) || (nExponent >= nPrecision)) {
+               cType = 'e';
+               nPrecision = nPrecision - 1;
+            }
+            else {
+               cType = 'f';
+               nPrecision = nPrecision - nExponent - 1;
+            }
+         }
+
+         // For %e, convert the number to the form d.ddd
+         if ('e' == cType) {
+            dNumber = dNumber / FP_POW_10(nExponent);
+         }
+
+         // Now, round the number to the specified precision
+         dNumber = ROUND(dNumber, nPrecision);
+
+         // For %e, the rounding operation may have resulted in a number dd.ddd
+         // Reconvert it to the form d.ddd
+         if (('e' == cType) && ((dNumber >= 10.0) || (dNumber <= -10.0))) {
+            dNumber = dNumber / 10.0;
+            nExponent++;
+         }
+      }
+
+      // Convert the decmial number to string
+      nError = std_dtoa_decimal(dNumber, nPrecision, szIntegerPart, szFractionPart);
+      CLEANUP_ON_ERROR(nError, bail);
+   }
+   else
+   {
+      // Conver the hex floating point number to string
+      nError = std_dtoa_hex(dNumber, nPrecision, me->cType, szIntegerPart,
+                            szFractionPart, &nExponent);
+      CLEANUP_ON_ERROR(nError, bail);
+   }
+
+
+   //
+   // Write the output as per the specified format.
+   // First: Check for any prefixes that need to be added to the output.
+   // The only possible prefixes are '-', '+' or ' '. The following rules
+   // are applicable:
+   // 1. One and only one prefix will be applicable at any time.
+   // 2. If the number is negative, then '+' and ' ' are not applicable.
+   // 3. For positive numbers, the prefix '+' takes precedence over ' '.
+   //
+   // In addition, we were dealing with a hex floating point number (%a),
+   // then we need to write of the 0x prefix.
+   //
+   BufBound_Init(&OutBuf, pcBuffer, nBufSize);
+   if (dNumber < 0.0) {
+      // The '-' sign would have already been added to the szIntegerPart by
+      // the conversion function.
+      me->nPrefix = 1;
+   }
+   if (dNumber >= 0.0){
+      if (me->flags & FF_PLUS) {
+         BufBound_Putc(&OutBuf, '+');
+         me->nPrefix = 1;
+      }
+      else if(me->flags & FF_BLANK) {
+         BufBound_Putc(&OutBuf, ' ');
+         me->nPrefix = 1;
+      }
+   }
+
+   // For %a, write out the 0x prefix
+   if ('a' == cType) {
+      BufBound_Putc(&OutBuf, '0');
+      BufBound_Putc(&OutBuf, ('a' == me->cType) ? 'x' : 'X');
+      me->nPrefix += 2;
+   }
+
+   // Second: Write the integer part
+   BufBound_Puts(&OutBuf, szIntegerPart);
+
+   // Third: Write the decimal point followed by the fraction part.
+   // For %g, we need to truncate the trailing zeros in the fraction.
+   // Skip this if the '#' flag is specified
+   if (!(me->flags & FF_POUND) && ('g' == TOLOWER(me->cType))) {
+      for (nIndex = std_strlen(szFractionPart) - 1;
+           (nIndex >= 0) && (szFractionPart[nIndex] == '0'); nIndex--) {
+         szFractionPart[nIndex] = '\0';
+      }
+   }
+
+   // The decimal point is specified only if there are some decimal digits.
+   // However, if the '#' format specifier is present then the decimal point
+   // will be present.
+   if ((me->flags & FF_POUND) || (*szFractionPart != 0)) {
+      BufBound_Putc(&OutBuf, '.');
+
+      // Write the fraction part
+      BufBound_Puts(&OutBuf, szFractionPart);
+   }
+
+   // For %e and %a, write out the exponent
+   if (('e' == cType) || ('a' == cType)) {
+      char* pcExpStart = NULL;
+      char* pcExpEnd = NULL;
+      char cTemp = 0;
+
+      if ('a' == me->cType) {
+         BufBound_Putc(&OutBuf, 'p');
+      }
+      else if ('A' == me->cType) {
+         BufBound_Putc(&OutBuf, 'P');
+      }
+      else if (('e' == me->cType) || ('g' == me->cType)) {
+         BufBound_Putc(&OutBuf, 'e');
+      }
+      else {
+         BufBound_Putc(&OutBuf, 'E');
+      }
+
+      // Write the exponent sign
+      if (nExponent < 0) {
+         BufBound_Putc(&OutBuf, '-');
+         nExponent = -nExponent;
+      }
+      else {
+         BufBound_Putc(&OutBuf, '+');
+      }
+
+      // Write out the exponent.
+      // For %e, the exponent should at least be two digits.
+      // The exponent to be written will be at most 4 digits as any
+      // overflow would have been take care of by now.
+      if (BufBound_Left(&OutBuf) >= 4) {
+         if ('e' == cType) {
+            if (nExponent < 10) {
+               BufBound_Putc(&OutBuf, '0');
+            }
+         }
+
+         pcExpStart = OutBuf.pcWrite;
+         do {
+            BufBound_Putc(&OutBuf, '0' + (nExponent % 10));
+            nExponent /= 10;
+         } while (nExponent);
+         pcExpEnd = OutBuf.pcWrite - 1;
+
+         // Reverse the exponent
+         for (; pcExpStart < pcExpEnd; pcExpStart++, pcExpEnd--) {
+            cTemp = *pcExpStart;
+            *pcExpStart = *pcExpEnd;
+            *pcExpEnd = cTemp;
+         }
+      }
+   }
+
+   // Null-terminate the string
+   BufBound_ForceNullTerm(&OutBuf);
+
+   // Set the output parameters
+   // We do not care if there was enough space in the output buffer or not.
+   // The output would be truncated to a maximum length of
+   // STD_DTOA_FORMAT_FLOAT_SIZE.
+   me->pszStr = OutBuf.pcBuf;
+   me->nLen = BufBound_ReallyWrote(&OutBuf) - me->nPrefix - 1;
+
+bail:
+
+   return nError;
+}
+
+//
+// This is a wrapper function that converts an input floating point number
+// to a string based on a given format specifier %e, %f or %g. It first checks
+// if the specified number is a valid floating point number before calling
+// the function that does the conversion.
+//
+// The size of the output buffer pcBuffer should be at least STD_DTOA_FORMAT_FLOAT_SIZE.
+//
+static int FormatFloat(FieldFormat* me, double dNumber,
+                       char pcBuffer[STD_DTOA_FORMAT_FLOAT_SIZE])
+{
+   int nError = AEE_SUCCESS;
+   FloatingPointType NumberType = FP_TYPE_UNKOWN;
+
+   // Check for error conditions
+   if (NULL == pcBuffer) {
+      nError = AEE_EBADPARM;
+      goto bail;
+   }
+
+   // Initialize the output params first
+   me->nLen = 0;
+   me->nPrefix = 0;
+
+   // Check for special cases such as NaN and Infinity
+   nError = fp_check_special_cases(dNumber, &NumberType);
+   CLEANUP_ON_ERROR(nError, bail);
+
+   switch(NumberType) {
+	  case FP_TYPE_NEGATIVE_INF:
+
+		 if (('E' == me->cType) || ('F' == me->cType) || ('G' == me->cType)) {
+			me->nLen = std_strlcpy(pcBuffer, STD_DTOA_NEGATIVE_INF_UPPER_CASE,
+								   STD_DTOA_FORMAT_FLOAT_SIZE);
+		 }
+		 else {
+			me->nLen = std_strlcpy(pcBuffer, STD_DTOA_NEGATIVE_INF_LOWER_CASE,
+								   STD_DTOA_FORMAT_FLOAT_SIZE);
+		 }
+
+		 // Don't pad with 0's
+		 me->flags &= ~FF_ZERO;
+
+		 break;
+
+	  case FP_TYPE_POSITIVE_INF:
+
+		 if (('E' == me->cType) || ('F' == me->cType) || ('G' == me->cType)) {
+			me->nLen = std_strlcpy(pcBuffer, STD_DTOA_POSITIVE_INF_UPPER_CASE,
+								   STD_DTOA_FORMAT_FLOAT_SIZE);
+		 }
+		 else {
+			me->nLen = std_strlcpy(pcBuffer, STD_DTOA_POSITIVE_INF_LOWER_CASE,
+								   STD_DTOA_FORMAT_FLOAT_SIZE);
+		 }
+
+		 // Don't pad with 0's
+		 me->flags &= ~FF_ZERO;
+
+		 break;
+
+	  case FP_TYPE_NAN:
+
+		 if (('E' == me->cType) || ('F' == me->cType) || ('G' == me->cType)) {
+			me->nLen = std_strlcpy(pcBuffer, STD_DTOA_NAN_UPPER_CASE,
+								   STD_DTOA_FORMAT_FLOAT_SIZE);
+		 }
+		 else
+		 {
+			me->nLen = std_strlcpy(pcBuffer, STD_DTOA_NAN_LOWER_CASE,
+								   STD_DTOA_FORMAT_FLOAT_SIZE);
+		 }
+
+		 // Don't pad with 0's
+		 me->flags &= ~FF_ZERO;
+
+		 break;
+
+	  case FP_TYPE_GENERAL:
+
+		 nError = ConvertFloat(me, dNumber, pcBuffer,
+                               STD_DTOA_FORMAT_FLOAT_SIZE);
+		 CLEANUP_ON_ERROR(nError, bail);
+
+		 break;
+
+	  default:
+
+		 // This should only happen if this function has been modified
+		 // to support other special cases and this block has not been
+		 // updated.
+		 nError = AEE_EFAILED;
+		 goto bail;
+   }
+
+   // Set the output parameters
+   me->pszStr = pcBuffer;
+
+
+bail:
+
+   return nError;
+}
+
+static int std_strlprintf_inner(char *pszDest, int nDestSize,
+                                const char *cpszFmt, AEEVaList args,
+                                pfnFormatFloat pfnFormatFloatFunc)
+{
+   BufBound bb;
+   const char *pcIn = cpszFmt;
+
+   BufBound_Init(&bb, pszDest, nDestSize);
+
+   for (;;) {
+      FieldFormat ff;
+      const char *pcEsc;
+      char achBuf[FORMATNUMBER_SIZE];
+      char achBuf2[STD_DTOA_FORMAT_FLOAT_SIZE];
+      char cType;
+      boolean bLong = 0;
+
+      pcEsc = std_strchrend(pcIn, '%');
+      BufBound_Write(&bb, pcIn, pcEsc-pcIn);
+
+      if (0 == *pcEsc) {
+         break;
+      }
+      pcIn = pcEsc+1;
+
+      //----------------------------------------------------
+      // Consume "%..." specifiers:
+      //
+      //   %[FLAGS] [WIDTH] [.PRECISION] [{h | l | I64 | L}]
+      //----------------------------------------------------
+
+      std_memset(&ff, 0, sizeof(FieldFormat));
+      ff.nPrecision = -1;
+
+      // Consume all flags
+      for (;;) {
+         int f;
+
+         f = (('+' == *pcIn) ? FF_PLUS  :
+              ('-' == *pcIn) ? FF_MINUS :
+              ('#' == *pcIn) ? FF_POUND :
+              (' ' == *pcIn) ? FF_BLANK :
+              ('0' == *pcIn) ? FF_ZERO  : 0);
+
+         if (0 == f) {
+            break;
+         }
+
+         ff.flags |= f;
+         ++pcIn;
+      }
+
+      // Consume width
+      if ('*' == *pcIn) {
+         AEEVA_ARG(args, ff.nWidth, int32);
+         pcIn++;
+      } else {
+         ff.nWidth = ScanDecimal(&pcIn);
+      }
+      if ((ff.flags & FF_MINUS) && ff.nWidth > 0) {
+         ff.nWidth = -ff.nWidth;
+      }
+
+      // Consume precision
+      if ('.' == *pcIn) {
+         pcIn++;
+         if ('*' == *pcIn) { // Can be *... (given in int * param)
+            AEEVA_ARG(args, ff.nPrecision, int32);
+            pcIn++;
+         } else {
+            ff.nPrecision = ScanDecimal(&pcIn);
+         }
+      }
+
+      // Consume size designator
+      {
+         static const struct {
+            char    szPre[3];
+            boolean b64;
+         } a[] = {
+            { "l",  0, },
+            { "ll", 1, },
+            { "L",  1, },
+            { "j",  1, },
+            { "h",  0, },
+            { "hh", 0, },
+            { "z",  0 }
+         };
+
+         int n = STD_ARRAY_SIZE(a);
+
+         while (--n >= 0) {
+            const char *psz = std_strbegins(pcIn, a[n].szPre);
+            if ((const char*)0 != psz) {
+               pcIn = psz;
+               bLong = a[n].b64;
+               break;
+            }
+         }
+      }
+
+      //----------------------------------------------------
+      //
+      // Format output values
+      //
+      //----------------------------------------------------
+
+      ff.cType = cType = *pcIn++;
+
+      if ('s' == cType) {
+
+         // String
+         char *psz;
+
+         AEEVA_ARG(args, psz, char*);
+         ff.pszStr = psz;
+         ff.nLen = std_strlen(psz);
+         if (ff.nPrecision >= 0 && ff.nPrecision < ff.nLen) {
+            ff.nLen = ff.nPrecision;
+         }
+
+      } else if ('c' == cType) {
+
+         // char
+         AEEVA_ARG(args, achBuf[0], int);
+         achBuf[1] = '\0';
+         ff.pszStr = achBuf;
+         ff.nLen = 1;
+
+      } else if ('u' == cType ||
+                 'o' == cType ||
+                 'd' == cType ||
+                 'i' == cType ||
+                 'p' == cType ||
+                 'x' == TOLOWER(cType) ) {
+
+         // int
+         uint64 uArg64;
+
+         if (bLong) {
+            AEEVA_ARG(args, uArg64, int64);  // See how much room needed
+         } else {
+            uint32 uArg32;
+            AEEVA_ARG(args, uArg32, int32);  // See how much room needed
+            uArg64 = uArg32;
+            if ('d' == cType || 'i' == cType) {
+               uArg64 = (uint64)(int64)(int32)uArg32;
+            }
+         }
+
+         FormatNumber(&ff, achBuf, uArg64);
+
+      } else if (pfnFormatFloatFunc &&
+                 ('e' == TOLOWER(cType) ||
+                  'f' == TOLOWER(cType) ||
+                  'g' == TOLOWER(cType) ||
+                  'a' == TOLOWER(cType))) {
+
+         // float
+            int nError = AEE_SUCCESS;
+            double dNumber;
+
+            AEEVA_ARG(args, dNumber, double);
+            nError = pfnFormatFloatFunc(&ff, dNumber, achBuf2);
+            if (FAILED(nError)) {
+               continue;
+            }
+
+      } else if ('\0' == cType) {
+
+         // premature end
+         break;
+
+      } else {
+         // Unknown type
+         BufBound_Putc(&bb, cType);
+         continue;
+      }
+
+      // FieldFormat computed variables + nWidth controls output
+
+      if (ff.flags & FF_ZERO) {
+         ff.nNumWidth = ff.nWidth - ff.nPrefix;
+      }
+
+      {
+         int nLen1 = ff.nLen;
+         int nLen2 = STD_MAX(ff.nNumWidth, nLen1) + ff.nPrefix;
+
+         // Putnc() safely ignores negative sizes
+         BufBound_Putnc(&bb, ' ', smath_Sub(ff.nWidth,nLen2));
+         BufBound_Write(&bb, ff.pszStr, ff.nPrefix);
+         BufBound_Putnc(&bb, '0', smath_Sub(ff.nNumWidth, nLen1));
+         BufBound_Write(&bb, ff.pszStr+ff.nPrefix, nLen1);
+         BufBound_Putnc(&bb, ' ', smath_Sub(-nLen2, ff.nWidth));
+      }
+   }
+
+   AEEVA_END(args);
+
+   BufBound_ForceNullTerm(&bb);
+
+   /* Return number of bytes required regardless if buffer bound was reached */
+
+   /* Note that we subtract 1 because the NUL byte which was added in
+      BufBound_ForceNullTerm() is counted as a written byte; the semantics
+      of both the ...printf() functions and the strl...() functions call for
+      the NUL byte to be excluded from the count. */
+
+   return BufBound_Wrote(&bb)-1;
+}
+
+int std_vstrlprintf(char *pszDest, int nDestSize,
+                    const char *cpszFmt,
+                    AEEVaList args)
+{
+   return std_strlprintf_inner(pszDest, nDestSize, cpszFmt, args, NULL);
+}
+
+int std_vsnprintf(char *pszDest, int nDestSize,
+                  const char *cpszFmt,
+                  AEEVaList args)
+/*
+   Same as std_vstrlprintf with the additional support of floating point
+   conversion specifiers - %e, %f, %g and %a
+*/
+{
+   return std_strlprintf_inner(pszDest, nDestSize, cpszFmt, args, FormatFloat);
+}
+
+int std_strlprintf(char *pszDest, int nDestSize, const char *pszFmt, ...)
+{
+   int nRet;
+   AEEVaList args;
+
+   AEEVA_START(args, pszFmt);
+
+   nRet = std_vstrlprintf(pszDest, nDestSize, pszFmt, args);
+
+   AEEVA_END(args);
+
+   return nRet;
+}
+
+int std_snprintf(char *pszDest, int nDestSize, const char *pszFmt, ...)
+/*
+   Same as std_strlprintf with the additional support of floating point
+   conversion specifiers - %e, %f, %g and %a
+*/
+{
+   int nRet;
+   AEEVaList args;
+
+   AEEVA_START(args, pszFmt);
+
+   nRet = std_vsnprintf(pszDest, nDestSize, pszFmt, args);
+
+   AEEVA_END(args);
+
+   return nRet;
+}
diff --git a/src/symbols.lst b/src/symbols.lst
new file mode 100644
index 0000000..5e0458d
--- /dev/null
+++ b/src/symbols.lst
@@ -0,0 +1,56 @@
+/*
+ * Copyright (c) 2019, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *    * Redistributions of source code must retain the above copyright
+ *      notice, this list of conditions and the following disclaimer.
+ *    * Redistributions in binary form must reproduce the above
+ *      copyright notice, this list of conditions and the following
+ *      disclaimer in the documentation and/or other materials provided
+ *      with the distribution.
+ *    * Neither the name of The Linux Foundation nor the names of its
+ *      contributors may be used to endorse or promote products derived
+ *      from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * 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.
+ */
+{
+   global:
+      remote_handle_open;
+      remote_handle_invoke;
+      remote_handle_close;
+      remote_handle_control;
+      remote_session_control;
+      remote_mmap;
+      remote_munmap;
+      remote_mmap64;
+      remote_munmap64;
+      remote_register_buf;
+      remote_register_buf_attr;
+      remote_register_fd;
+      remote_register_dma_handle;
+      remote_register_dma_handle_attr;
+      remote_set_mode;
+      remote_handle64_open;
+      remote_handle64_invoke;
+      remote_handle64_close;
+      remote_handle64_control;
+      rpcmem_alloc;
+      rpcmem_free;
+      rpcmem_to_fd;
+      rpcmem_init;
+      rpcmem_deinit;
+   local: *;
+};