summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/AEEsmath.h38
-rw-r--r--src/BufBound.c225
-rw-r--r--src/adsp_current_process1_stub.c587
-rw-r--r--src/adsp_current_process_stub.c669
-rw-r--r--src/adsp_def_symbols.lst33
-rw-r--r--src/adsp_default_listener.c106
-rw-r--r--src/adsp_default_listener_stub.c517
-rw-r--r--src/adsp_listener_stub.c797
-rw-r--r--src/adsp_perf_stub.c623
-rw-r--r--src/adspmsgd_adsp1_stub.c489
-rw-r--r--src/adspmsgd_adsp_stub.c595
-rw-r--r--src/adspmsgd_android.c83
-rw-r--r--src/adspmsgd_apps.c82
-rw-r--r--src/adspmsgd_apps_skel.c494
-rw-r--r--src/adsprpcd.c71
-rw-r--r--src/apps_mem_imp.c244
-rw-r--r--src/apps_mem_skel.c617
-rw-r--r--src/apps_remotectl_skel.c499
-rw-r--r--src/apps_std_imp.c1076
-rw-r--r--src/apps_std_skel.c1227
-rw-r--r--src/atomic.c68
-rw-r--r--src/cae.c88
-rw-r--r--src/cdsprpcd.c71
-rw-r--r--src/fastrpc_apps_user.c1915
-rw-r--r--src/fastrpc_perf.c217
-rw-r--r--src/gpls.c72
-rw-r--r--src/listener_android.c474
-rw-r--r--src/log_config.c543
-rw-r--r--src/mod_table.c865
-rw-r--r--src/pl_list.c40
-rw-r--r--src/platform_libs.c121
-rw-r--r--src/remote_priv.h42
-rw-r--r--src/remotectl_stub.c656
-rw-r--r--src/rpcmem_android.c183
-rw-r--r--src/smath.c54
-rw-r--r--src/std.c570
-rw-r--r--src/std_SwapBytes.c194
-rw-r--r--src/std_dtoa.c504
-rw-r--r--src/std_dtoa.h137
-rw-r--r--src/std_mem.c107
-rw-r--r--src/std_path.c165
-rw-r--r--src/std_strlprintf.c759
-rw-r--r--src/symbols.lst56
43 files changed, 16973 insertions, 0 deletions
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: *;
+};