+
+#define COAP_TRANS_LOCK(ctx) coap_lock(ctx->transaction_lock)
+#define COAP_TRANS_UNLOCK(ctx ) coap_unlock(ctx->transaction_lock)
+
+/* REST_MAX_CHUNK_SIZE is the max size of payload.
+ * The maximum buffer size that is provided for resource responses and must be respected due to the limited IP buffer.
+ * Larger data must be handled by the resource and will be sent chunk-wise through a TCP stream or CoAP blocks.
+ */
+#ifndef REST_MAX_CHUNK_SIZE
+#define REST_MAX_CHUNK_SIZE (1024*1024)
+#endif
+
+#ifndef MIN
+#define MIN(a, b) ((a) < (b) ? (a) : (b))
+#endif /* MIN */
+
+#define CLOCK_SECOND 1000
+
+typedef enum {
+ A_Raw, A_Sock_Addr, A_IP_Addr, A_Custom
+} Net_Addr_Type;
+
+#define NET_ADDR_RAW_SIZE 32
+
+typedef struct net_addr_coap {
+ Net_Addr_Type addr_type;
+ union {
+ char raw[NET_ADDR_RAW_SIZE];
+ struct sockaddr_in sock_addr;
+ } u;
+ uint16_t port;
+ uint16_t addr_len;
+} net_addr_t;
+
+#define uip_ipaddr_t struct net_addr_coap
+
+#define memb_free(x, y) free(x)
+
+void set_addr_ip(uip_ipaddr_t *, char * ip, int port);
+uip_ipaddr_t * new_net_addr(Net_Addr_Type type);
+void copy_net_addr(uip_ipaddr_t * dest, uip_ipaddr_t * src);
+bool compare_net_addr(uip_ipaddr_t * dest, uip_ipaddr_t * src);
+
+uint32_t get_elpased_ms(uint32_t * last_system_clock);
+uint32_t get_platform_time();
+uint32_t get_platform_time_sec();
+
+void coap_sleep_ms(uint32_t ms);
+void coap_lock(void *);
+void coap_unlock(void *);
+void * coap_create_lock();
+void coap_free_lock(void *);
+
+void *xalloc(uint32_t size);
+
+#define os_malloc bh_malloc
+#define os_free bh_free
+
+#ifdef __cplusplus
+}
+#endif
+#endif /* COAP_PLATFORMS_H_ */
diff --git a/core/shared-lib/coap/lib_coap.cmake b/core/shared-lib/coap/lib_coap.cmake
new file mode 100644
index 0000000000..8a35f3cb77
--- /dev/null
+++ b/core/shared-lib/coap/lib_coap.cmake
@@ -0,0 +1,23 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+set (LIB_COAP_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${LIB_COAP_DIR}/er-coap)
+include_directories(${LIB_COAP_DIR}/extension)
+
+file (GLOB_RECURSE source_all ${LIB_COAP_DIR}/*.c)
+
+set (LIB_COAP_SOURCE ${source_all})
+
diff --git a/core/shared-lib/include/bni.h b/core/shared-lib/include/bni.h
new file mode 100644
index 0000000000..36e797fd6a
--- /dev/null
+++ b/core/shared-lib/include/bni.h
@@ -0,0 +1,236 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file bni.h
+ * @date Mon Jul 2 16:54:58 2012
+ *
+ * @brief Beihai native interface.
+ */
+
+#ifndef BNI_H
+#define BNI_H
+
+#include "bh_types.h"
+
+/* Primitive types */
+typedef uint8 jboolean;
+typedef int8 jbyte;
+typedef uint16 jchar;
+typedef int16 jshort;
+typedef int32 jint;
+typedef int64 jlong;
+typedef float jfloat;
+typedef double jdouble;
+typedef jint jsize;
+
+/* Predefined Java class types. */
+struct _jobject;
+typedef struct _jobject *jobject;
+struct _jclass;
+typedef struct _jclass *jclass;
+struct _jstring;
+typedef struct _jstring *jstring;
+
+/* Values of jboolean: */
+#define BNI_FALSE 0
+#define BNI_TRUE 1
+
+/**
+ * Return the length of the array object.
+ *
+ * @param array Java array object
+ *
+ * @return the length of the Java array
+ */
+#define bni_array_length(array) ((jsize)((uint32)(array)->__length >> 2))
+
+/**
+ * Return the address of the first element of array object.
+ *
+ * @param array Java array object
+ *
+ * @return the address of the first element of array object
+ */
+#define bni_array_elem(array) ((array)->__elem)
+
+/**
+ * Find the Java class with given class name.
+ *
+ * @param name Java class name
+ *
+ * @return class object of the Java class if found, NULL otherwise
+ *
+ * @throws OutOfMemoryError if VM runs out of memory.
+ */
+jclass
+bni_find_class(const char *name);
+
+/**
+ * Throw an exception of given class with message.
+ *
+ * @param clazz class object of a subclass of java.lang.Throwable
+ * @param msg message for the exception or NULL if no message
+ *
+ * @return 0 if succeeds, nonzero otherwise
+ */
+jint
+bni_throw_new(jclass clazz, const char *msg);
+
+/**
+ * Throw a NullPointerException.
+ *
+ * @throws NullPointerException
+ */
+void
+bni_throw_npe(void);
+
+/**
+ * Throw an ArrayIndexOutOfBoundsException
+ *
+ * @param index the index used to access the array
+ *
+ * @throws ArrayIndexOutOfBoundsException
+ */
+void
+bni_throw_aioobe(int index);
+
+/**
+ * Determine whether an exception is being thrown.
+ *
+ * @return exception object if exception is thrown, NULL otherwise
+ */
+jobject
+bni_exception_occurred(void);
+
+/**
+ * Print the current exception to error-reporting channel.
+ */
+void
+bni_exception_describe(void);
+
+/**
+ * Clear the currently thrown exception.
+ */
+void
+bni_exception_clear(void);
+
+/**
+ * Return the Unicode character number of a string.
+ *
+ * @param str Java string object
+ *
+ * @return the Unicode character number of the string
+ */
+jsize
+bni_string_length(jstring str);
+
+/**
+ * Return the length in bytes of the modified UTF-8 representation of
+ * a string.
+ *
+ * @param str Java string object
+ * @param start start offset in the string
+ * @param len number of Unicode characters
+ *
+ * @return the UTF-8 length of the string
+ *
+ * @throws StringIndexOutOfBoundsException on index overflow.
+ */
+jsize
+bni_string_utf_length(jstring str, jsize start, jsize len);
+
+/**
+ * Copies len number of Unicode characters beginning at offset start
+ * to the given buffer buf.
+ *
+ * @param str Java string object
+ * @param start start offset in the string
+ * @param len number of Unicode characters to copy
+ * @param buf buffer for storing the result
+ */
+void
+bni_string_region(jstring str, jsize start, jsize len, jchar *buf);
+
+/**
+ * Translates len number of Unicode characters beginning at offset
+ * start into modified UTF-8 encoding and place the result in the
+ * given buffer buf.
+ *
+ * @param str Java string object
+ * @param start start offset in the string
+ * @param len number of Unicode characters to copy
+ * @param buf buffer for storing the result
+ *
+ * @throws StringIndexOutOfBoundsException on index overflow.
+ */
+void
+bni_string_utf_region(jstring str, jsize start, jsize len, char *buf);
+
+/**
+ * Translate Unicode characters into modified UTF-8 encoding and return
+ * the result.
+ *
+ * @param str Java string object
+ *
+ * @return the UTF-8 encoding string if succeeds, NULL otherwise
+ */
+char *
+bni_string_get_utf_chars(jstring str);
+
+/**
+ * Get the given Java object's class index.
+ *
+ * @param obj Java object
+ *
+ * @return -1 if obj is an array, class index of the object otherwise
+ */
+jint
+bni_object_class_index(jobject obj);
+
+/**
+ * Allocate memory from the current instance's private heap.
+ *
+ * @param size bytes to allocate
+ *
+ * @return pointer to the allocated memory
+ *
+ * @throws OutOfMemoryError if VM runs out of memory.
+ */
+void*
+bni_malloc(unsigned size);
+
+/**
+ * Allocate memory from the current instance's private heap and clear
+ * to zero.
+ *
+ * @param size bytes to allocate
+ *
+ * @return pointer to the allocated memory
+ *
+ * @throws OutOfMemoryError if VM runs out of memory.
+ */
+void*
+bni_calloc(unsigned size);
+
+/**
+ * Free the memory allocated from the current instance's private heap.
+ *
+ * @param ptr pointer to the memory in current instance's private heap
+ */
+void
+bni_free(void *ptr);
+
+#endif
diff --git a/core/shared-lib/include/jeff_export.h b/core/shared-lib/include/jeff_export.h
new file mode 100755
index 0000000000..360bba7dbc
--- /dev/null
+++ b/core/shared-lib/include/jeff_export.h
@@ -0,0 +1,615 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+/**
+ * @file jeff-export.h
+ * @date Wed Aug 3 18:17:30 2011
+ *
+ * @brief Exported interface for operating or executing JEFF files.
+ * All interface names start with "jeff_", which is the namespace name
+ * of this module.
+ */
+
+#ifndef JEFF_EXPORT_H
+#define JEFF_EXPORT_H
+
+#include "bni.h"
+#include "korp_types.h"
+
+/********************************************************************
+ * Exported internal types
+ ********************************************************************/
+
+/**
+ * JEFF file handle type
+ */
+struct JeffFileHeaderLinked;
+typedef struct JeffFileHeaderLinked *jeff_file_t;
+
+/**
+ * JEFF class type
+ */
+struct JeffClassHeaderLinked;
+typedef struct JeffClassHeaderLinked *jeff_class_t;
+
+/**
+ * VM instance handle type
+ */
+struct JeffInstanceLocalRoot;
+typedef struct JeffInstanceLocalRoot *jeff_instance_t;
+
+/**
+ * Record of one native method's definition.
+ */
+struct JeffNativeMethodDef {
+ /* Mangled name of the native method. NULL for initialization
+ functions. */
+ const char *mangled_name;
+
+ /* Points to the native C function. */
+ void (*func_ptr)(uint32 *);
+
+ /* Return size type of the native function. */
+ uint32 return_size_type;
+};
+
+/********************************************************************
+ * Interface for operating global environment of the JEFF VM
+ ********************************************************************/
+
+/**
+ * Load the core library from the given file buffer and initialize the
+ * runtime environment (global objects etc.) of the VM. The thread
+ * calls this function becomes the supervisor thread, which belongs to
+ * a unique supervisor instance. Currently, if this init failed,
+ * partially initialized states of the VM runtime environment won't be
+ * cleaned up, so the VM must be shutdown and restarted. method_defs
+ * points to an array of native method definition records.
+ * Initialization functions must be in the front of the array and
+ * following native method definitions must be sorted by their mangled
+ * names.
+ *
+ * @param file the JEFF file of the core library
+ * @param file_size the size of the JEFF file of the core library
+ * @param method_defs native method definition records
+ * @param method_defs_num number of native method records
+ * @param heap the heap for the current (supervisor) instance
+ *
+ * @return true if succeeds, otherwise the error cannot be recovered
+ */
+bool
+jeff_runtime_init(jeff_file_t file, unsigned file_size,
+ struct JeffNativeMethodDef *method_defs, unsigned method_defs_num,
+ void *heap);
+
+/**
+ * Load a JEFF file into the VM from the given file buffer. It can be
+ * called from any VM thread.
+ *
+ * @param file the JEFF file to be loaded
+ * @param size the size of the JEFF file
+ * @param is_library whether the JEFF file is a library
+ * @param allow_to_load a function that returns true if classes in the
+ * given package is allowed to be loaded. The NULL function pointer
+ * allows all packages.
+ * @param allow_to_link a function that returns true if classes in the
+ * given package is allowed to be linked to. The NULL function
+ * pointer allows all packages.
+ *
+ * @return true if succeeds, otherwise detailed error information is
+ * passed to vmci_diagnostic_print. The caller can catch it by
+ * implementing that function.
+ */
+bool
+jeff_runtime_load(jeff_file_t file, unsigned size, bool is_library,
+ bool (*allow_to_load)(const uint8 *pname, unsigned len),
+ bool (*allow_to_link)(const uint8 *pname, unsigned plen,
+ const uint8 *cname, unsigned clen));
+
+/**
+ * Unload a JEFF file from the VM. All resources related to the JEFF
+ * file except the JEFF file itself are released. It can be called
+ * from any VM thread.
+ *
+ * @param file the JEFF file to be unloaded
+ *
+ * @return true if succeeds, otherwise detailed error information is
+ * passed to vmci_diagnostic_print. The caller can catch it by
+ * implementing that function.
+ */
+bool
+jeff_runtime_unload(jeff_file_t file);
+
+/**
+ * Return the JEFF file with the given file uid.
+ *
+ * @param fuid the unique id of a loaded JEFF file
+ *
+ * @return the JEFF file is exists, otherwise NULL
+ */
+jeff_file_t
+jeff_runtime_fuid_to_file(unsigned fuid);
+
+/**
+ * Return the file uid of the given JEFF file.
+ *
+ * @param file a loaded JEFF file
+ *
+ * @return the unique id of the given JEFF file
+ */
+unsigned
+jeff_runtime_file_to_fuid(jeff_file_t file);
+
+/**
+ * Create a supervisor thread belonging to the supervisor instance.
+ * Threads that may interact with VM core must be either the main
+ * thread of supervisor instance (which calls jeff_runtime_init) or
+ * created by this function so that VM core required data structures
+ * can be set up correctly.
+ *
+ * @param start_routine the start routine of the new thread
+ * @param arg argument to the start routine
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jeff_runtime_create_supervisor_thread(void* (*start_routine)(void *),
+ void *arg);
+
+/**
+ * Create a supervisor thread belonging to the supervisor instance.
+ * Threads that may interact with VM core must be either the main
+ * thread of supervisor instance (which calls jeff_runtime_init) or
+ * created by this function so that VM core required data structures
+ * can be set up correctly.
+ *
+ * @param start_routine the start routine of the new thread
+ * @param arg argument to the start routine
+ * @param prio thread priority
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jeff_runtime_create_supervisor_thread_with_prio(void* (*start_routine)(void *),
+ void *arg, int prio);
+
+/********************************************************************
+ * Interface for operating instance local environment
+ ********************************************************************/
+
+/**
+ * Create a VM instance with the given JEFF file as its main file,
+ * (i.e. the file containing the main class of the VM instance). This
+ * function can be called from any VM thread, but it must be isolated
+ * from JEFF file's unloading operation so that the main file won't be
+ * unloaded before it's locked by the new instance. All instance
+ * local memory except stacks of threads are allocated from the given
+ * heap. If succeeds, it increases reference count of the main_file
+ * and returns the handle of the new VM instance. The new instance's
+ * main thread will run the start_routine with argument arg. If the
+ * cleanup_routine is not NULL, it will be called after start_routine
+ * returns and just before the main thread exits. It will also be
+ * called after the instance is destroied. It is guaranteed to be
+ * called exactly once no matter how the instance terminates.
+ *
+ * @param main_file the main JEFF file of the new instance
+ * @param heap the private heap of the new instance
+ * @param stack_depth the maximal nesting levels of Java methods of
+ * the new instance. It must be <= 16 * 1024. Otherwise the instance
+ * creation will fail.
+ * @param start_routine start routine of the main thread. Don't
+ * destroy the heap or inform other thread to do this at the end of
+ * this routine since after it returns, VM core will call destroy
+ * functions on objects allocated in this heap (e.g. locks and
+ * condition variables). Do the destroying or informing of destroying
+ * in the cleanup_routine.
+ * @param arg the instance argument that will be passed to the start
+ * routine. It can be get or set by jeff_runtime_get_instance_arg and
+ * jeff_runtime_set_instance arg from threads of the instance. The
+ * caller can use it to store instance local data.
+ * @param cleanup_routine the optional cleanup routine for the
+ * instance, which may be NULL. It may be executed in the end of the
+ * main thread of the created instance by this function if this
+ * instance exits normally, or it may be executed in a thread of other
+ * instance in case this instance is being killed by that instance.
+ * In both cases, this routine regards it is executed in a thread of
+ * this instance (the instance created by this function) because
+ * jeff_runtime_get_instance_arg will always return the argument of
+ * this instance.
+ *
+ * @return the VM instance handle if succeeds, NULL otherwise
+ */
+jeff_instance_t
+jeff_runtime_create_instance(jeff_file_t main_file, void *heap,
+ unsigned stack_depth, void* (*start_routine)(void *), void *arg,
+ void (*cleanup_routine)(void));
+
+/**
+ * Destroy the given VM instance and decrease the reference count of
+ * its main file and all explicitly used JEFF files. It can be called
+ * from any VM thread. If there are alive threads of the instance,
+ * they will be terminated mandatorily and then the cleanup routine is
+ * called if it's not NULL.
+ *
+ * @param handle the handle of the instance to be destroyed
+ */
+void
+jeff_runtime_destroy_instance(jeff_instance_t handle);
+
+/**
+ * Retrieve the current instance's argument.
+ *
+ * @return the current instance's argument
+ */
+void*
+jeff_runtime_get_instance_arg(void);
+
+/**
+ * Set the current instance's argument.
+ *
+ * @return the new argument for the current instance
+ */
+void
+jeff_runtime_set_instance_arg(void *arg);
+
+/**
+ * Retrieve the current instance's heap.
+ *
+ * @return the current instance's heap
+ */
+void*
+jeff_runtime_get_instance_heap(void);
+
+/**
+ * Suspend all threads of the given VM instance. This function can
+ * only be called from thread that is not of the given VM instance.
+ *
+ * @param handle the handle of the instance to be suspended
+ */
+void
+jeff_runtime_suspend_instance(jeff_instance_t handle);
+
+/**
+ * Resume all threads of the given VM instance. This function can
+ * only be called from thread that is not of the given VM instance.
+ *
+ * @param handle the handle of the instance to be resumed
+ */
+void
+jeff_runtime_resume_instance(jeff_instance_t handle);
+
+/**
+ * Interrupt all threads of the given VM instance. This function can
+ * only be called from thread that is not of the given VM instance.
+ *
+ * @param handle the handle of the instance to be interrupted
+ * @param by_force whether the interruption is by force
+ */
+void
+jeff_runtime_interrupt_instance(jeff_instance_t handle, bool by_force);
+
+/**
+ * Wait for the given VM instance to terminate.
+ *
+ * @param ilr the VM instance to be waited for
+ * @param mills wait millseconds to return
+ */
+void
+jeff_runtime_wait_for_instance(jeff_instance_t ilr, int mills);
+
+/********************************************************************
+ * Interface for operating thread local environment
+ ********************************************************************/
+
+/**
+ * Return true if there is an uncaught exception (thrown during
+ * running an application or applet command).
+ *
+ * @return true if there is an uncaught exception
+ */
+bool
+jeff_runtime_check_uncaught_exception(void);
+
+/**
+ * Print qualified name of the uncaught exception (and stack trace if
+ * enabled) by calling vmci_diagnostic_print.
+ */
+void
+jeff_runtime_print_uncaught_exception(void);
+
+/**
+ * Clear the uncaught exception.
+ */
+void
+jeff_runtime_reset_uncaught_exception(void);
+
+/**
+ * Change current thread to a safe state (VMWAIT). After calling this
+ * and before calling jeff_runtime_exit_safe_state, all operations
+ * must be safe, i.e. no GC or system level resource operations are
+ * allowed because in a safe state, the VM instance is assumed to be
+ * able to perform GC, JDWP or termination at any time. Usually, this
+ * function is called just before the native code is going to wait for
+ * something and the exiting safe state function is called just after
+ * the waiting returns.
+ */
+void
+jeff_runtime_enter_safe_state(void);
+
+/**
+ * Change current thread to an unsafe state (RUNNING) so that unsafe
+ * operations can also be done.
+ */
+void
+jeff_runtime_exit_safe_state(void);
+
+/**
+ * Set thread local error code for the current thread.
+ *
+ * @param code the error code to be set
+ */
+void
+jeff_runtime_set_error(unsigned code);
+
+/**
+ * Get the last error code of current thread.
+ *
+ * @return the last error code of current thread
+ */
+unsigned
+jeff_runtime_get_error(void);
+
+/********************************************************************
+ * Interface for GC support
+ ********************************************************************/
+
+/**
+ * Traverse all objects of the given heap that are global or locate in
+ * threads' frames and return them by calling vmci_gc_rootset_elem.
+ * This function will suspend all threads except the current one of
+ * the VM instance owning the given heap before traversing. It
+ * traverses either all or none of the rootset objects, and returns
+ * true and false respectively. If it returns false, the GC process
+ * shouldn't proceed and is not necessary to unmark anything because
+ * no objects are marked. The function jeff_runtime_gc_finished must
+ * be called if and only if this function returns true so as to resume
+ * threads that are suspended during GC process.
+ *
+ * @param heap the heap for which rootset objects are looked up
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jeff_runtime_traverse_gc_rootset(void *heap);
+
+/**
+ * Get the reference offset table of the given object. If the
+ * returned value R >= 0, *ret points to the reference offset table of
+ * the object and R is the number of offsets in the table. Otherwise,
+ * if the returned value R < 0, all reference fields of the object
+ * must be in a continuous region (usually the object is an array),
+ * then *ret is the offset to the first field in the region and R is
+ * the number of such fields in the region.
+ *
+ * @param obj pointer to the Java object
+ * @param ret points to a pointer for storing the reference offset
+ * table if return value >= 0, or for storing the offset to the first
+ * object reference in the Java object if return value < 0
+ *
+ * @return number of offsets in the reference_offset table if >= 0, or
+ * number of object references in the object if < 0
+ */
+int
+jeff_object_get_reference_offsets(const jobject obj, uint16 **ret);
+
+/**
+ * Inform the containing VM instance that GC has finished and all
+ * suspended threads can be resumed. This function must be called if
+ * and only if jeff_runtime_traverse_gc_rootset returns true.
+ */
+void
+jeff_runtime_gc_finished(void);
+
+/********************************************************************
+ * Interface for tooling support
+ ********************************************************************/
+
+/**
+ * This function is used to suspend the main thread of VM instance so
+ * that debugger can have chance to connect to the VM instance, set
+ * breakpoints and do any other debug settings. It must be called
+ * from the main thread of VM instance at the point just after VM
+ * instance initialization finishes and just before application code
+ * is to be executed.
+ */
+void
+jeff_tool_suspend_self(void);
+
+/**
+ * Start up tool agent thread for the given VM instance. It can be
+ * called from any VM thread.
+ *
+ * @param handle the VM instance for which tool agent is started up
+ * @param queue queue of the tool agent
+ * @return true if succeeds, false otherwise
+ */
+bool
+jeff_tool_start_agent(jeff_instance_t handle, void *queue);
+
+/********************************************************************
+ * Interface for toolkit support
+ ********************************************************************/
+
+/**
+ * Return the JEFF class pointer of the given class name.
+ *
+ * @param class_name the qualified class name
+ *
+ * @return the JEFF class pointer
+ */
+jeff_class_t
+jeff_tool_get_jeff_class(const char *class_name);
+
+/**
+ * Get the mangled class name of the given class.
+ *
+ * @param clz the JEFF class
+ * @param buf buffer for returning the mangled name
+ * @param buf_size size of the buffer
+ *
+ * @return actual size of the mangled class name including the
+ * terminating null byte
+ */
+unsigned
+jeff_tool_get_mangled_class_name(jeff_class_t clz, char *buf,
+ unsigned buf_size);
+
+/**
+ * Get class index of given class in its containing JEFF file.
+ *
+ * @param clz the JEFF class
+ *
+ * @return class index in the containing JEFF file
+ */
+int
+jeff_tool_get_class_index(jeff_class_t clz);
+
+/**
+ * Callback handler prototype for traversing fields of class.
+ *
+ * @param arg argument passed to the handler from caller
+ * @param access_flag access flag of the method
+ * @param name the field name
+ * @param descriptor mangled field type descriptor
+ * @param offset the offset of the field in the class
+ * @param size size of the field
+ */
+typedef void
+(*JeffToolFieldHandler)(void *arg, unsigned access_flag, const char *name,
+ const char *descriptor, unsigned offset, unsigned size);
+
+/**
+ * Traverse all fields of the given class, including those inherited
+ * from super classes. The fields are traversed in the same order as
+ * the field layout of the class.
+ *
+ * @param arg argument to be passed to the handler
+ * @param clz the JEFF class
+ * @param instance instance fields or static fielts
+ * @param handler the callback handler for each field
+ */
+void
+jeff_tool_foreach_field(void *arg, jeff_class_t clz, bool instance,
+ JeffToolFieldHandler handler);
+
+/**
+ * Callback handler prototype for traversing methods of class.
+ *
+ * @param arg argument passed to the handler from caller
+ * @param access_flag access flag of the method
+ * @param name mangled name of the method
+ * @param descriptor mangled method arguments descriptor
+ * @param retune_type mangled descriptor of method's return type
+ */
+typedef void
+(*JeffToolMethodHandler)(void *arg, unsigned access_flag, const char *name,
+ const char *descriptor, const char *return_type);
+
+/**
+ * Traverse all methods of the given class.
+ *
+ * @param arg argument to be passed to the handler
+ * @param clz the JEFF class
+ * @param handler the callback handler for each method
+ */
+void
+jeff_tool_foreach_method(void *arg, jeff_class_t clz,
+ JeffToolMethodHandler handler);
+
+/**
+ * Callback handler prototype for traversing classes of main file.
+ *
+ * @param arg argument passed to the handler from caller
+ * @param clz pointer to one class in the main file
+ */
+typedef void
+(*JeffToolClassHandler)(void *arg, jeff_class_t clz);
+
+/**
+ * Traverse all classes of the main file.
+ *
+ * @param arg argument to be passed to the handler
+ * @param handler the callback handler for each class
+ */
+void
+jeff_tool_foreach_class(void *arg, JeffToolClassHandler handler);
+
+/********************************************************************
+ * Interface for executing applications
+ ********************************************************************/
+
+/**
+ * Initialize global environment for executing Java applications.
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jeff_application_env_init(void);
+
+/**
+ * Find the unique class containing a public static "main
+ * ([Ljava.lang.String;)V" method from the main JEFF file of the
+ * current instance and execute that method.
+ *
+ * @param argc the number of arguments
+ * @param argv the arguments array
+ *
+ * @return true if the main method is called, false otherwise (e.g. an
+ * exception occurs when preparing the arguments Java string array)
+ */
+bool
+jeff_application_execute(int argc, char *argv[]);
+
+/********************************************************************
+ * Interface for executing applets
+ ********************************************************************/
+
+/**
+ * Initialize global environment for executing applets.
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jeff_applet_env_init(void);
+
+/**
+ * Start to run from com.intel.runtime.core.RuntimeContext.main with a
+ * default message queue size and a default service class object. If
+ * the main JEFF file of the current VM instance contains exactly one
+ * class that is derived from com.intel.util.IntelApplet, then use it
+ * as the default service class.
+ *
+ * @param queue_size the default main message queue size
+ * @param default_service_class qualified class name of the default
+ * service class (entry point class), which must be in the main JEFF
+ * file. If NULL, find the default main class with rules described
+ * above.
+ *
+ * @return true if succeeds, false otherwise
+ */
+bool
+jeff_applet_start(int queue_size, const char *default_service_class);
+
+#endif
diff --git a/core/shared-lib/mem-alloc/ems/ems_kfc.c b/core/shared-lib/mem-alloc/ems/ems_kfc.c
index 10fe090ad0..791a298a50 100644
--- a/core/shared-lib/mem-alloc/ems/ems_kfc.c
+++ b/core/shared-lib/mem-alloc/ems/ems_kfc.c
@@ -44,7 +44,7 @@ int gci_check_platform()
CHECK(1, sizeof(gc_int8));
CHECK(1, sizeof(gc_uint8));
CHECK(4, sizeof(gc_size_t));
- CHECK(4, sizeof(void *));
+ /*CHECK(4, sizeof(void *));*/
return GC_SUCCESS;
}
diff --git a/core/shared-lib/utils/runtime_timer.c b/core/shared-lib/utils/runtime_timer.c
index 60356e9300..a0e17fd54e 100644
--- a/core/shared-lib/utils/runtime_timer.c
+++ b/core/shared-lib/utils/runtime_timer.c
@@ -417,7 +417,6 @@ int check_app_timers(timer_ctx_t ctx)
vm_mutex_lock(&ctx->mutex);
app_timer_t * t = ctx->g_app_timers;
- app_timer_t * prev = NULL;
app_timer_t * expired = NULL;
uint64 now = bh_get_tick_ms();
@@ -443,8 +442,6 @@ int check_app_timers(timer_ctx_t ctx)
void cleanup_app_timers(timer_ctx_t ctx)
{
- app_timer_t *t;
-
vm_mutex_lock(&ctx->mutex);
release_timer_list(&ctx->g_app_timers);
diff --git a/doc/pics/architecture_extend.PNG b/doc/pics/architecture_extend.PNG
index b6822ed2d0..31905df5ac 100644
Binary files a/doc/pics/architecture_extend.PNG and b/doc/pics/architecture_extend.PNG differ
diff --git a/doc/pics/safe.PNG b/doc/pics/safe.PNG
index 7d0ed9fcdb..ee3ed21e65 100644
Binary files a/doc/pics/safe.PNG and b/doc/pics/safe.PNG differ
diff --git a/doc/pics/vgl.PNG b/doc/pics/vgl.PNG
new file mode 100644
index 0000000000..d7a06d9568
Binary files /dev/null and b/doc/pics/vgl.PNG differ
diff --git a/doc/pics/vgl2.PNG b/doc/pics/vgl2.PNG
new file mode 100644
index 0000000000..1387d6f103
Binary files /dev/null and b/doc/pics/vgl2.PNG differ
diff --git a/doc/pics/vgl_linux.PNG b/doc/pics/vgl_linux.PNG
new file mode 100644
index 0000000000..65ce063070
Binary files /dev/null and b/doc/pics/vgl_linux.PNG differ
diff --git a/doc/pics/workflow.PNG b/doc/pics/workflow.PNG
index a43fe1adfa..2bba240ff5 100644
Binary files a/doc/pics/workflow.PNG and b/doc/pics/workflow.PNG differ
diff --git a/projects/README.md b/projects/README.md
deleted file mode 100644
index 792d600548..0000000000
--- a/projects/README.md
+++ /dev/null
@@ -1 +0,0 @@
-#
diff --git a/samples/littlevgl/LICENCE.txt b/samples/littlevgl/LICENCE.txt
new file mode 100644
index 0000000000..beaef1d26e
--- /dev/null
+++ b/samples/littlevgl/LICENCE.txt
@@ -0,0 +1,8 @@
+MIT licence
+Copyright (c) 2016 Gábor Kiss-Vámosi
+
+Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the “Software”), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED “AS IS”, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
diff --git a/samples/littlevgl/README.md b/samples/littlevgl/README.md
new file mode 100644
index 0000000000..5933c4d364
--- /dev/null
+++ b/samples/littlevgl/README.md
@@ -0,0 +1,113 @@
+Introduction
+==============
+This sample demonstrates that a graphic user interface application in WebAssembly integrates the LittlevGL, an open-source embedded 2d graphic library.
+
+In this sample, the whole LittlevGL source code is built into the WebAssembly code with the user application. The platform interfaces defined by LittlevGL is implemented in the runtime and exported to the application through the declarations from source "ext_lib_export.c" as below:
+
+ EXPORT_WASM_API(display_init),
+ EXPORT_WASM_API(display_input_read),
+ EXPORT_WASM_API(display_flush),
+ EXPORT_WASM_API(display_fill),
+ EXPORT_WASM_API(display_vdb_write),
+ EXPORT_WASM_API(display_map),
+ EXPORT_WASM_API(time_get_ms), };
+
+The runtime component supports building target for Linux and Zephyr/STM Nucleo board. The beauty of this sample is the WebAssembly application can have identical display and behavior when running from both runtime environments. That implies we can do majority of application validation from desktop environment as long as two runtime distributions support the same set of application interface.
+
+The sample also provides the native Linux version of application without the runtime under folder "vgl-native-ui-app". It can help to check differences between the implementations in native and WebAssembly.
+
+
+
+
+The number on top will plus one each second, and the number on the bottom will plus one when clicked.
+
+Install required SDK and libraries
+==============
+- 32 bit SDL(simple directmedia layer)
+Use apt-get
+ `sudo apt-get install libsdl2-dev:i386`
+Or download source from www.libsdl.org
+ `./configure C_FLAGS=-m32 CXX_FLAGS=-m32 LD_FLAGS=-m32`
+ `make`
+ `sudo make install`
+- Install EMSDK
+
+ https://emscripten.org/docs/tools_reference/emsdk.html
+
+
+Build and Run
+==============
+
+Linux
+--------------------------------
+- Build
+`./build.sh`
+ All binaries are in "out", which contains "host_tool", "vgl_native_ui_app", "TestApplet1.wasm" and "vgl_wasm_runtime".
+- Run native Linux application
+`./vgl_native_ui_app`
+
+- Run WASM VM Linux applicaton & install WASM APP
+ First start vgl_wasm_runtime in server mode.
+`./vgl_wasm_runtime -s`
+ Then install wasm APP use host tool.
+`./host_tool -i ui_app -f ui_app.wasm`
+
+Zephyr
+--------------------------------
+WASM VM and native extension method can be built into Zephyr, Then we can install wasm app into STM32.
+- Build WASM VM into Zephyr system
+ a. clone zephyr source code
+`git clone https://github.com/zephyrproject-rtos/zephyr.git`
+ b. copy samples
+ `cd zephyr/samples/`
+ `cp -a samples/littlevgl/vgl-wasm-runtime vgl-wasm-runtime`
+ `cd vgl-wasm-runtime/zephyr_build`
+ c. create a link to wamr core
+ ` ln -s /core core`
+ d. build source code
+ Since ui_app incorporated LittlevGL source code, so it needs more RAM on the device to install the application.
+ It is recommended that RAM SIZE greater than 512KB.
+ In our test use nucleo_f767zi, which is not supported by Zephyr.
+ However, nucleo_f767zi is almost the same as nucleo_f746zg, except FLASH and SRAM size.
+ So we changed the DTS setting of nucleo_f746zg boards for a workaround.
+
+ `Modify zephyr/dts/arm/st/f7/stm32f746xg.dtsi, change DT_SIZE_K(320) to DT_SIZE_K(512)`
+ `mkdir build && cd build`
+ `source ../../../../zephyr-env.sh`
+ `cmake -GNinja -DBOARD=nucleo_f746zg ..`
+ ` ninja flash`
+
+- Test on STM32 NUCLEO_F767ZI with ILI9341 Display with XPT2046 touch
+Hardware Connections
+
+```
++-------------------+-+------------------+
+|NUCLEO-F767ZI || ILI9341 Display |
++-------------------+-+------------------+
+| CN7.10 | CLK |
++-------------------+-+------------------+
+| CN7.12 | MISO |
++-------------------+-+------------------+
+| CN7.14 | MOSI |
++-------------------+-+------------------+
+| CN11.1 | CS1 for ILI9341 |
++-------------------+-+------------------+
+| CN11.2 | D/C |
++-------------------+-+------------------+
+| CN11.3 | RESET |
++-------------------+-+------------------+
+| CN9.25 | PEN interrupt|
++-------------------+-+------------------+
+| CN9.27 | CS2 for XPT2046 |
++-------------------+-+------------------+
+| CN10.14 | PC UART RX |
++-------------------+-+------------------+
+| CN11.16 | PC UART RX |
++-------------------+-+------------------+
+```
+
+
+- Install WASM application to Zephyr using host_tool
+First, connect PC and STM32 with UART. Then install to use host_tool.
+`./host_tool -D /dev/ttyUSBXXX -i ui_app -f ui_app.wasm`
+
diff --git a/samples/littlevgl/build.sh b/samples/littlevgl/build.sh
new file mode 100755
index 0000000000..ec123263e4
--- /dev/null
+++ b/samples/littlevgl/build.sh
@@ -0,0 +1,69 @@
+#!/bin/bash
+
+PROJECT_DIR=$PWD
+ROOT_DIR=${PWD}/../../..
+OUT_DIR=${PWD}/out
+BUILD_DIR=${PWD}/build
+
+if [ ! -d $BUILD_DIR ]; then
+ mkdir ${BUILD_DIR}
+fi
+
+rm -rf ${OUT_DIR}
+mkdir ${OUT_DIR}
+
+
+cd ${ROOT_DIR}/wamr/core/shared-lib/mem-alloc
+if [ ! -d "tlsf" ]; then
+ git clone https://github.com/mattconte/tlsf
+fi
+
+echo "##################### 1. build native-ui-app start#####################"
+cd $BUILD_DIR
+mkdir -p vgl-native-ui-app
+cd vgl-native-ui-app
+cmake ${PROJECT_DIR}/vgl-native-ui-app
+make
+if [ $? != 0 ];then
+ echo "BUILD_FAIL native-ui-app $?\n"
+ exit 2
+fi
+echo $PWD
+cp vgl_native_ui_app ${OUT_DIR}
+echo "#####################build native-ui-app success"
+
+echo "#####################build host-tool"
+cd $BUILD_DIR
+mkdir -p host-tool
+cd host-tool
+cmake ${ROOT_DIR}/wamr/test-tools/host-tool
+make
+if [ $? != 0 ];then
+ echo "BUILD_FAIL host tool exit as $?\n"
+ exit 2
+fi
+cp host_tool ${OUT_DIR}
+echo "#####################build host-tool success"
+
+
+echo "##################### 2. build littlevgl wasm runtime start#####################"
+cd $BUILD_DIR
+mkdir -p vgl-wasm-runtime
+cd vgl-wasm-runtime
+cmake ${PROJECT_DIR}/vgl-wasm-runtime
+make
+cp vgl_wasm_runtime ${OUT_DIR}/
+
+echo "##################### build littlevgl wasm runtime end#####################"
+
+
+echo "##################### 3. build wasm ui app start#####################"
+cd ${PROJECT_DIR}/wasm-apps
+if [ ! -d "${PROJECT_DIR}/wasm-apps/lvgl" ]; then
+ if [ -d "$BUILD_DIR/vgl-native-ui-app/lvgl" ]; then
+ cp -fr $BUILD_DIR/vgl-native-ui-app/lvgl ${PROJECT_DIR}/wasm-apps
+ fi
+fi
+./build_wasm_app.sh
+cp ui_app.wasm ${OUT_DIR}/
+echo "##################### build wasm ui app end#####################"
diff --git a/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt b/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt
new file mode 100644
index 0000000000..56e9d5deee
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt
@@ -0,0 +1,143 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required (VERSION 2.8.2)
+message ("vgl_native_ui_app...")
+project (vgl_native_ui_app)
+
+
+SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32 -g -DLV_CONF_INCLUDE_SIMPLE -DPLATFORM_NATIVE_LINUX -DUSE_MONITOR -DUSE_MOUSE=1")
+
+set(lv_name lvgl)
+set(LVGL_SOURCE_DIR ${CMAKE_CURRENT_BINARY_DIR}/${lv_name})
+set(LVGL_DRIVER_DIR ${CMAKE_CURRENT_LIST_DIR}/lv-drivers)
+
+message(${LVGL_SOURCE_DIR})
+include( ExternalProject )
+
+configure_file(${CMAKE_CURRENT_SOURCE_DIR}/CMakeLists.txt.in ${CMAKE_CURRENT_BINARY_DIR}/download_lvgl/CMakeLists.txt)
+
+execute_process(COMMAND ${CMAKE_COMMAND} -G "${CMAKE_GENERATOR}" .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download_lvgl )
+if(result)
+ message(FATAL_ERROR "CMake step for lvgl failed: ${result}")
+endif()
+execute_process(COMMAND ${CMAKE_COMMAND} --build .
+ RESULT_VARIABLE result
+ WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/download_lvgl )
+if(result)
+ message(FATAL_ERROR "Build step for lvgl failed: ${result}")
+endif()
+SET (LVGL_SOURCES
+ ${LVGL_SOURCE_DIR}/lv_core/lv_group.c
+ ${LVGL_SOURCE_DIR}/lv_core/lv_indev.c
+ ${LVGL_SOURCE_DIR}/lv_core/lv_lang.c
+ ${LVGL_SOURCE_DIR}/lv_core/lv_obj.c
+ ${LVGL_SOURCE_DIR}/lv_core/lv_refr.c
+ ${LVGL_SOURCE_DIR}/lv_core/lv_style.c
+ ${LVGL_SOURCE_DIR}/lv_core/lv_vdb.c
+
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_arc.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_img.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_label.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_line.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_rbasic.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_rect.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_triangle.c
+ ${LVGL_SOURCE_DIR}/lv_draw/lv_draw_vbasic.c
+
+ ${LVGL_SOURCE_DIR}/lv_hal/lv_hal_disp.c
+ ${LVGL_SOURCE_DIR}/lv_hal/lv_hal_indev.c
+ ${LVGL_SOURCE_DIR}/lv_hal/lv_hal_tick.c
+
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_anim.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_area.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_circ.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_color.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_font.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_fs.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_gc.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_ll.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_log.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_math.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_mem.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_task.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_templ.c
+ ${LVGL_SOURCE_DIR}/lv_misc/lv_txt.c
+
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_arc.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_bar.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_btn.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_btnm.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_calendar.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_canvas.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_cb.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_chart.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_cont.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_ddlist.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_gauge.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_img.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_imgbtn.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_kb.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_label.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_led.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_line.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_list.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_lmeter.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_mbox.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_objx_templ.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_page.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_preload.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_roller.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_slider.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_spinbox.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_sw.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_ta.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_table.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_tabview.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_tileview.c
+ ${LVGL_SOURCE_DIR}/lv_objx/lv_win.c
+
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_alien.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_default.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_material.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_mono.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_nemo.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_night.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_templ.c
+ ${LVGL_SOURCE_DIR}/lv_themes/lv_theme_zen.c
+
+ ${LVGL_SOURCE_DIR}/lv_fonts/lv_font_builtin.c
+ ${LVGL_SOURCE_DIR}/lv_fonts/lv_font_dejavu_20.c
+ ${LVGL_DRIVER_DIR}/linux_display_indev.c
+ ${LVGL_DRIVER_DIR}/indev/mouse.c
+
+)
+SET(SOURCES
+ ${LVGL_SOURCES}
+ ${CMAKE_CURRENT_LIST_DIR}/main.c
+ )
+include_directories(
+ ${LVGL_DRIVER_DIR}
+ ${LVGL_DRIVER_DIR}/display
+ ${LVGL_DRIVER_DIR}/indev
+ ${LVGL_SOURCE_DIR}
+ ${CMAKE_CURRENT_BINARY_DIR}
+ ${CMAKE_CURRENT_LIST_DIR}
+)
+add_executable(vgl_native_ui_app ${SOURCES} )
+target_link_libraries( vgl_native_ui_app -lSDL2)
diff --git a/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt.in b/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt.in
new file mode 100644
index 0000000000..225af16bfb
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/CMakeLists.txt.in
@@ -0,0 +1,29 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 2.8.2)
+
+project(lvgl_download NONE)
+
+include(ExternalProject)
+ExternalProject_Add(${lv_name}
+ GIT_REPOSITORY https://github.com/littlevgl/lvgl.git
+ GIT_TAG v5.3
+ BINARY_DIR ""
+ SOURCE_DIR "${CMAKE_CURRENT_BINARY_DIR}/lvgl"
+ CONFIGURE_COMMAND ""
+ BUILD_COMMAND ""
+ INSTALL_COMMAND ""
+ TEST_COMMAND ""
+ )
diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/.gitignore b/samples/littlevgl/vgl-native-ui-app/lv-drivers/.gitignore
new file mode 100644
index 0000000000..2372cca067
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/.gitignore
@@ -0,0 +1 @@
+**/*.o
\ No newline at end of file
diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/display_indev.h b/samples/littlevgl/vgl-native-ui-app/lv-drivers/display_indev.h
new file mode 100644
index 0000000000..f1b966e0b6
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/display_indev.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DISPLAY_INDEV_H_
+#define DISPLAY_INDEV_H_
+#include
+#include
+#include "mouse.h"
+#include "lvgl/lv_misc/lv_color.h"
+#include "lvgl/lv_hal/lv_hal_indev.h"
+extern void display_init(void);
+extern void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p);
+extern bool display_input_read(lv_indev_data_t * data);
+extern void display_deinit(void);
+extern void display_vdb_write(void *buf, lv_coord_t buf_w, lv_coord_t x,
+ lv_coord_t y, lv_color_t *color, lv_opa_t opa);
+extern int time_get_ms();
+
+#endif
diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.c b/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.c
new file mode 100644
index 0000000000..58f7be0ca5
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.c
@@ -0,0 +1,95 @@
+/**
+ * @file mouse.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "mouse.h"
+#if USE_MOUSE != 0
+
+/*********************
+ * DEFINES
+ *********************/
+#ifndef MONITOR_ZOOM
+#define MONITOR_ZOOM 1
+#endif
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+static bool left_button_down = false;
+static int16_t last_x = 0;
+static int16_t last_y = 0;
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+/**
+ * Initialize the mouse
+ */
+void mouse_init(void)
+{
+
+}
+
+/**
+ * Get the current position and state of the mouse
+ * @param data store the mouse data here
+ * @return false: because the points are not buffered, so no more data to be read
+ */
+bool mouse_read(lv_indev_data_t * data)
+{
+ /*Store the collected data*/
+ data->point.x = last_x;
+ data->point.y = last_y;
+ data->state = left_button_down ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
+
+ return false;
+}
+
+/**
+ * It will be called from the main SDL thread
+ */
+void mouse_handler(SDL_Event * event)
+{
+ switch (event->type) {
+ case SDL_MOUSEBUTTONUP:
+ if (event->button.button == SDL_BUTTON_LEFT)
+ left_button_down = false;
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ if (event->button.button == SDL_BUTTON_LEFT) {
+ left_button_down = true;
+ last_x = event->motion.x / MONITOR_ZOOM;
+ last_y = event->motion.y / MONITOR_ZOOM;
+ }
+ break;
+ case SDL_MOUSEMOTION:
+ last_x = event->motion.x / MONITOR_ZOOM;
+ last_y = event->motion.y / MONITOR_ZOOM;
+
+ break;
+ }
+
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+#endif
diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.h b/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.h
new file mode 100644
index 0000000000..6e7c88e634
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/indev/mouse.h
@@ -0,0 +1,72 @@
+/**
+ * @file mouse.h
+ *
+ */
+
+#ifndef MOUSE_H
+#define MOUSE_H
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#ifdef LV_CONF_INCLUDE_SIMPLE
+//#include "lv_drv_conf.h"
+#else
+#include "../../lv_drv_conf.h"
+#endif
+
+#if USE_MOUSE
+
+#include
+#include
+#include "lvgl/lv_hal/lv_hal_indev.h"
+
+#ifndef MONITOR_SDL_INCLUDE_PATH
+#define MONITOR_SDL_INCLUDE_PATH
+#endif
+
+#include MONITOR_SDL_INCLUDE_PATH
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+
+/**
+ * Initialize the mouse
+ */
+void mouse_init(void);
+/**
+ * Get the current position and state of the mouse
+ * @param data store the mouse data here
+ * @return false: because the points are not buffered, so no more data to be read
+ */
+bool mouse_read(lv_indev_data_t * data);
+
+/**
+ * It will be called from the main SDL thread
+ */
+void mouse_handler(SDL_Event *event);
+
+/**********************
+ * MACROS
+ **********************/
+
+#endif /* USE_MOUSE */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* MOUSE_H */
diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/linux_display_indev.c b/samples/littlevgl/vgl-native-ui-app/lv-drivers/linux_display_indev.c
new file mode 100644
index 0000000000..e8bbc5218e
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/linux_display_indev.c
@@ -0,0 +1,314 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include "display_indev.h"
+#include "sys/time.h"
+#include "SDL2/SDL.h"
+#define MONITOR_HOR_RES 320
+#define MONITOR_VER_RES 240
+#ifndef MONITOR_ZOOM
+#define MONITOR_ZOOM 1
+#endif
+#define SDL_REFR_PERIOD 50
+void monitor_sdl_init(void);
+void monitor_sdl_refr_core(void);
+void monitor_sdl_clean_up(void);
+static uint32_t tft_fb[MONITOR_HOR_RES * MONITOR_VER_RES];
+
+void display_vdb_write(void *buf, lv_coord_t buf_w, lv_coord_t x, lv_coord_t y,
+ lv_color_t *color, lv_opa_t opa)
+{
+ unsigned char *buf_xy = buf + 4 * x + 4 * y * buf_w;
+ lv_color_t * temp = (lv_color_t *) buf_xy;
+ *temp = *color;
+ /*
+ if (opa != LV_OPA_COVER) {
+ lv_color_t mix_color;
+
+ mix_color.red = *buf_xy;
+ mix_color.green = *(buf_xy+1);
+ mix_color.blue = *(buf_xy+2);
+ color = lv_color_mix(color, mix_color, opa);
+ }
+ */
+}
+int time_get_ms()
+{
+ static struct timeval tv;
+ gettimeofday(&tv, NULL);
+ long long time_in_mill = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
+
+ return (int) time_in_mill;
+}
+
+SDL_Window * window;
+SDL_Renderer * renderer;
+SDL_Texture * texture;
+static volatile bool sdl_inited = false;
+static volatile bool sdl_refr_qry = false;
+static volatile bool sdl_quit_qry = false;
+
+void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ /*Return if the area is out the screen*/
+ if (x2 < 0 || y2 < 0 || x1 > MONITOR_HOR_RES - 1
+ || y1 > MONITOR_VER_RES - 1) {
+ return;
+ }
+
+ int32_t y;
+ uint32_t w = x2 - x1 + 1;
+ for (y = y1; y <= y2; y++) {
+ memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color_p,
+ w * sizeof(lv_color_t));
+
+ color_p += w;
+ }
+ sdl_refr_qry = true;
+
+ /*IMPORTANT! It must be called to tell the system the flush is ready*/
+
+}
+
+/**
+ * Fill out the marked area with a color
+ * @param x1 left coordinate
+ * @param y1 top coordinate
+ * @param x2 right coordinate
+ * @param y2 bottom coordinate
+ * @param color fill color
+ */
+void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color)
+{
+ /*Return if the area is out the screen*/
+ if (x2 < 0)
+ return;
+ if (y2 < 0)
+ return;
+ if (x1 > MONITOR_HOR_RES - 1)
+ return;
+ if (y1 > MONITOR_VER_RES - 1)
+ return;
+
+ /*Truncate the area to the screen*/
+ int32_t act_x1 = x1 < 0 ? 0 : x1;
+ int32_t act_y1 = y1 < 0 ? 0 : y1;
+ int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
+ int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
+
+ int32_t x;
+ int32_t y;
+ uint32_t color32 = color.full; //lv_color_to32(color);
+
+ for (x = act_x1; x <= act_x2; x++) {
+ for (y = act_y1; y <= act_y2; y++) {
+ tft_fb[y * MONITOR_HOR_RES + x] = color32;
+ }
+ }
+
+ sdl_refr_qry = true;
+}
+
+/**
+ * Put a color map to the marked area
+ * @param x1 left coordinate
+ * @param y1 top coordinate
+ * @param x2 right coordinate
+ * @param y2 bottom coordinate
+ * @param color_p an array of colors
+ */
+void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ /*Return if the area is out the screen*/
+ if (x2 < 0)
+ return;
+ if (y2 < 0)
+ return;
+ if (x1 > MONITOR_HOR_RES - 1)
+ return;
+ if (y1 > MONITOR_VER_RES - 1)
+ return;
+
+ /*Truncate the area to the screen*/
+ int32_t act_x1 = x1 < 0 ? 0 : x1;
+ int32_t act_y1 = y1 < 0 ? 0 : y1;
+ int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
+ int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
+
+ int32_t x;
+ int32_t y;
+
+ for (y = act_y1; y <= act_y2; y++) {
+ for (x = act_x1; x <= act_x2; x++) {
+ tft_fb[y * MONITOR_HOR_RES + x] = color_p->full; //lv_color_to32(*color_p);
+ color_p++;
+ }
+
+ color_p += x2 - act_x2;
+ }
+
+ sdl_refr_qry = true;
+}
+
+void display_init(void)
+{
+}
+
+void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ monitor_flush(x1, y1, x2, y2, color_p);
+}
+void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color_p)
+{
+ monitor_fill(x1, y1, x2, y2, color_p);
+}
+void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ monitor_map(x1, y1, x2, y2, color_p);
+}
+
+bool display_input_read(lv_indev_data_t * data)
+{
+ return mouse_read(data);
+}
+
+void display_deinit(void)
+{
+
+}
+
+int monitor_sdl_refr_thread(void * param)
+{
+ (void) param;
+
+ /*If not OSX initialize SDL in the Thread*/
+ monitor_sdl_init();
+ /*Run until quit event not arrives*/
+ while (sdl_quit_qry == false) {
+ /*Refresh handling*/
+ monitor_sdl_refr_core();
+ }
+
+ monitor_sdl_clean_up();
+ exit(0);
+
+ return 0;
+}
+
+void monitor_sdl_refr_core(void)
+{
+ if (sdl_refr_qry != false) {
+ sdl_refr_qry = false;
+
+ SDL_UpdateTexture(texture, NULL, tft_fb,
+ MONITOR_HOR_RES * sizeof(uint32_t));
+ SDL_RenderClear(renderer);
+ /*Test: Draw a background to test transparent screens (LV_COLOR_SCREEN_TRANSP)*/
+// SDL_SetRenderDrawColor(renderer, 0xff, 0, 0, 0xff);
+// SDL_Rect r;
+// r.x = 0; r.y = 0; r.w = MONITOR_HOR_RES; r.w = MONITOR_VER_RES;
+// SDL_RenderDrawRect(renderer, &r);
+ /*Update the renderer with the texture containing the rendered image*/
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ }
+
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+#if USE_MOUSE != 0
+ mouse_handler(&event);
+#endif
+ if ((&event)->type == SDL_WINDOWEVENT) {
+ switch ((&event)->window.event) {
+#if SDL_VERSION_ATLEAST(2, 0, 5)
+ case SDL_WINDOWEVENT_TAKE_FOCUS:
+#endif
+ case SDL_WINDOWEVENT_EXPOSED:
+
+ SDL_UpdateTexture(texture, NULL, tft_fb,
+ MONITOR_HOR_RES * sizeof(uint32_t));
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /*Sleep some time*/
+ SDL_Delay(SDL_REFR_PERIOD);
+
+}
+int quit_filter(void * userdata, SDL_Event * event)
+{
+ (void) userdata;
+
+ if (event->type == SDL_QUIT) {
+ sdl_quit_qry = true;
+ }
+
+ return 1;
+}
+
+void monitor_sdl_clean_up(void)
+{
+ SDL_DestroyTexture(texture);
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+}
+
+void monitor_sdl_init(void)
+{
+ /*Initialize the SDL*/
+ SDL_Init(SDL_INIT_VIDEO);
+
+ SDL_SetEventFilter(quit_filter, NULL);
+
+ window = SDL_CreateWindow("TFT Simulator", SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ MONITOR_HOR_RES * MONITOR_ZOOM, MONITOR_VER_RES * MONITOR_ZOOM, 0); /*last param. SDL_WINDOW_BORDERLESS to hide borders*/
+
+ renderer = SDL_CreateRenderer(window, -1, 0);
+ texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STATIC, MONITOR_HOR_RES, MONITOR_VER_RES);
+ SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
+
+ /*Initialize the frame buffer to gray (77 is an empirical value) */
+ memset(tft_fb, 0x44, MONITOR_HOR_RES * MONITOR_VER_RES * sizeof(uint32_t));
+ SDL_UpdateTexture(texture, NULL, tft_fb,
+ MONITOR_HOR_RES * sizeof(uint32_t));
+ sdl_refr_qry = true;
+ sdl_inited = true;
+}
+
+void display_SDL_init()
+{
+ SDL_CreateThread(monitor_sdl_refr_thread, "sdl_refr", NULL);
+ while (sdl_inited == false)
+ ; /*Wait until 'sdl_refr' initializes the SDL*/
+}
+
diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/lv_conf.h b/samples/littlevgl/vgl-native-ui-app/lv-drivers/lv_conf.h
new file mode 100644
index 0000000000..76533a8e1b
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/lv_conf.h
@@ -0,0 +1,389 @@
+/**
+ * @file lv_conf.h
+ *
+ */
+
+#if 1 /*Set it to "1" to enable content*/
+
+#ifndef LV_CONF_H
+#define LV_CONF_H
+/*===================
+ Dynamic memory
+ *===================*/
+
+/* Memory size which will be used by the library
+ * to store the graphical objects and other data */
+#define LV_MEM_CUSTOM 1 /*1: use custom malloc/free, 0: use the built-in lv_mem_alloc/lv_mem_free*/
+#if LV_MEM_CUSTOM == 0
+# define LV_MEM_SIZE (64U * 1024U) /*Size memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
+# define LV_MEM_ATTR /*Complier prefix for big array declaration*/
+# define LV_MEM_ADR 0 /*Set an address for memory pool instead of allocation it as an array. Can be in external SRAM too.*/
+# define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/
+#else /*LV_MEM_CUSTOM*/
+# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/
+# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/
+# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/
+#endif /*LV_MEM_CUSTOM*/
+
+/* Garbage Collector settings
+ * Used if lvgl is binded to higher language and the memory is managed by that language */
+#define LV_ENABLE_GC 0
+#if LV_ENABLE_GC != 0
+# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/
+# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/
+# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
+#endif /* LV_ENABLE_GC */
+
+/*===================
+ Graphical settings
+ *===================*/
+
+/* Horizontal and vertical resolution of the library.*/
+#define LV_HOR_RES (320)
+#define LV_VER_RES (240)
+
+/* Dot Per Inch: used to initialize default sizes. E.g. a button with width = LV_DPI / 2 -> half inch wide
+ * (Not so important, you can adjust it to modify default sizes and spaces)*/
+#define LV_DPI 100
+
+/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
+#define LV_ANTIALIAS 0 /*1: Enable anti-aliasing*/
+
+/*Screen refresh period in milliseconds*/
+#define LV_REFR_PERIOD 30
+
+/*-----------------
+ * VDB settings
+ *----------------*/
+
+/* VDB (Virtual Display Buffer) is an internal graphics buffer.
+ * The GUI will be drawn into this buffer first and then
+ * the buffer will be passed to your `disp_drv.disp_flush` function to
+ * copy it to your frame buffer.
+ * VDB is required for: buffered drawing, opacity, anti-aliasing and shadows
+ * Learn more: https://docs.littlevgl.com/#Drawing*/
+
+/* Size of the VDB in pixels. Typical size: ~1/10 screen. Must be >= LV_HOR_RES
+ * Setting it to 0 will disable VDB and `disp_drv.disp_fill` and `disp_drv.disp_map` functions
+ * will be called to draw to the frame buffer directly*/
+#define LV_VDB_SIZE ((LV_VER_RES * LV_HOR_RES) / 10)
+
+/* Bit-per-pixel of VDB. Useful for monochrome or non-standard color format displays.
+ * Special formats are handled with `disp_drv.vdb_wr`)*/
+#define LV_VDB_PX_BPP LV_COLOR_SIZE /*LV_COLOR_SIZE comes from LV_COLOR_DEPTH below to set 8, 16 or 32 bit pixel size automatically */
+
+/* Place VDB to a specific address (e.g. in external RAM)
+ * 0: allocate automatically into RAM
+ * LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/
+#define LV_VDB_ADR 0
+
+/* Use two Virtual Display buffers (VDB) to parallelize rendering and flushing
+ * The flushing should use DMA to write the frame buffer in the background */
+#define LV_VDB_DOUBLE 0
+
+/* Place VDB2 to a specific address (e.g. in external RAM)
+ * 0: allocate automatically into RAM
+ * LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/
+#define LV_VDB2_ADR 0
+
+/* Using true double buffering in `disp_drv.disp_flush` you will always get the image of the whole screen.
+ * Your only task is to set the rendered image (`color_p` parameter) as frame buffer address or send it to your display.
+ * The best if you do in the blank period of you display to avoid tearing effect.
+ * Requires:
+ * - LV_VDB_SIZE = LV_HOR_RES * LV_VER_RES
+ * - LV_VDB_DOUBLE = 1
+ */
+#define LV_VDB_TRUE_DOUBLE_BUFFERED 0
+
+/*=================
+ Misc. setting
+ *=================*/
+
+/*Input device settings*/
+#define LV_INDEV_READ_PERIOD 50 /*Input device read period in milliseconds*/
+#define LV_INDEV_POINT_MARKER 0 /*Mark the pressed points (required: USE_LV_REAL_DRAW = 1)*/
+#define LV_INDEV_DRAG_LIMIT 10 /*Drag threshold in pixels */
+#define LV_INDEV_DRAG_THROW 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */
+#define LV_INDEV_LONG_PRESS_TIME 400 /*Long press time in milliseconds*/
+#define LV_INDEV_LONG_PRESS_REP_TIME 100 /*Repeated trigger period in long press [ms] */
+
+/*Color settings*/
+#define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/
+#define LV_COLOR_16_SWAP 0 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
+#define LV_COLOR_SCREEN_TRANSP 0 /*1: Enable screen transparency. Useful for OSD or other overlapping GUIs. Requires ARGB8888 colors*/
+#define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/
+
+/*Text settings*/
+#define LV_TXT_UTF8 1 /*Enable UTF-8 coded Unicode character usage */
+#define LV_TXT_BREAK_CHARS " ,.;:-_" /*Can break texts on these chars*/
+#define LV_TXT_LINE_BREAK_LONG_LEN 12 /* If a character is at least this long, will break wherever "prettiest" */
+#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 /* Minimum number of characters of a word to put on a line before a break */
+#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 1 /* Minimum number of characters of a word to put on a line after a break */
+
+/*Feature usage*/
+#define USE_LV_ANIMATION 1 /*1: Enable all animations*/
+#define USE_LV_SHADOW 1 /*1: Enable shadows*/
+#define USE_LV_GROUP 1 /*1: Enable object groups (for keyboards)*/
+#define USE_LV_GPU 0 /*1: Enable GPU interface*/
+#define USE_LV_REAL_DRAW 1 /*1: Enable function which draw directly to the frame buffer instead of VDB (required if LV_VDB_SIZE = 0)*/
+#define USE_LV_FILESYSTEM 0 /*1: Enable file system (might be required for images*/
+#define USE_LV_MULTI_LANG 0 /* Number of languages for labels to store (0: to disable this feature)*/
+
+/*Compiler settings*/
+#define LV_ATTRIBUTE_TICK_INC /* Define a custom attribute to `lv_tick_inc` function */
+#define LV_ATTRIBUTE_TASK_HANDLER /* Define a custom attribute to `lv_task_handler` function */
+#define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/
+#define LV_COMPILER_NON_CONST_INIT_SUPPORTED 1 /* 1: Initialization with non constant values are supported */
+
+/*HAL settings*/
+#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */
+#if LV_TICK_CUSTOM == 1
+#define LV_TICK_CUSTOM_INCLUDE "system_header.h" /*Header for the sys time function*/
+#define LV_TICK_CUSTOM_SYS_TIME_EXPR (time_get_ms()) /*Expression evaluating to current systime in ms*/
+#endif /*LV_TICK_CUSTOM*/
+
+/*Log settings*/
+#define USE_LV_LOG 1 /*Enable/disable the log module*/
+#if USE_LV_LOG
+/* How important log should be added:
+ * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
+ * LV_LOG_LEVEL_INFO Log important events
+ * LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't caused problem
+ * LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
+ */
+# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
+/* 1: Print the log with 'printf'; 0: user need to register a callback*/
+
+# define LV_LOG_PRINTF 0
+#endif /*USE_LV_LOG*/
+
+/*================
+ * THEME USAGE
+ *================*/
+#define LV_THEME_LIVE_UPDATE 1 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/
+
+#define USE_LV_THEME_TEMPL 0 /*Just for test*/
+#define USE_LV_THEME_DEFAULT 1 /*Built mainly from the built-in styles. Consumes very few RAM*/
+#define USE_LV_THEME_ALIEN 0 /*Dark futuristic theme*/
+#define USE_LV_THEME_NIGHT 0 /*Dark elegant theme*/
+#define USE_LV_THEME_MONO 0 /*Mono color theme for monochrome displays*/
+#define USE_LV_THEME_MATERIAL 0 /*Flat theme with bold colors and light shadows*/
+#define USE_LV_THEME_ZEN 0 /*Peaceful, mainly light theme */
+#define USE_LV_THEME_NEMO 0 /*Water-like theme based on the movie "Finding Nemo"*/
+
+/*==================
+ * FONT USAGE
+ *===================*/
+
+/* More info about fonts: https://docs.littlevgl.com/#Fonts
+ * To enable a built-in font use 1,2,4 or 8 values
+ * which will determine the bit-per-pixel. Higher value means smoother fonts */
+#define USE_LV_FONT_DEJAVU_10 0
+#define USE_LV_FONT_DEJAVU_10_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_10_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_10 0
+
+#define USE_LV_FONT_DEJAVU_20 4
+#define USE_LV_FONT_DEJAVU_20_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_20_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_20 0
+
+#define USE_LV_FONT_DEJAVU_30 0
+#define USE_LV_FONT_DEJAVU_30_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_30_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_30 0
+
+#define USE_LV_FONT_DEJAVU_40 0
+#define USE_LV_FONT_DEJAVU_40_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_40_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_40 0
+
+#define USE_LV_FONT_MONOSPACE_8 1
+
+/* Optionally declare your custom fonts here.
+ * You can use these fonts as default font too
+ * and they will be available globally. E.g.
+ * #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \
+ * LV_FONT_DECLARE(my_font_2) \
+ */
+#define LV_FONT_CUSTOM_DECLARE
+
+#define LV_FONT_DEFAULT &lv_font_dejavu_20 /*Always set a default font from the built-in fonts*/
+
+/*===================
+ * LV_OBJ SETTINGS
+ *==================*/
+#define LV_OBJ_FREE_NUM_TYPE uint32_t /*Type of free number attribute (comment out disable free number)*/
+#define LV_OBJ_FREE_PTR 1 /*Enable the free pointer attribute*/
+#define LV_OBJ_REALIGN 1 /*Enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/
+
+/*==================
+ * LV OBJ X USAGE
+ *================*/
+/*
+ * Documentation of the object types: https://docs.littlevgl.com/#Object-types
+ */
+
+/*****************
+ * Simple object
+ *****************/
+
+/*Label (dependencies: -*/
+#define USE_LV_LABEL 1
+#if USE_LV_LABEL != 0
+# define LV_LABEL_SCROLL_SPEED 25 /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_SCROLL/ROLL' mode*/
+#endif
+
+/*Image (dependencies: lv_label*/
+#define USE_LV_IMG 1
+#if USE_LV_IMG != 0
+# define LV_IMG_CF_INDEXED 1 /*Enable indexed (palette) images*/
+# define LV_IMG_CF_ALPHA 1 /*Enable alpha indexed images*/
+#endif
+
+/*Line (dependencies: -*/
+#define USE_LV_LINE 1
+
+/*Arc (dependencies: -)*/
+#define USE_LV_ARC 1
+
+/*******************
+ * Container objects
+ *******************/
+
+/*Container (dependencies: -*/
+#define USE_LV_CONT 1
+
+/*Page (dependencies: lv_cont)*/
+#define USE_LV_PAGE 1
+
+/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/
+#define USE_LV_WIN 1
+
+/*Tab (dependencies: lv_page, lv_btnm)*/
+#define USE_LV_TABVIEW 1
+# if USE_LV_TABVIEW != 0
+# define LV_TABVIEW_ANIM_TIME 300 /*Time of slide animation [ms] (0: no animation)*/
+#endif
+
+/*Tileview (dependencies: lv_page) */
+#define USE_LV_TILEVIEW 1
+#if USE_LV_TILEVIEW
+# define LV_TILEVIEW_ANIM_TIME 300 /*Time of slide animation [ms] (0: no animation)*/
+#endif
+
+/*************************
+ * Data visualizer objects
+ *************************/
+
+/*Bar (dependencies: -)*/
+#define USE_LV_BAR 1
+
+/*Line meter (dependencies: *;)*/
+#define USE_LV_LMETER 1
+
+/*Gauge (dependencies:lv_bar, lv_lmeter)*/
+#define USE_LV_GAUGE 1
+
+/*Chart (dependencies: -)*/
+#define USE_LV_CHART 1
+
+/*Table (dependencies: lv_label)*/
+#define USE_LV_TABLE 1
+#if USE_LV_TABLE
+# define LV_TABLE_COL_MAX 12
+#endif
+
+/*LED (dependencies: -)*/
+#define USE_LV_LED 1
+
+/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/
+#define USE_LV_MBOX 1
+
+/*Text area (dependencies: lv_label, lv_page)*/
+#define USE_LV_TA 1
+#if USE_LV_TA != 0
+# define LV_TA_CURSOR_BLINK_TIME 400 /*ms*/
+# define LV_TA_PWD_SHOW_TIME 1500 /*ms*/
+#endif
+
+/*Spinbox (dependencies: lv_ta)*/
+#define USE_LV_SPINBOX 1
+
+/*Calendar (dependencies: -)*/
+#define USE_LV_CALENDAR 1
+
+/*Preload (dependencies: lv_arc)*/
+#define USE_LV_PRELOAD 1
+#if USE_LV_PRELOAD != 0
+# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/
+# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/
+# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC
+#endif
+
+/*Canvas (dependencies: lv_img)*/
+#define USE_LV_CANVAS 1
+/*************************
+ * User input objects
+ *************************/
+
+/*Button (dependencies: lv_cont*/
+#define USE_LV_BTN 1
+#if USE_LV_BTN != 0
+# define LV_BTN_INK_EFFECT 1 /*Enable button-state animations - draw a circle on click (dependencies: USE_LV_ANIMATION)*/
+#endif
+
+/*Image Button (dependencies: lv_btn*/
+#define USE_LV_IMGBTN 1
+#if USE_LV_IMGBTN
+# define LV_IMGBTN_TILED 0 /*1: The imgbtn requires left, mid and right parts and the width can be set freely*/
+#endif
+
+/*Button matrix (dependencies: -)*/
+#define USE_LV_BTNM 1
+
+/*Keyboard (dependencies: lv_btnm)*/
+#define USE_LV_KB 1
+
+/*Check box (dependencies: lv_btn, lv_label)*/
+#define USE_LV_CB 1
+
+/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/
+#define USE_LV_LIST 1
+#if USE_LV_LIST != 0
+# define LV_LIST_FOCUS_TIME 100 /*Default animation time of focusing to a list element [ms] (0: no animation) */
+#endif
+
+/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
+#define USE_LV_DDLIST 1
+#if USE_LV_DDLIST != 0
+# define LV_DDLIST_ANIM_TIME 200 /*Open and close default animation time [ms] (0: no animation)*/
+#endif
+
+/*Roller (dependencies: lv_ddlist)*/
+#define USE_LV_ROLLER 1
+#if USE_LV_ROLLER != 0
+# define LV_ROLLER_ANIM_TIME 200 /*Focus animation time [ms] (0: no animation)*/
+#endif
+
+/*Slider (dependencies: lv_bar)*/
+#define USE_LV_SLIDER 1
+
+/*Switch (dependencies: lv_slider)*/
+#define USE_LV_SW 1
+
+/*************************
+ * Non-user section
+ *************************/
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/*--END OF LV_CONF_H--*/
+
+/*Be sure every define has a default value*/
+#include "lvgl/lv_conf_checker.h"
+
+#endif /*LV_CONF_H*/
+
+#endif /*End of "Content enable"*/
diff --git a/samples/littlevgl/vgl-native-ui-app/lv-drivers/system_header.h b/samples/littlevgl/vgl-native-ui-app/lv-drivers/system_header.h
new file mode 100644
index 0000000000..9c8b1d238d
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/lv-drivers/system_header.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+int time_get_ms();
diff --git a/samples/littlevgl/vgl-native-ui-app/main.c b/samples/littlevgl/vgl-native-ui-app/main.c
new file mode 100644
index 0000000000..59d0e6b6dc
--- /dev/null
+++ b/samples/littlevgl/vgl-native-ui-app/main.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file main
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include
+#include
+#include "lvgl/lvgl.h"
+#include "display_indev.h"
+#include
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static void hal_init(void);
+//static int tick_thread(void * data);
+//static void memory_monitor(void * param);
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+uint32_t count = 0;
+char count_str[11] = { 0 };
+lv_obj_t *hello_world_label;
+lv_obj_t *count_label;
+lv_obj_t * btn1;
+
+lv_obj_t * label_count1;
+int label_count1_value = 0;
+char label_count1_str[11] = { 0 };
+static lv_res_t btn_rel_action(lv_obj_t * btn)
+{
+ label_count1_value++;
+ sprintf(label_count1_str, "%d", label_count1_value);
+ lv_label_set_text(label_count1, label_count1_str);
+ return LV_RES_OK;
+}
+
+
+int main()
+{
+ void display_SDL_init();
+ display_SDL_init();
+
+ /*Initialize LittlevGL*/
+ lv_init();
+
+ /*Initialize the HAL (display, input devices, tick) for LittlevGL*/
+ hal_init();
+
+ hello_world_label = lv_label_create(lv_scr_act(), NULL);
+ lv_label_set_text(hello_world_label, "Hello world!");
+ lv_obj_align(hello_world_label, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
+
+ count_label = lv_label_create(lv_scr_act(), NULL);
+ lv_obj_align(count_label, NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
+
+ btn1 = lv_btn_create(lv_scr_act(), NULL); /*Create a button on the currently loaded screen*/
+ lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, btn_rel_action); /*Set function to be called when the button is released*/
+ lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 20); /*Align below the label*/
+
+ /*Create a label on the button*/
+ lv_obj_t * btn_label = lv_label_create(btn1, NULL);
+ lv_label_set_text(btn_label, "Click ++");
+
+ label_count1 = lv_label_create(lv_scr_act(), NULL);
+ lv_label_set_text(label_count1, "0");
+ lv_obj_align(label_count1, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
+
+ while(1) {
+ /* Periodically call the lv_task handler.
+ * It could be done in a timer interrupt or an OS task too.*/
+ if ((count % 100) == 0) {
+ sprintf(count_str, "%d", count/ 100);
+ lv_label_set_text(count_label, count_str);
+ }
+ lv_task_handler();
+ ++count;
+ usleep(10 * 1000); /*Just to let the system breath*/
+ }
+
+ return 0;
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+/**
+ * Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library
+ */
+void display_flush_wrapper(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ display_flush(x1, y1, x2, y2, color_p);
+ lv_flush_ready();
+}
+void display_vdb_write_wrapper(uint8_t *buf, lv_coord_t buf_w, lv_coord_t x,
+ lv_coord_t y, lv_color_t color, lv_opa_t opa)
+{
+ display_vdb_write(buf, buf_w, x, y, &color, opa);
+}
+extern void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color_p);
+extern void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p);
+static void hal_init(void)
+{
+ /* Add a display*/
+ lv_disp_drv_t disp_drv;
+ lv_disp_drv_init(&disp_drv); /*Basic initialization*/
+ disp_drv.disp_flush = display_flush_wrapper; /*Used when `LV_VDB_SIZE != 0` in lv_conf.h (buffered drawing)*/
+ disp_drv.disp_fill = display_fill; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
+ disp_drv.disp_map = display_map; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
+#if LV_VDB_SIZE != 0
+ disp_drv.vdb_wr = display_vdb_write_wrapper;
+#endif
+ lv_disp_drv_register(&disp_drv);
+
+ /* Add the mouse as input device
+ * Use the 'mouse' driver which reads the PC's mouse*/
+// mouse_init();
+ lv_indev_drv_t indev_drv;
+ lv_indev_drv_init(&indev_drv); /*Basic initialization*/
+ indev_drv.type = LV_INDEV_TYPE_POINTER;
+ indev_drv.read = display_input_read; /*This function will be called periodically (by the library) to get the mouse position and state*/
+ lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv);
+
+}
+
diff --git a/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt
new file mode 100644
index 0000000000..719f866b40
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/CMakeLists.txt
@@ -0,0 +1,93 @@
+cmake_minimum_required (VERSION 2.8)
+
+project (vgl_wasm_runtime)
+
+set (TARGET_PLATFORM "linux")
+
+# Reset default linker flags
+set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+# Enable repl mode if want to test spec cases
+# add_definitions(-DWASM_ENABLE_REPL)
+
+if (NOT ("$ENV{VALGRIND}" STREQUAL "YES"))
+ add_definitions(-DNVALGRIND)
+endif ()
+
+# Currently build as 32-bit by default.
+set (BUILD_AS_64BIT_SUPPORT "NO")
+
+if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+if (${BUILD_AS_64BIT_SUPPORT} STREQUAL "YES")
+ # Add -fPIC flag if build as 64-bit
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+else ()
+ add_definitions (-m32)
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
+ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32")
+endif ()
+endif ()
+
+if (NOT CMAKE_BUILD_TYPE)
+SET(CMAKE_BUILD_TYPE Debug)
+endif (NOT CMAKE_BUILD_TYPE)
+message ("CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE})
+
+if (NOT PLATFORM)
+SET(PLATFORM linux)
+endif (NOT PLATFORM)
+message ("PLATFORM = " ${PLATFORM})
+
+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic")
+
+set(REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..)
+set(WASM_DIR ${REPO_ROOT_DIR}/core/iwasm)
+set(APP_MGR_DIR ${REPO_ROOT_DIR}/core/app-mgr)
+set(SHARED_DIR ${REPO_ROOT_DIR}/core/shared-lib)
+
+
+enable_language (ASM)
+
+include (${WASM_DIR}/runtime/platform/${TARGET_PLATFORM}/platform.cmake)
+include (${WASM_DIR}/runtime/utils/utils.cmake)
+include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake)
+include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake)
+include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake)
+include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake)
+include (${WASM_DIR}/lib/native-interface/native_interface.cmake)
+include (${APP_MGR_DIR}/app-manager/app_mgr.cmake)
+include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake)
+include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake)
+include (${SHARED_DIR}/utils/shared_utils.cmake)
+include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
+include (${SHARED_DIR}/coap/lib_coap.cmake)
+
+
+include_directories(${SHARED_DIR}/include ${CMAKE_CURRENT_LIST_DIR}/src)
+
+add_definitions (-DWASM_ENABLE_BASE_LIB)
+add_definitions (-Dattr_container_malloc=bh_malloc)
+add_definitions (-Dattr_container_free=bh_free)
+
+add_library (vmlib
+ ${WASM_PLATFORM_LIB_SOURCE}
+ ${WASM_UTILS_LIB_SOURCE}
+ ${VMCORE_LIB_SOURCE}
+ ${WASM_LIBC_SOURCE}
+ ${APP_MGR_SOURCE}
+ ${WASM_LIB_BASE_SOURCE}
+ ${WASM_LIB_EXT_SOURCE}
+ ${WASM_LIB_SENSOR_SOURCE}
+ ${PLATFORM_SHARED_SOURCE}
+ ${UTILS_SHARED_SOURCE}
+ ${MEM_ALLOC_SHARED_SOURCE}
+ ${NATIVE_INTERFACE_SOURCE}
+ )
+
+add_executable (vgl_wasm_runtime src/platform/${TARGET_PLATFORM}/main.c src/platform/${TARGET_PLATFORM}/iwasm_main.c src/ext_lib_export.c src/platform/${TARGET_PLATFORM}/display_indev.c src/platform/${TARGET_PLATFORM}/mouse.c)
+
+target_link_libraries (vgl_wasm_runtime vmlib -lm -ldl -lpthread -lSDL2)
+
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h b/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h
new file mode 100644
index 0000000000..154071e362
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/display_indev.h
@@ -0,0 +1,74 @@
+#ifndef DISPLAY_INDEV_H_
+#define DISPLAY_INDEV_H_
+#include
+#include "bh_platform.h"
+#include
+#include
+
+#define USE_MOUSE 1
+typedef union {
+ struct {
+ uint8_t blue;
+ uint8_t green;
+ uint8_t red;
+ uint8_t alpha;
+ };
+ uint32_t full;
+} lv_color32_t;
+
+typedef lv_color32_t lv_color_t;
+typedef uint8_t lv_indev_state_t;
+typedef int16_t lv_coord_t;
+typedef uint8_t lv_opa_t;
+typedef struct {
+ lv_coord_t x;
+ lv_coord_t y;
+} lv_point_t;
+
+typedef struct {
+ union {
+ lv_point_t point; /*For LV_INDEV_TYPE_POINTER the currently pressed point*/
+ uint32_t key; /*For LV_INDEV_TYPE_KEYPAD the currently pressed key*/
+ uint32_t btn; /*For LV_INDEV_TYPE_BUTTON the currently pressed button*/
+ int16_t enc_diff; /*For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/
+ };
+ void *user_data; /*'lv_indev_drv_t.priv' for this driver*/
+ lv_indev_state_t state; /*LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/
+} lv_indev_data_t;
+
+enum {
+ LV_INDEV_STATE_REL = 0, LV_INDEV_STATE_PR
+};
+enum {
+ LV_OPA_TRANSP = 0,
+ LV_OPA_0 = 0,
+ LV_OPA_10 = 25,
+ LV_OPA_20 = 51,
+ LV_OPA_30 = 76,
+ LV_OPA_40 = 102,
+ LV_OPA_50 = 127,
+ LV_OPA_60 = 153,
+ LV_OPA_70 = 178,
+ LV_OPA_80 = 204,
+ LV_OPA_90 = 229,
+ LV_OPA_100 = 255,
+ LV_OPA_COVER = 255,
+};
+extern void display_init(void);
+extern void display_deinit(void);
+extern int time_get_ms();
+extern bool touchscreen_read(lv_indev_data_t * data);
+
+extern void xpt2046_init(void);
+extern void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ int32 color_p_offset);
+extern void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color_p);
+extern void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p);
+extern bool display_input_read(int32 data_offset);
+void display_vdb_write(int32 buf_offset, lv_coord_t buf_w, lv_coord_t x,
+ lv_coord_t y, int32 color_p_offset, lv_opa_t opa);
+extern bool mouse_read(lv_indev_data_t * data);
+#endif
+
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/ext_lib_export.c b/samples/littlevgl/vgl-wasm-runtime/src/ext_lib_export.c
new file mode 100644
index 0000000000..8927493a8f
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/ext_lib_export.c
@@ -0,0 +1,14 @@
+#include "lib_export.h"
+#include "native_interface.h"
+#include "display_indev.h"
+static NativeSymbol extended_native_symbol_defs[] = {
+#include "runtime_sensor.inl"
+ EXPORT_WASM_API(display_init),
+ EXPORT_WASM_API(display_input_read),
+ EXPORT_WASM_API(display_flush),
+ EXPORT_WASM_API(display_fill),
+ EXPORT_WASM_API(display_vdb_write),
+ EXPORT_WASM_API(display_map),
+ EXPORT_WASM_API(time_get_ms), };
+
+#include "ext_lib_export.h"
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c
new file mode 100644
index 0000000000..6aeaec19c2
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/display_indev.c
@@ -0,0 +1,341 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include "display_indev.h"
+#include "SDL2/SDL.h"
+#include "sys/time.h"
+#include "wasm_export.h"
+
+#define MONITOR_HOR_RES 320
+#define MONITOR_VER_RES 240
+#ifndef MONITOR_ZOOM
+#define MONITOR_ZOOM 1
+#endif
+#define SDL_REFR_PERIOD 50
+void monitor_sdl_init(void);
+void monitor_sdl_refr_core(void);
+void monitor_sdl_clean_up(void);
+
+static uint32_t tft_fb[MONITOR_HOR_RES * MONITOR_VER_RES];
+
+
+
+int time_get_ms()
+{
+ static struct timeval tv;
+ gettimeofday(&tv, NULL);
+ long long time_in_mill = (tv.tv_sec) * 1000 + (tv.tv_usec) / 1000;
+
+ return (int) time_in_mill;
+}
+
+SDL_Window * window;
+SDL_Renderer * renderer;
+SDL_Texture * texture;
+static volatile bool sdl_inited = false;
+static volatile bool sdl_refr_qry = false;
+static volatile bool sdl_quit_qry = false;
+
+void monitor_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ /*Return if the area is out the screen*/
+ if (x2 < 0 || y2 < 0 || x1 > MONITOR_HOR_RES - 1
+ || y1 > MONITOR_VER_RES - 1) {
+ return;
+ }
+
+ int32_t y;
+ uint32_t w = x2 - x1 + 1;
+ for (y = y1; y <= y2; y++) {
+ memcpy(&tft_fb[y * MONITOR_HOR_RES + x1], color_p,
+ w * sizeof(lv_color_t));
+
+ color_p += w;
+ }
+ sdl_refr_qry = true;
+
+ /*IMPORTANT! It must be called to tell the system the flush is ready*/
+
+}
+
+/**
+ * Fill out the marked area with a color
+ * @param x1 left coordinate
+ * @param y1 top coordinate
+ * @param x2 right coordinate
+ * @param y2 bottom coordinate
+ * @param color fill color
+ */
+void monitor_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color)
+{
+ /*Return if the area is out the screen*/
+ if (x2 < 0)
+ return;
+ if (y2 < 0)
+ return;
+ if (x1 > MONITOR_HOR_RES - 1)
+ return;
+ if (y1 > MONITOR_VER_RES - 1)
+ return;
+
+ /*Truncate the area to the screen*/
+ int32_t act_x1 = x1 < 0 ? 0 : x1;
+ int32_t act_y1 = y1 < 0 ? 0 : y1;
+ int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
+ int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
+
+ int32_t x;
+ int32_t y;
+ uint32_t color32 = color.full; //lv_color_to32(color);
+
+ for (x = act_x1; x <= act_x2; x++) {
+ for (y = act_y1; y <= act_y2; y++) {
+ tft_fb[y * MONITOR_HOR_RES + x] = color32;
+ }
+ }
+
+ sdl_refr_qry = true;
+}
+
+/**
+ * Put a color map to the marked area
+ * @param x1 left coordinate
+ * @param y1 top coordinate
+ * @param x2 right coordinate
+ * @param y2 bottom coordinate
+ * @param color_p an array of colors
+ */
+void monitor_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ /*Return if the area is out the screen*/
+ if (x2 < 0)
+ return;
+ if (y2 < 0)
+ return;
+ if (x1 > MONITOR_HOR_RES - 1)
+ return;
+ if (y1 > MONITOR_VER_RES - 1)
+ return;
+
+ /*Truncate the area to the screen*/
+ int32_t act_x1 = x1 < 0 ? 0 : x1;
+ int32_t act_y1 = y1 < 0 ? 0 : y1;
+ int32_t act_x2 = x2 > MONITOR_HOR_RES - 1 ? MONITOR_HOR_RES - 1 : x2;
+ int32_t act_y2 = y2 > MONITOR_VER_RES - 1 ? MONITOR_VER_RES - 1 : y2;
+
+ int32_t x;
+ int32_t y;
+
+ for (y = act_y1; y <= act_y2; y++) {
+ for (x = act_x1; x <= act_x2; x++) {
+ tft_fb[y * MONITOR_HOR_RES + x] = color_p->full; //lv_color_to32(*color_p);
+ color_p++;
+ }
+
+ color_p += x2 - act_x2;
+ }
+
+ sdl_refr_qry = true;
+}
+
+
+void display_init(void)
+{
+}
+
+void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ int32 color_p_offset)
+{
+
+ wasm_module_inst_t module_inst = wasm_runtime_get_current_module_inst();
+ if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
+ return;
+ lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst,
+ color_p_offset);
+
+ monitor_flush(x1, y1, x2, y2, color_p);
+}
+void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color_p)
+{
+ monitor_fill(x1, y1, x2, y2, color_p);
+}
+void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ monitor_map(x1, y1, x2, y2, color_p);
+}
+
+bool display_input_read(int32 data_p_offset)
+{
+ wasm_module_inst_t module_inst = wasm_runtime_get_current_module_inst();
+ if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1))
+ return false;
+ lv_indev_data_t * data = wasm_runtime_addr_app_to_native(module_inst,
+ data_p_offset);
+ return mouse_read(data);
+}
+
+void display_deinit(void)
+{
+
+}
+
+void display_vdb_write(int32 buf_offset, lv_coord_t buf_w, lv_coord_t x,
+ lv_coord_t y, int32 color_p_offset, lv_opa_t opa)
+{
+ wasm_module_inst_t module_inst = wasm_runtime_get_current_module_inst();
+ if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
+ return;
+ lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst,
+ color_p_offset);
+
+ void *buf = wasm_runtime_addr_app_to_native(module_inst, buf_offset);
+
+ unsigned char *buf_xy = buf + 4 * x + 4 * y * buf_w;
+ lv_color_t * temp = (lv_color_t *) buf_xy;
+ *temp = *color;
+ /*
+ if (opa != LV_OPA_COVER) {
+ lv_color_t mix_color;
+
+ mix_color.red = *buf_xy;
+ mix_color.green = *(buf_xy+1);
+ mix_color.blue = *(buf_xy+2);
+ color = lv_color_mix(color, mix_color, opa);
+ }
+ */
+ /*
+ *buf_xy = color->red;
+ *(buf_xy + 1) = color->green;
+ *(buf_xy + 2) = color->blue;
+ */
+}
+
+int monitor_sdl_refr_thread(void * param)
+{
+ (void) param;
+
+ /*If not OSX initialize SDL in the Thread*/
+ monitor_sdl_init();
+ /*Run until quit event not arrives*/
+ while (sdl_quit_qry == false) {
+ /*Refresh handling*/
+ monitor_sdl_refr_core();
+ }
+
+ monitor_sdl_clean_up();
+ exit(0);
+
+ return 0;
+}
+extern void mouse_handler(SDL_Event *event);
+void monitor_sdl_refr_core(void)
+{
+ if (sdl_refr_qry != false) {
+ sdl_refr_qry = false;
+
+ SDL_UpdateTexture(texture, NULL, tft_fb,
+ MONITOR_HOR_RES * sizeof(uint32_t));
+ SDL_RenderClear(renderer);
+ /*Update the renderer with the texture containing the rendered image*/
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ }
+
+ SDL_Event event;
+ while (SDL_PollEvent(&event)) {
+
+ mouse_handler(&event);
+
+ if ((&event)->type == SDL_WINDOWEVENT) {
+ switch ((&event)->window.event) {
+#if SDL_VERSION_ATLEAST(2, 0, 5)
+ case SDL_WINDOWEVENT_TAKE_FOCUS:
+#endif
+ case SDL_WINDOWEVENT_EXPOSED:
+
+ SDL_UpdateTexture(texture, NULL, tft_fb,
+ MONITOR_HOR_RES * sizeof(uint32_t));
+ SDL_RenderClear(renderer);
+ SDL_RenderCopy(renderer, texture, NULL, NULL);
+ SDL_RenderPresent(renderer);
+ break;
+ default:
+ break;
+ }
+ }
+ }
+
+ /*Sleep some time*/
+ SDL_Delay(SDL_REFR_PERIOD);
+
+}
+int quit_filter(void * userdata, SDL_Event * event)
+{
+ (void) userdata;
+
+ if (event->type == SDL_QUIT) {
+ sdl_quit_qry = true;
+ }
+
+ return 1;
+}
+
+void monitor_sdl_clean_up(void)
+{
+ SDL_DestroyTexture(texture);
+ SDL_DestroyRenderer(renderer);
+ SDL_DestroyWindow(window);
+ SDL_Quit();
+}
+
+void monitor_sdl_init(void)
+{
+ /*Initialize the SDL*/
+ SDL_Init(SDL_INIT_VIDEO);
+
+ SDL_SetEventFilter(quit_filter, NULL);
+
+ window = SDL_CreateWindow("TFT Simulator", SDL_WINDOWPOS_UNDEFINED,
+ SDL_WINDOWPOS_UNDEFINED,
+ MONITOR_HOR_RES * MONITOR_ZOOM, MONITOR_VER_RES * MONITOR_ZOOM, 0); /*last param. SDL_WINDOW_BORDERLESS to hide borders*/
+
+ renderer = SDL_CreateRenderer(window, -1, 0);
+ texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
+ SDL_TEXTUREACCESS_STATIC, MONITOR_HOR_RES, MONITOR_VER_RES);
+ SDL_SetTextureBlendMode(texture, SDL_BLENDMODE_BLEND);
+
+ /*Initialize the frame buffer to gray (77 is an empirical value) */
+ memset(tft_fb, 0x44, MONITOR_HOR_RES * MONITOR_VER_RES * sizeof(uint32_t));
+ SDL_UpdateTexture(texture, NULL, tft_fb,
+ MONITOR_HOR_RES * sizeof(uint32_t));
+ sdl_refr_qry = true;
+ sdl_inited = true;
+}
+
+void display_SDL_init()
+{
+ SDL_CreateThread(monitor_sdl_refr_thread, "sdl_refr", NULL);
+ while (sdl_inited == false)
+ ; /*Wait until 'sdl_refr' initializes the SDL*/
+}
+
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c
new file mode 100644
index 0000000000..cbb894100e
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/iwasm_main.c
@@ -0,0 +1,467 @@
+
+#ifndef CONNECTION_UART
+#include
+#include
+#include
+#include
+#else
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "runtime_lib.h"
+#include "runtime_timer.h"
+#include "native_interface.h"
+#include "app_manager_export.h"
+#include "bh_common.h"
+#include "bh_queue.h"
+#include "bh_thread.h"
+#include "bh_memory.h"
+#include "runtime_sensor.h"
+#include "attr_container.h"
+#include "module_wasm_app.h"
+#include "wasm_export.h"
+#define MAX 2048
+
+#ifndef CONNECTION_UART
+#define SA struct sockaddr
+static char *host_address = "127.0.0.1";
+static int port = 8888;
+#else
+static char *uart_device = "/dev/ttyS2";
+static int baudrate = B115200;
+#endif
+
+extern void * thread_timer_check(void *);
+extern void init_sensor_framework();
+extern int aee_host_msg_callback(void *msg, uint16_t msg_len);
+
+#ifndef CONNECTION_UART
+int listenfd = -1;
+int sockfd = -1;
+static pthread_mutex_t sock_lock = PTHREAD_MUTEX_INITIALIZER;
+#else
+int uartfd = -1;
+#endif
+
+#ifndef CONNECTION_UART
+static bool server_mode = false;
+
+// Function designed for chat between client and server.
+void* func(void* arg)
+{
+ char buff[MAX];
+ int n;
+ struct sockaddr_in servaddr;
+
+ while (1) {
+ if (sockfd != -1)
+ close(sockfd);
+ // socket create and verification
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd == -1) {
+ printf("socket creation failed...\n");
+ return NULL;
+ } else
+ printf("Socket successfully created..\n");
+ bzero(&servaddr, sizeof(servaddr));
+ // assign IP, PORT
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = inet_addr(host_address);
+ servaddr.sin_port = htons(port);
+
+ // connect the client socket to server socket
+ if (connect(sockfd, (SA*) &servaddr, sizeof(servaddr)) != 0) {
+ printf("connection with the server failed...\n");
+ sleep(10);
+ continue;
+ } else {
+ printf("connected to the server..\n");
+ }
+
+ // infinite loop for chat
+ for (;;) {
+ bzero(buff, MAX);
+
+ // read the message from client and copy it in buffer
+ n = read(sockfd, buff, sizeof(buff));
+ // print buffer which contains the client contents
+ //fprintf(stderr, "recieved %d bytes from host: %s", n, buff);
+
+ // socket disconnected
+ if (n <= 0)
+ break;
+
+ aee_host_msg_callback(buff, n);
+ }
+ }
+
+ // After chatting close the socket
+ close(sockfd);
+}
+
+static bool host_init()
+{
+ return true;
+}
+
+int host_send(void * ctx, const char *buf, int size)
+{
+ int ret;
+
+ if (pthread_mutex_trylock(&sock_lock) == 0) {
+ if (sockfd == -1) {
+ pthread_mutex_unlock(&sock_lock);
+ return 0;
+ }
+
+ ret = write(sockfd, buf, size);
+
+ pthread_mutex_unlock(&sock_lock);
+ return ret;
+ }
+
+ return -1;
+}
+
+void host_destroy()
+{
+ if (server_mode)
+ close(listenfd);
+
+ pthread_mutex_lock(&sock_lock);
+ close(sockfd);
+ pthread_mutex_unlock(&sock_lock);
+}
+
+host_interface interface = {
+ .init = host_init,
+ .send = host_send,
+ .destroy = host_destroy
+ };
+
+void* func_server_mode(void* arg)
+{
+ int clilent;
+ struct sockaddr_in serv_addr, cli_addr;
+ int n;
+ char buff[MAX];
+
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &sa, 0);
+
+ /* First call to socket() function */
+ listenfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (listenfd < 0) {
+ perror("ERROR opening socket");
+ exit(1);
+ }
+
+ /* Initialize socket structure */
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = INADDR_ANY;
+ serv_addr.sin_port = htons(port);
+
+ /* Now bind the host address using bind() call.*/
+ if (bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+ perror("ERROR on binding");
+ exit(1);
+ }
+
+ listen(listenfd, 5);
+ clilent = sizeof(cli_addr);
+
+ while (1) {
+ pthread_mutex_lock(&sock_lock);
+
+ sockfd = accept(listenfd, (struct sockaddr *) &cli_addr, &clilent);
+
+ pthread_mutex_unlock(&sock_lock);
+
+ if (sockfd < 0) {
+ perror("ERROR on accept");
+ exit(1);
+ }
+
+ printf("connection established!\n");
+
+ for (;;) {
+ bzero(buff, MAX);
+
+ // read the message from client and copy it in buffer
+ n = read(sockfd, buff, sizeof(buff));
+
+ // socket disconnected
+ if (n <= 0) {
+ pthread_mutex_lock(&sock_lock);
+ close(sockfd);
+ sockfd = -1;
+ pthread_mutex_unlock(&sock_lock);
+
+ sleep(2);
+ break;
+ }
+
+ aee_host_msg_callback(buff, n);
+ }
+ }
+}
+
+#else
+static int parse_baudrate(int baud)
+{
+ switch (baud) {
+ case 9600:
+ return B9600;
+ case 19200:
+ return B19200;
+ case 38400:
+ return B38400;
+ case 57600:
+ return B57600;
+ case 115200:
+ return B115200;
+ case 230400:
+ return B230400;
+ case 460800:
+ return B460800;
+ case 500000:
+ return B500000;
+ case 576000:
+ return B576000;
+ case 921600:
+ return B921600;
+ case 1000000:
+ return B1000000;
+ case 1152000:
+ return B1152000;
+ case 1500000:
+ return B1500000;
+ case 2000000:
+ return B2000000;
+ case 2500000:
+ return B2500000;
+ case 3000000:
+ return B3000000;
+ case 3500000:
+ return B3500000;
+ case 4000000:
+ return B4000000;
+ default:
+ return -1;
+ }
+}
+static bool uart_init(const char *device, int baudrate, int *fd)
+{
+ int uart_fd;
+ struct termios uart_term;
+
+ uart_fd = open(device, O_RDWR | O_NOCTTY);
+
+ if (uart_fd <= 0)
+ return false;
+
+ memset(&uart_term, 0, sizeof(uart_term));
+ uart_term.c_cflag = baudrate | CS8 | CLOCAL | CREAD;
+ uart_term.c_iflag = IGNPAR;
+ uart_term.c_oflag = 0;
+
+ /* set noncanonical mode */
+ uart_term.c_lflag = 0;
+ uart_term.c_cc[VTIME] = 30;
+ uart_term.c_cc[VMIN] = 1;
+ tcflush(uart_fd, TCIFLUSH);
+
+ if (tcsetattr(uart_fd, TCSANOW, &uart_term) != 0) {
+ close(uart_fd);
+ return false;
+ }
+
+ *fd = uart_fd;
+
+ return true;
+}
+
+static void *func_uart_mode(void *arg)
+{
+ int n;
+ char buff[MAX];
+
+ if (!uart_init(uart_device, baudrate, &uartfd)) {
+ printf("open uart fail! %s\n", uart_device);
+ return NULL;
+ }
+
+ for (;;) {
+ bzero(buff, MAX);
+
+ n = read(uartfd, buff, sizeof(buff));
+
+ if (n <= 0) {
+ close(uartfd);
+ uartfd = -1;
+ break;
+ }
+
+ aee_host_msg_callback(buff, n);
+ }
+
+ return NULL;
+}
+
+static int uart_send(void * ctx, const char *buf, int size)
+{
+ int ret;
+
+ ret = write(uartfd, buf, size);
+
+ return ret;
+}
+
+static void uart_destroy()
+{
+ close(uartfd);
+}
+
+static host_interface interface = { .send = uart_send, .destroy = uart_destroy };
+
+#endif
+
+static char global_heap_buf[1024 * 1024] = { 0 };
+
+static void showUsage()
+{
+#ifndef CONNECTION_UART
+ printf("Usage:\n");
+ printf("\nWork as TCP server mode:\n");
+ printf("\tvgl_wasm_runtime -s|--server_mode -p|--port \n");
+ printf("where\n");
+ printf("\t represents the port that would be listened on and the default is 8888\n");
+ printf("\nWork as TCP client mode:\n");
+ printf("\tvgl_wasm_runtime -a|--host_address -p|--port \n");
+ printf("where\n");
+ printf("\t represents the network address of host and the default is 127.0.0.1\n");
+ printf("\t represents the listen port of host and the default is 8888\n");
+#else
+ printf("Usage:\n");
+ printf("\tvgl_wasm_runtime -u -b \n\n");
+ printf("where\n");
+ printf("\t represents the UART device name and the default is /dev/ttyS2\n");
+ printf("\t represents the UART device baudrate and the default is 115200\n");
+#endif
+}
+
+static bool parse_args(int argc, char *argv[])
+{
+ int c;
+
+ while (1) {
+ int optIndex = 0;
+ static struct option longOpts[] = {
+#ifndef CONNECTION_UART
+ { "server_mode", no_argument, NULL, 's' },
+ { "host_address", required_argument, NULL, 'a' },
+ { "port", required_argument, NULL, 'p' },
+#else
+ { "uart", required_argument, NULL, 'u' },
+ { "baudrate", required_argument, NULL, 'b' },
+#endif
+ { "help", required_argument, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long(argc, argv, "sa:p:u:b:h", longOpts, &optIndex);
+ if (c == -1)
+ break;
+
+ switch (c) {
+#ifndef CONNECTION_UART
+ case 's':
+ server_mode = true;
+ break;
+ case 'a':
+ host_address = optarg;
+ printf("host address: %s\n", host_address);
+ break;
+ case 'p':
+ port = atoi(optarg);
+ printf("port: %d\n", port);
+ break;
+#else
+ case 'u':
+ uart_device = optarg;
+ printf("uart device: %s\n", uart_device);
+ break;
+ case 'b':
+ baudrate = parse_baudrate(atoi(optarg));
+ printf("uart baudrate: %s\n", optarg);
+ break;
+#endif
+ case 'h':
+ showUsage();
+ return false;
+ default:
+ showUsage();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Driver function
+int iwasm_main(int argc, char *argv[])
+{
+ korp_thread tid;
+
+ if (!parse_args(argc, argv))
+ return -1;
+
+ if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf))
+ != 0) {
+ printf("Init global heap failed.\n");
+ return -1;
+ }
+
+ if (vm_thread_sys_init() != 0) {
+ goto fail1;
+ }
+ extern void display_SDL_init();
+ display_SDL_init();
+
+ init_sensor_framework();
+
+ // timer manager
+ init_wasm_timer();
+
+#ifndef CONNECTION_UART
+ if (server_mode)
+ vm_thread_create(&tid, func_server_mode, NULL,
+ BH_APPLET_PRESERVED_STACK_SIZE);
+ else
+ vm_thread_create(&tid, func, NULL, BH_APPLET_PRESERVED_STACK_SIZE);
+#else
+ vm_thread_create(&tid, func_uart_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE);
+#endif
+
+ // TODO:
+ app_manager_startup(&interface);
+
+ fail1: bh_memory_destroy();
+ return -1;
+}
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/main.c
new file mode 100644
index 0000000000..24cae03d8e
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/main.c
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+extern void iwasm_main(int argc, char *argv[]);
+int main(int argc, char *argv[])
+{
+ iwasm_main(argc,argv);
+}
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/mouse.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/mouse.c
new file mode 100644
index 0000000000..f5d071d3c1
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/linux/mouse.c
@@ -0,0 +1,96 @@
+/**
+ * @file mouse.c
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include "display_indev.h"
+#include "SDL2/SDL.h"
+#if USE_MOUSE != 0
+
+/*********************
+ * DEFINES
+ *********************/
+#ifndef MONITOR_ZOOM
+#define MONITOR_ZOOM 1
+#endif
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+static bool left_button_down = false;
+static int16_t last_x = 0;
+static int16_t last_y = 0;
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+/**
+ * Initialize the mouse
+ */
+void mouse_init(void)
+{
+
+}
+
+/**
+ * Get the current position and state of the mouse
+ * @param data store the mouse data here
+ * @return false: because the points are not buffered, so no more data to be read
+ */
+bool mouse_read(lv_indev_data_t * data)
+{
+ /*Store the collected data*/
+ data->point.x = last_x;
+ data->point.y = last_y;
+ data->state = left_button_down ? LV_INDEV_STATE_PR : LV_INDEV_STATE_REL;
+
+ return false;
+}
+
+/**
+ * It will be called from the main SDL thread
+ */
+void mouse_handler(SDL_Event * event)
+{
+ switch (event->type) {
+ case SDL_MOUSEBUTTONUP:
+ if (event->button.button == SDL_BUTTON_LEFT)
+ left_button_down = false;
+ break;
+ case SDL_MOUSEBUTTONDOWN:
+ if (event->button.button == SDL_BUTTON_LEFT) {
+ left_button_down = true;
+ last_x = event->motion.x / MONITOR_ZOOM;
+ last_y = event->motion.y / MONITOR_ZOOM;
+ }
+ break;
+ case SDL_MOUSEMOTION:
+ last_x = event->motion.x / MONITOR_ZOOM;
+ last_y = event->motion.y / MONITOR_ZOOM;
+
+ break;
+ }
+
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+#endif
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/LICENSE b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/LICENSE
new file mode 100644
index 0000000000..8f71f43fee
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/LICENSE
@@ -0,0 +1,202 @@
+ Apache License
+ Version 2.0, January 2004
+ http://www.apache.org/licenses/
+
+ TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+ 1. Definitions.
+
+ "License" shall mean the terms and conditions for use, reproduction,
+ and distribution as defined by Sections 1 through 9 of this document.
+
+ "Licensor" shall mean the copyright owner or entity authorized by
+ the copyright owner that is granting the License.
+
+ "Legal Entity" shall mean the union of the acting entity and all
+ other entities that control, are controlled by, or are under common
+ control with that entity. For the purposes of this definition,
+ "control" means (i) the power, direct or indirect, to cause the
+ direction or management of such entity, whether by contract or
+ otherwise, or (ii) ownership of fifty percent (50%) or more of the
+ outstanding shares, or (iii) beneficial ownership of such entity.
+
+ "You" (or "Your") shall mean an individual or Legal Entity
+ exercising permissions granted by this License.
+
+ "Source" form shall mean the preferred form for making modifications,
+ including but not limited to software source code, documentation
+ source, and configuration files.
+
+ "Object" form shall mean any form resulting from mechanical
+ transformation or translation of a Source form, including but
+ not limited to compiled object code, generated documentation,
+ and conversions to other media types.
+
+ "Work" shall mean the work of authorship, whether in Source or
+ Object form, made available under the License, as indicated by a
+ copyright notice that is included in or attached to the work
+ (an example is provided in the Appendix below).
+
+ "Derivative Works" shall mean any work, whether in Source or Object
+ form, that is based on (or derived from) the Work and for which the
+ editorial revisions, annotations, elaborations, or other modifications
+ represent, as a whole, an original work of authorship. For the purposes
+ of this License, Derivative Works shall not include works that remain
+ separable from, or merely link (or bind by name) to the interfaces of,
+ the Work and Derivative Works thereof.
+
+ "Contribution" shall mean any work of authorship, including
+ the original version of the Work and any modifications or additions
+ to that Work or Derivative Works thereof, that is intentionally
+ submitted to Licensor for inclusion in the Work by the copyright owner
+ or by an individual or Legal Entity authorized to submit on behalf of
+ the copyright owner. For the purposes of this definition, "submitted"
+ means any form of electronic, verbal, or written communication sent
+ to the Licensor or its representatives, including but not limited to
+ communication on electronic mailing lists, source code control systems,
+ and issue tracking systems that are managed by, or on behalf of, the
+ Licensor for the purpose of discussing and improving the Work, but
+ excluding communication that is conspicuously marked or otherwise
+ designated in writing by the copyright owner as "Not a Contribution."
+
+ "Contributor" shall mean Licensor and any individual or Legal Entity
+ on behalf of whom a Contribution has been received by Licensor and
+ subsequently incorporated within the Work.
+
+ 2. Grant of Copyright License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ copyright license to reproduce, prepare Derivative Works of,
+ publicly display, publicly perform, sublicense, and distribute the
+ Work and such Derivative Works in Source or Object form.
+
+ 3. Grant of Patent License. Subject to the terms and conditions of
+ this License, each Contributor hereby grants to You a perpetual,
+ worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+ (except as stated in this section) patent license to make, have made,
+ use, offer to sell, sell, import, and otherwise transfer the Work,
+ where such license applies only to those patent claims licensable
+ by such Contributor that are necessarily infringed by their
+ Contribution(s) alone or by combination of their Contribution(s)
+ with the Work to which such Contribution(s) was submitted. If You
+ institute patent litigation against any entity (including a
+ cross-claim or counterclaim in a lawsuit) alleging that the Work
+ or a Contribution incorporated within the Work constitutes direct
+ or contributory patent infringement, then any patent licenses
+ granted to You under this License for that Work shall terminate
+ as of the date such litigation is filed.
+
+ 4. Redistribution. You may reproduce and distribute copies of the
+ Work or Derivative Works thereof in any medium, with or without
+ modifications, and in Source or Object form, provided that You
+ meet the following conditions:
+
+ (a) You must give any other recipients of the Work or
+ Derivative Works a copy of this License; and
+
+ (b) You must cause any modified files to carry prominent notices
+ stating that You changed the files; and
+
+ (c) You must retain, in the Source form of any Derivative Works
+ that You distribute, all copyright, patent, trademark, and
+ attribution notices from the Source form of the Work,
+ excluding those notices that do not pertain to any part of
+ the Derivative Works; and
+
+ (d) If the Work includes a "NOTICE" text file as part of its
+ distribution, then any Derivative Works that You distribute must
+ include a readable copy of the attribution notices contained
+ within such NOTICE file, excluding those notices that do not
+ pertain to any part of the Derivative Works, in at least one
+ of the following places: within a NOTICE text file distributed
+ as part of the Derivative Works; within the Source form or
+ documentation, if provided along with the Derivative Works; or,
+ within a display generated by the Derivative Works, if and
+ wherever such third-party notices normally appear. The contents
+ of the NOTICE file are for informational purposes only and
+ do not modify the License. You may add Your own attribution
+ notices within Derivative Works that You distribute, alongside
+ or as an addendum to the NOTICE text from the Work, provided
+ that such additional attribution notices cannot be construed
+ as modifying the License.
+
+ You may add Your own copyright statement to Your modifications and
+ may provide additional or different license terms and conditions
+ for use, reproduction, or distribution of Your modifications, or
+ for any such Derivative Works as a whole, provided Your use,
+ reproduction, and distribution of the Work otherwise complies with
+ the conditions stated in this License.
+
+ 5. Submission of Contributions. Unless You explicitly state otherwise,
+ any Contribution intentionally submitted for inclusion in the Work
+ by You to the Licensor shall be under the terms and conditions of
+ this License, without any additional terms or conditions.
+ Notwithstanding the above, nothing herein shall supersede or modify
+ the terms of any separate license agreement you may have executed
+ with Licensor regarding such Contributions.
+
+ 6. Trademarks. This License does not grant permission to use the trade
+ names, trademarks, service marks, or product names of the Licensor,
+ except as required for reasonable and customary use in describing the
+ origin of the Work and reproducing the content of the NOTICE file.
+
+ 7. Disclaimer of Warranty. Unless required by applicable law or
+ agreed to in writing, Licensor provides the Work (and each
+ Contributor provides its Contributions) on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+ implied, including, without limitation, any warranties or conditions
+ of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+ PARTICULAR PURPOSE. You are solely responsible for determining the
+ appropriateness of using or redistributing the Work and assume any
+ risks associated with Your exercise of permissions under this License.
+
+ 8. Limitation of Liability. In no event and under no legal theory,
+ whether in tort (including negligence), contract, or otherwise,
+ unless required by applicable law (such as deliberate and grossly
+ negligent acts) or agreed to in writing, shall any Contributor be
+ liable to You for damages, including any direct, indirect, special,
+ incidental, or consequential damages of any character arising as a
+ result of this License or out of the use or inability to use the
+ Work (including but not limited to damages for loss of goodwill,
+ work stoppage, computer failure or malfunction, or any and all
+ other commercial damages or losses), even if such Contributor
+ has been advised of the possibility of such damages.
+
+ 9. Accepting Warranty or Additional Liability. While redistributing
+ the Work or Derivative Works thereof, You may choose to offer,
+ and charge a fee for, acceptance of support, warranty, indemnity,
+ or other liability obligations and/or rights consistent with this
+ License. However, in accepting such obligations, You may act only
+ on Your own behalf and on Your sole responsibility, not on behalf
+ of any other Contributor, and only if You agree to indemnify,
+ defend, and hold each Contributor harmless for any liability
+ incurred by, or claims asserted against, such Contributor by reason
+ of your accepting any such warranty or additional liability.
+
+ END OF TERMS AND CONDITIONS
+
+ APPENDIX: How to apply the Apache License to your work.
+
+ To apply the Apache License to your work, attach the following
+ boilerplate notice, with the fields enclosed by brackets "{}"
+ replaced with your own identifying information. (Don't include
+ the brackets!) The text should be enclosed in the appropriate
+ comment syntax for the file format. We also recommend that a
+ file or class name and description of purpose be included on the
+ same "printed page" as the copyright notice for easier
+ identification within third-party archives.
+
+ Copyright {yyyy} {name of copyright owner}
+
+ Licensed under the Apache License, Version 2.0 (the "License");
+ you may not use this file except in compliance with the License.
+ You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.c
new file mode 100644
index 0000000000..5d408b562d
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.c
@@ -0,0 +1,336 @@
+/**
+ * @file XPT2046.c
+*/
+/*********************
+ * INCLUDES
+ *********************/
+#include "XPT2046.h"
+#include "board_config.h"
+#include "stdio.h"
+#include
+#include "spi.h"
+
+#include "zephyr.h"
+#include "kernel.h"
+
+#if USE_XPT2046
+
+#include
+
+#define abs(x) ((x) < 0 ? -(x) : (x))
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static void xpt2046_corr(int16_t * x, int16_t * y);
+static void xpt2046_avg(int16_t * x, int16_t * y);
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+int16_t avg_buf_x[XPT2046_AVG];
+int16_t avg_buf_y[XPT2046_AVG];
+uint8_t avg_last;
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+
+/**
+ * Initialize the XPT2046
+ */
+struct device *input_dev;
+
+struct spi_config spi_conf_xpt2046;
+struct spi_cs_control xpt2046_cs_ctrl;
+struct device *xpt2046_pen_gpio_dev;
+static struct gpio_callback gpio_cb;
+lv_indev_data_t touch_point;
+lv_indev_data_t last_touch_point;
+
+#define TOUCH_READ_THREAD_STACK_SIZE 4096
+static K_THREAD_STACK_DEFINE(touch_read_thread_stack, TOUCH_READ_THREAD_STACK_SIZE);
+static struct k_thread touch_thread_data;
+static struct k_sem sem_touch_read;
+
+K_MUTEX_DEFINE( spi_display_touch_mutex);
+
+int cnt = 0;
+int touch_read_times = 0;
+int last_pen_interrupt_time = 0;
+void xpt2046_pen_gpio_callback(struct device *port, struct gpio_callback *cb,
+ u32_t pins)
+{
+ int i;
+ cnt++;
+ if ((k_uptime_get_32() - last_pen_interrupt_time) > 500) {
+ k_sem_give(&sem_touch_read);
+ touch_read_times++;
+ last_pen_interrupt_time = k_uptime_get_32();
+ }
+
+}
+
+void disable_pen_interrupt()
+{
+ int ret = 0;
+ ret = gpio_pin_disable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN);
+ if (ret != 0) {
+ printf("gpio_pin_configure GPIO_DIR_IN failed\n");
+ }
+}
+void enable_pen_interrupt()
+{
+ int ret = 0;
+ ret = gpio_pin_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN);
+ if (ret != 0) {
+ printf("gpio_pin_configure failed\n");
+ }
+}
+
+void touch_screen_read_thread()
+{
+ int i;
+ bool ret = false;
+
+ for (;;) {
+ k_sem_take(&sem_touch_read, K_FOREVER);
+ memset(&last_touch_point, 0, sizeof(lv_indev_data_t));
+ memset(&touch_point, 0, sizeof(lv_indev_data_t));
+ memset(avg_buf_x, 0, sizeof(avg_buf_x));
+ memset(avg_buf_y, 0, sizeof(avg_buf_y));
+ k_mutex_lock(&spi_display_touch_mutex, K_FOREVER);
+ disable_pen_interrupt();
+ for (i = 0; i < 100; i++) {
+ ret = xpt2046_read(&touch_point);
+ if (ret) {
+ if ((abs(last_touch_point.point.x - touch_point.point.x) < 4)
+ && (abs(last_touch_point.point.y - touch_point.point.y)
+ < 4)) {
+ break;
+ }
+ last_touch_point = touch_point;
+
+ }
+ }
+ enable_pen_interrupt();
+ k_mutex_unlock(&spi_display_touch_mutex);
+ }
+}
+
+void xpt2046_init(void)
+{
+ int ret;
+ input_dev = device_get_binding(XPT2046_SPI_DEVICE_NAME);
+
+ if (input_dev == NULL) {
+ printf("device not found. Aborting test.");
+ return;
+ }
+ memset((void *) &touch_point, 0, sizeof(lv_indev_data_t));
+
+ spi_conf_xpt2046.frequency = XPT2046_SPI_MAX_FREQUENCY;
+ spi_conf_xpt2046.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
+ spi_conf_xpt2046.slave = 0;
+ spi_conf_xpt2046.cs = NULL;
+#ifdef XPT2046_CS_GPIO_CONTROLLER
+ xpt2046_cs_ctrl.gpio_dev = device_get_binding(XPT2046_CS_GPIO_CONTROLLER);
+ if (xpt2046_cs_ctrl.gpio_dev == NULL) {
+ printk("Cannot find %s!\n", XPT2046_CS_GPIO_CONTROLLER);
+ return;
+ }
+ gpio_pin_configure(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN,
+ GPIO_DIR_OUT);
+ gpio_pin_write(xpt2046_cs_ctrl.gpio_dev, XPT2046_CS_GPIO_PIN, 1);
+ xpt2046_cs_ctrl.gpio_pin = XPT2046_CS_GPIO_PIN;
+ xpt2046_cs_ctrl.delay = 0;
+ spi_conf_xpt2046.cs = &xpt2046_cs_ctrl;
+
+#endif
+
+#ifdef XPT2046_PEN_GPIO_CONTROLLER
+
+ xpt2046_pen_gpio_dev = device_get_binding(XPT2046_PEN_GPIO_CONTROLLER);
+ if (!xpt2046_pen_gpio_dev) {
+ printk("Cannot find %s!\n", XPT2046_PEN_GPIO_CONTROLLER);
+ return;
+ }
+ /* Setup GPIO input */
+ ret = gpio_pin_configure(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN,
+ (GPIO_DIR_IN | GPIO_INT | GPIO_INT_EDGE | GPIO_INT_ACTIVE_LOW
+ | GPIO_INT_DEBOUNCE));
+ if (ret) {
+ printk("Error configuring pin %d!\n", XPT2046_PEN_GPIO_PIN);
+ }
+
+ gpio_init_callback(&gpio_cb, xpt2046_pen_gpio_callback,
+ BIT(XPT2046_PEN_GPIO_PIN));
+
+ ret = gpio_add_callback(xpt2046_pen_gpio_dev, &gpio_cb);
+ if (ret) {
+ printk("gpio_add_callback error\n");
+ }
+ ret = gpio_pin_enable_callback(xpt2046_pen_gpio_dev, XPT2046_PEN_GPIO_PIN);
+ if (ret) {
+ printk("gpio_pin_enable_callback error\n");
+ }
+#endif
+
+ k_sem_init(&sem_touch_read, 0, 1);
+
+ k_thread_create(&touch_thread_data, touch_read_thread_stack,
+ TOUCH_READ_THREAD_STACK_SIZE, touch_screen_read_thread, NULL, NULL, NULL, 5,
+ 0, K_NO_WAIT);
+ printf("xpt2046_init ok \n");
+
+}
+
+/**
+ * Get the current position and state of the touchpad
+ * @param data store the read data here
+ * @return false: because no ore data to be read
+ */
+bool xpt2046_read(lv_indev_data_t * data)
+{
+ static int16_t last_x = 0;
+ static int16_t last_y = 0;
+ bool valid = true;
+ int s32_ret = 0;
+ uint8_t buf;
+
+ int16_t x = 0;
+ int16_t y = 0;
+
+ char tx1[16] = { 0 };
+ char rx1[16] = { 0 };
+
+ struct spi_buf tx_buf = { .buf = &tx1, .len = 3 };
+ struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 };
+ struct spi_buf rx_buf = { .buf = &rx1, .len = 3 };
+ struct spi_buf_set rx_bufs = { .buffers = &rx_buf, .count = 1 };
+
+ tx1[0] = CMD_X_READ;
+ s32_ret = spi_transceive(input_dev, &spi_conf_xpt2046, &tx_bufs, &rx_bufs);
+ if (s32_ret != 0) {
+ printf("spi_transceive return failed:%d\n", s32_ret);
+ }
+ x = rx1[1] << 8;
+ x += rx1[2];
+
+ tx1[0] = CMD_Y_READ;
+ s32_ret = spi_transceive(input_dev, &spi_conf_xpt2046, &tx_bufs, &rx_bufs);
+ if (s32_ret != 0) {
+ printf("spi_transceive return failed:%d\n", s32_ret);
+ }
+ y = rx1[1] << 8;
+ y += rx1[2];
+ x = x >> 3;
+ y = y >> 3;
+
+ xpt2046_corr(&x, &y);
+ if (y <= 0 || (x > 320)) {
+ valid = false;
+ }
+
+ last_x = x;
+ last_y = y;
+
+ data->point.x = x;
+ data->point.y = y;
+ data->state = valid == false ? LV_INDEV_STATE_REL : LV_INDEV_STATE_PR;
+
+ return valid;
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+static void xpt2046_corr(int16_t * x, int16_t * y)
+{
+#if XPT2046_XY_SWAP != 0
+ int16_t swap_tmp;
+ swap_tmp = *x;
+ *x = *y;
+ *y = swap_tmp;
+#endif
+
+ if ((*x) > XPT2046_X_MIN)
+ (*x) -= XPT2046_X_MIN;
+ else
+ (*x) = 0;
+
+ if ((*y) > XPT2046_Y_MIN)
+ (*y) -= XPT2046_Y_MIN;
+ else
+ (*y) = 0;
+
+ (*x) = (uint32_t)((uint32_t)(*x) * XPT2046_HOR_RES)
+ / (XPT2046_X_MAX - XPT2046_X_MIN);
+
+ (*y) = (uint32_t)((uint32_t)(*y) * XPT2046_VER_RES)
+ / (XPT2046_Y_MAX - XPT2046_Y_MIN);
+
+#if XPT2046_X_INV != 0
+ (*x) = XPT2046_HOR_RES - (*x);
+#endif
+
+#if XPT2046_Y_INV != 0
+ (*y) = XPT2046_VER_RES - (*y);
+#endif
+
+}
+
+static void xpt2046_avg(int16_t * x, int16_t * y)
+{
+ /*Shift out the oldest data*/
+ uint8_t i;
+ for (i = XPT2046_AVG - 1; i > 0; i--) {
+ avg_buf_x[i] = avg_buf_x[i - 1];
+ avg_buf_y[i] = avg_buf_y[i - 1];
+ }
+
+ /*Insert the new point*/
+ avg_buf_x[0] = *x;
+ avg_buf_y[0] = *y;
+ if (avg_last < XPT2046_AVG)
+ avg_last++;
+
+ /*Sum the x and y coordinates*/
+ int32_t x_sum = 0;
+ int32_t y_sum = 0;
+ for (i = 0; i < avg_last; i++) {
+ x_sum += avg_buf_x[i];
+ y_sum += avg_buf_y[i];
+ }
+
+ /*Normalize the sums*/
+ (*x) = (int32_t) x_sum / avg_last;
+ (*y) = (int32_t) y_sum / avg_last;
+}
+
+bool touchscreen_read(lv_indev_data_t * data)
+{
+ /*Store the collected data*/
+ data->point.x = last_touch_point.point.x;
+ data->point.y = last_touch_point.point.y;
+ data->state = last_touch_point.state;
+
+ if (last_touch_point.state == LV_INDEV_STATE_PR) {
+ last_touch_point.state = LV_INDEV_STATE_REL;
+ }
+ return false;
+}
+
+#endif
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.h b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.h
new file mode 100644
index 0000000000..92aa7e60b7
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/XPT2046.h
@@ -0,0 +1,93 @@
+/**
+ * @file XPT2046.h
+ *
+ */
+
+#ifndef XPT2046_H
+#define XPT2046_H
+
+#define USE_XPT2046 1
+#ifndef LV_CONF_INCLUDE_SIMPLE
+#define LV_CONF_INCLUDE_SIMPLE
+#endif
+
+# define XPT2046_HOR_RES 320
+# define XPT2046_VER_RES 240
+# define XPT2046_X_MIN 200
+# define XPT2046_Y_MIN 200
+# define XPT2046_X_MAX 3800
+# define XPT2046_Y_MAX 3800
+# define XPT2046_AVG 4
+# define XPT2046_INV 0
+
+#define CMD_X_READ 0b10010000
+#define CMD_Y_READ 0b11010000
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/*********************
+ * INCLUDES
+ *********************/
+#ifdef LV_CONF_INCLUDE_SIMPLE
+//#include "lv_drv_conf.h"
+#else
+//#include "../../lv_drv_conf.h"
+#endif
+
+#if USE_XPT2046
+#include
+#include
+#include
+//#include "lvgl/lv_hal/lv_hal_indev.h"
+#include "device.h"
+#include "gpio.h"
+#if 1
+enum {
+ LV_INDEV_STATE_REL = 0, LV_INDEV_STATE_PR
+};
+typedef uint8_t lv_indev_state_t;
+typedef int16_t lv_coord_t;
+typedef struct {
+ lv_coord_t x;
+ lv_coord_t y;
+} lv_point_t;
+
+typedef struct {
+ union {
+ lv_point_t point; /*For LV_INDEV_TYPE_POINTER the currently pressed point*/
+ uint32_t key; /*For LV_INDEV_TYPE_KEYPAD the currently pressed key*/
+ uint32_t btn; /*For LV_INDEV_TYPE_BUTTON the currently pressed button*/
+ int16_t enc_diff; /*For LV_INDEV_TYPE_ENCODER number of steps since the previous read*/
+ };
+ void *user_data; /*'lv_indev_drv_t.priv' for this driver*/
+ lv_indev_state_t state; /*LV_INDEV_STATE_REL or LV_INDEV_STATE_PR*/
+} lv_indev_data_t;
+#endif
+
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * GLOBAL PROTOTYPES
+ **********************/
+void xpt2046_init(void);
+bool xpt2046_read(lv_indev_data_t * data);
+
+/**********************
+ * MACROS
+ **********************/
+
+#endif /* USE_XPT2046 */
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+#endif /* XPT2046_H */
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/board_config.h b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/board_config.h
new file mode 100644
index 0000000000..1233c300a0
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/board_config.h
@@ -0,0 +1,20 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __BOARD_CONFIG_H__
+#define __BOARD_CONFIG_H__
+#include "pin_config_stm32.h"
+
+#endif /* __BOARD_CONFIG_H__ */
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display.h b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display.h
new file mode 100644
index 0000000000..b820b9ce96
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display.h
@@ -0,0 +1,405 @@
+/*
+ * Copyright (c) 2017 Jan Van Winkel
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+/**
+ * @file
+ * @brief Public API for display drivers and applications
+ */
+
+#ifndef ZEPHYR_INCLUDE_DISPLAY_H_
+#define ZEPHYR_INCLUDE_DISPLAY_H_
+
+/**
+ * @brief Display Interface
+ * @defgroup display_interface Display Interface
+ * @ingroup display_interfaces
+ * @{
+ */
+
+#include
+#include
+#include
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum display_pixel_format {
+ PIXEL_FORMAT_RGB_888 = BIT(0), PIXEL_FORMAT_MONO01 = BIT(1), /* 0=Black 1=White */
+ PIXEL_FORMAT_MONO10 = BIT(2), /* 1=Black 0=White */
+ PIXEL_FORMAT_ARGB_8888 = BIT(3), PIXEL_FORMAT_RGB_565 = BIT(4),
+};
+
+enum display_screen_info {
+ /**
+ * If selected, one octet represents 8 pixels ordered vertically,
+ * otherwise ordered horizontally.
+ */
+ SCREEN_INFO_MONO_VTILED = BIT(0),
+ /**
+ * If selected, the MSB represents the first pixel,
+ * otherwise MSB represents the last pixel.
+ */
+ SCREEN_INFO_MONO_MSB_FIRST = BIT(1),
+ /**
+ * Electrophoretic Display.
+ */
+ SCREEN_INFO_EPD = BIT(2),
+ /**
+ * Screen has two alternating ram buffers
+ */
+ SCREEN_INFO_DOUBLE_BUFFER = BIT(3),
+};
+
+/**
+ * @enum display_orientation
+ * @brief Enumeration with possible display orientation
+ *
+ */
+enum display_orientation {
+ DISPLAY_ORIENTATION_NORMAL,
+ DISPLAY_ORIENTATION_ROTATED_90,
+ DISPLAY_ORIENTATION_ROTATED_180,
+ DISPLAY_ORIENTATION_ROTATED_270,
+};
+
+/**
+ * @struct display_capabilities
+ * @brief Structure holding display capabilities
+ *
+ * @var u16_t display_capabilities::x_resolution
+ * Display resolution in the X direction
+ *
+ * @var u16_t display_capabilities::y_resolution
+ * Display resolution in the Y direction
+ *
+ * @var u32_t display_capabilities::supported_pixel_formats
+ * Bitwise or of pixel formats supported by the display
+ *
+ * @var u32_t display_capabilities::screen_info
+ * Information about display panel
+ *
+ * @var enum display_pixel_format display_capabilities::current_pixel_format
+ * Currently active pixel format for the display
+ *
+ * @var enum display_orientation display_capabilities::current_orientation
+ * Current display orientation
+ *
+ */
+struct display_capabilities {
+ u16_t x_resolution;
+ u16_t y_resolution;
+ u32_t supported_pixel_formats;
+ u32_t screen_info;
+ enum display_pixel_format current_pixel_format;
+ enum display_orientation current_orientation;
+};
+
+/**
+ * @struct display_buffer_descriptor
+ * @brief Structure to describe display data buffer layout
+ *
+ * @var u32_t display_buffer_descriptor::buf_size
+ * Data buffer size in bytes
+ *
+ * @var u16_t display_buffer_descriptor::width
+ * Data buffer row width in pixels
+ *
+ * @var u16_t display_buffer_descriptor::height
+ * Data buffer column height in pixels
+ *
+ * @var u16_t display_buffer_descriptor::pitch
+ * Number of pixels between consecutive rows in the data buffer
+ *
+ */
+struct display_buffer_descriptor {
+ u32_t buf_size;
+ u16_t width;
+ u16_t height;
+ u16_t pitch;
+};
+
+/**
+ * @typedef display_blanking_on_api
+ * @brief Callback API to turn on display blanking
+ * See display_blanking_on() for argument description
+ */
+typedef int (*display_blanking_on_api)(const struct device *dev);
+
+/**
+ * @typedef display_blanking_off_api
+ * @brief Callback API to turn off display blanking
+ * See display_blanking_off() for argument description
+ */
+typedef int (*display_blanking_off_api)(const struct device *dev);
+
+/**
+ * @typedef display_write_api
+ * @brief Callback API for writing data to the display
+ * See display_write() for argument description
+ */
+typedef int (*display_write_api)(const struct device *dev, const u16_t x,
+ const u16_t y, const struct display_buffer_descriptor *desc,
+ const void *buf);
+
+/**
+ * @typedef display_read_api
+ * @brief Callback API for reading data from the display
+ * See display_read() for argument description
+ */
+typedef int (*display_read_api)(const struct device *dev, const u16_t x,
+ const u16_t y, const struct display_buffer_descriptor *desc, void *buf);
+
+/**
+ * @typedef display_get_framebuffer_api
+ * @brief Callback API to get framebuffer pointer
+ * See display_get_framebuffer() for argument description
+ */
+typedef void *(*display_get_framebuffer_api)(const struct device *dev);
+
+/**
+ * @typedef display_set_brightness_api
+ * @brief Callback API to set display brightness
+ * See display_set_brightness() for argument description
+ */
+typedef int (*display_set_brightness_api)(const struct device *dev,
+ const u8_t brightness);
+
+/**
+ * @typedef display_set_contrast_api
+ * @brief Callback API to set display contrast
+ * See display_set_contrast() for argument description
+ */
+typedef int (*display_set_contrast_api)(const struct device *dev,
+ const u8_t contrast);
+
+/**
+ * @typedef display_get_capabilities_api
+ * @brief Callback API to get display capabilities
+ * See display_get_capabilities() for argument description
+ */
+typedef void (*display_get_capabilities_api)(const struct device *dev,
+ struct display_capabilities * capabilities);
+
+/**
+ * @typedef display_set_pixel_format_api
+ * @brief Callback API to set pixel format used by the display
+ * See display_set_pixel_format() for argument description
+ */
+typedef int (*display_set_pixel_format_api)(const struct device *dev,
+ const enum display_pixel_format pixel_format);
+
+/**
+ * @typedef display_set_orientation_api
+ * @brief Callback API to set orientation used by the display
+ * See display_set_orientation() for argument description
+ */
+typedef int (*display_set_orientation_api)(const struct device *dev,
+ const enum display_orientation orientation);
+
+/**
+ * @brief Display driver API
+ * API which a display driver should expose
+ */
+struct display_driver_api {
+ display_blanking_on_api blanking_on;
+ display_blanking_off_api blanking_off;
+ display_write_api write;
+ display_read_api read;
+ display_get_framebuffer_api get_framebuffer;
+ display_set_brightness_api set_brightness;
+ display_set_contrast_api set_contrast;
+ display_get_capabilities_api get_capabilities;
+ display_set_pixel_format_api set_pixel_format;
+ display_set_orientation_api set_orientation;
+};
+extern struct ili9340_data ili9340_data1;
+extern struct display_driver_api ili9340_api1;
+/**
+ * @brief Write data to display
+ *
+ * @param dev Pointer to device structure
+ * @param x x Coordinate of the upper left corner where to write the buffer
+ * @param y y Coordinate of the upper left corner where to write the buffer
+ * @param desc Pointer to a structure describing the buffer layout
+ * @param buf Pointer to buffer array
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_write(const struct device *dev, const u16_t x,
+ const u16_t y, const struct display_buffer_descriptor *desc,
+ const void *buf)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->write(dev, x, y, desc, buf);
+}
+
+/**
+ * @brief Read data from display
+ *
+ * @param dev Pointer to device structure
+ * @param x x Coordinate of the upper left corner where to read from
+ * @param y y Coordinate of the upper left corner where to read from
+ * @param desc Pointer to a structure describing the buffer layout
+ * @param buf Pointer to buffer array
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_read(const struct device *dev, const u16_t x,
+ const u16_t y, const struct display_buffer_descriptor *desc, void *buf)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->read(dev, x, y, desc, buf);
+}
+
+/**
+ * @brief Get pointer to framebuffer for direct access
+ *
+ * @param dev Pointer to device structure
+ *
+ * @retval Pointer to frame buffer or NULL if direct framebuffer access
+ * is not supported
+ *
+ */
+static inline void *display_get_framebuffer(const struct device *dev)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->get_framebuffer(dev);
+}
+
+/**
+ * @brief Turn display blanking on
+ *
+ * @param dev Pointer to device structure
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_blanking_on(const struct device *dev)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->blanking_on(dev);
+}
+
+/**
+ * @brief Turn display blanking off
+ *
+ * @param dev Pointer to device structure
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_blanking_off(const struct device *dev)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->blanking_off(dev);
+}
+
+/**
+ * @brief Set the brightness of the display
+ *
+ * Set the brightness of the display in steps of 1/256, where 255 is full
+ * brightness and 0 is minimal.
+ *
+ * @param dev Pointer to device structure
+ * @param brightness Brightness in steps of 1/256
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_set_brightness(const struct device *dev,
+ u8_t brightness)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->set_brightness(dev, brightness);
+}
+
+/**
+ * @brief Set the contrast of the display
+ *
+ * Set the contrast of the display in steps of 1/256, where 255 is maximum
+ * difference and 0 is minimal.
+ *
+ * @param dev Pointer to device structure
+ * @param contrast Contrast in steps of 1/256
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_set_contrast(const struct device *dev, u8_t contrast)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->set_contrast(dev, contrast);
+}
+
+/**
+ * @brief Get display capabilities
+ *
+ * @param dev Pointer to device structure
+ * @param capabilities Pointer to capabilities structure to populate
+ */
+static inline void display_get_capabilities(const struct device *dev,
+ struct display_capabilities * capabilities)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ api->get_capabilities(dev, capabilities);
+}
+
+/**
+ * @brief Set pixel format used by the display
+ *
+ * @param dev Pointer to device structure
+ * @param pixel_format Pixel format to be used by display
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_set_pixel_format(const struct device *dev,
+ const enum display_pixel_format pixel_format)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->set_pixel_format(dev, pixel_format);
+}
+
+/**
+ * @brief Set display orientation
+ *
+ * @param dev Pointer to device structure
+ * @param orientation Orientation to be used by display
+ *
+ * @retval 0 on success else negative errno code.
+ */
+static inline int display_set_orientation(const struct device *dev,
+ const enum display_orientation orientation)
+{
+ struct display_driver_api *api = &ili9340_api1;
+ //(struct display_driver_api *)dev->driver_api;
+
+ return api->set_orientation(dev, orientation);
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/**
+ * @}
+ */
+
+#endif /* ZEPHYR_INCLUDE_DISPLAY_H_*/
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c
new file mode 100644
index 0000000000..07e77ffce3
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.c
@@ -0,0 +1,264 @@
+/*
+ * Copyright (c) 2017 Jan Van Winkel
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "display_ili9340.h"
+#include
+
+//#define LOG_LEVEL CONFIG_DISPLAY_LOG_LEVEL
+//#include
+//LOG_MODULE_REGISTER(display_ili9340);
+#define LOG_ERR printf
+#define LOG_DBG printf
+#define LOG_WRN printf
+
+#include
+#include
+#include
+#include
+
+struct ili9340_data {
+ struct device *reset_gpio;
+ struct device *command_data_gpio;
+ struct device *spi_dev;
+ struct spi_config spi_config;
+#ifdef DT_ILITEK_ILI9340_0_CS_GPIO_CONTROLLER
+struct spi_cs_control cs_ctrl;
+#endif
+};
+
+struct ili9340_data ili9340_data1;
+
+#define ILI9340_CMD_DATA_PIN_COMMAND 0
+#define ILI9340_CMD_DATA_PIN_DATA 1
+
+static void ili9340_exit_sleep(struct ili9340_data *data)
+{
+ ili9340_transmit(data, ILI9340_CMD_EXIT_SLEEP, NULL, 0);
+ //k_sleep(120);
+}
+
+int ili9340_init()
+{
+ struct ili9340_data *data = &ili9340_data1;
+ printf("Initializing display driver\n");
+ data->spi_dev = device_get_binding(DT_ILITEK_ILI9340_0_BUS_NAME);
+ if (data->spi_dev == NULL) {
+ return -EPERM;
+ }
+ data->spi_config.frequency = DT_ILITEK_ILI9340_0_SPI_MAX_FREQUENCY;
+ data->spi_config.operation = SPI_OP_MODE_MASTER | SPI_WORD_SET(8); //SPI_OP_MODE_MASTER | SPI_WORD_SET(8);
+ data->spi_config.slave = DT_ILITEK_ILI9340_0_BASE_ADDRESS;
+
+#ifdef DT_ILITEK_ILI9340_0_CS_GPIO_CONTROLLER
+ data->cs_ctrl.gpio_dev =
+ device_get_binding(DT_ILITEK_ILI9340_0_CS_GPIO_CONTROLLER);
+ data->cs_ctrl.gpio_pin = DT_ILITEK_ILI9340_0_CS_GPIO_PIN;
+ data->cs_ctrl.delay = 0;
+ data->spi_config.cs = &(data->cs_ctrl);
+#else
+ data->spi_config.cs = NULL;
+#endif
+ data->reset_gpio = device_get_binding(
+ DT_ILITEK_ILI9340_0_RESET_GPIOS_CONTROLLER);
+ if (data->reset_gpio == NULL) {
+ return -EPERM;
+ }
+
+ gpio_pin_configure(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN,
+ GPIO_DIR_OUT);
+
+ data->command_data_gpio = device_get_binding(
+ DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_CONTROLLER);
+ if (data->command_data_gpio == NULL) {
+ return -EPERM;
+ }
+
+ gpio_pin_configure(data->command_data_gpio,
+ DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN, GPIO_DIR_OUT);
+
+ LOG_DBG("Resetting display driver");
+ gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1);
+ k_sleep(1);
+ gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 0);
+ k_sleep(1);
+ gpio_pin_write(data->reset_gpio, DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN, 1);
+ k_sleep(5);
+
+ LOG_DBG("Initializing LCD\n");
+ ili9340_lcd_init(data);
+
+ LOG_DBG("Exiting sleep mode\n");
+ ili9340_exit_sleep(data);
+
+ return 0;
+}
+
+static void ili9340_set_mem_area(struct ili9340_data *data, const u16_t x,
+ const u16_t y, const u16_t w, const u16_t h)
+{
+ u16_t spi_data[2];
+
+ spi_data[0] = sys_cpu_to_be16(x);
+ spi_data[1] = sys_cpu_to_be16(x + w - 1);
+ ili9340_transmit(data, ILI9340_CMD_COLUMN_ADDR, &spi_data[0], 4);
+
+ spi_data[0] = sys_cpu_to_be16(y);
+ spi_data[1] = sys_cpu_to_be16(y + h - 1);
+ ili9340_transmit(data, ILI9340_CMD_PAGE_ADDR, &spi_data[0], 4);
+}
+
+static int ili9340_write(const struct device *dev, const u16_t x, const u16_t y,
+ const struct display_buffer_descriptor *desc, const void *buf)
+{
+ struct ili9340_data *data = (struct ili9340_data *) &ili9340_data1;
+ const u8_t *write_data_start = (u8_t *) buf;
+ struct spi_buf tx_buf;
+ struct spi_buf_set tx_bufs;
+ u16_t write_cnt;
+ u16_t nbr_of_writes;
+ u16_t write_h;
+
+ __ASSERT(desc->width <= desc->pitch, "Pitch is smaller then width");
+ __ASSERT((3 * desc->pitch * desc->height) <= desc->buf_size,
+ "Input buffer to small");
+ ili9340_set_mem_area(data, x, y, desc->width, desc->height);
+
+ if (desc->pitch > desc->width) {
+ write_h = 1U;
+ nbr_of_writes = desc->height;
+ } else {
+ write_h = desc->height;
+ nbr_of_writes = 1U;
+ }
+ ili9340_transmit(data, ILI9340_CMD_MEM_WRITE, (void *) write_data_start,
+ 3 * desc->width * write_h);
+
+ tx_bufs.buffers = &tx_buf;
+ tx_bufs.count = 1;
+
+ write_data_start += (3 * desc->pitch);
+ for (write_cnt = 1U; write_cnt < nbr_of_writes; ++write_cnt) {
+ tx_buf.buf = (void *) write_data_start;
+ tx_buf.len = 3 * desc->width * write_h;
+ spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, NULL);
+ write_data_start += (3 * desc->pitch);
+ }
+
+ return 0;
+}
+
+static int ili9340_read(const struct device *dev, const u16_t x, const u16_t y,
+ const struct display_buffer_descriptor *desc, void *buf)
+{
+ LOG_ERR("Reading not supported");
+ return -ENOTSUP;
+}
+
+static void *ili9340_get_framebuffer(const struct device *dev)
+{
+ LOG_ERR("Direct framebuffer access not supported");
+ return NULL;
+}
+
+static int ili9340_display_blanking_off(const struct device *dev)
+{
+ struct ili9340_data *data = (struct ili9340_data *) dev->driver_data;
+
+ LOG_DBG("Turning display blanking off");
+ ili9340_transmit(data, ILI9340_CMD_DISPLAY_ON, NULL, 0);
+ return 0;
+}
+
+static int ili9340_display_blanking_on(const struct device *dev)
+{
+ struct ili9340_data *data = (struct ili9340_data *) dev->driver_data;
+
+ LOG_DBG("Turning display blanking on");
+ ili9340_transmit(data, ILI9340_CMD_DISPLAY_OFF, NULL, 0);
+ return 0;
+}
+
+static int ili9340_set_brightness(const struct device *dev,
+ const u8_t brightness)
+{
+ LOG_WRN("Set brightness not implemented");
+ return -ENOTSUP;
+}
+
+static int ili9340_set_contrast(const struct device *dev, const u8_t contrast)
+{
+ LOG_ERR("Set contrast not supported");
+ return -ENOTSUP;
+}
+
+static int ili9340_set_pixel_format(const struct device *dev,
+ const enum display_pixel_format pixel_format)
+{
+ if (pixel_format == PIXEL_FORMAT_RGB_888) {
+ return 0;
+}
+ LOG_ERR("Pixel format change not implemented");
+ return -ENOTSUP;
+}
+
+static int ili9340_set_orientation(const struct device *dev,
+ const enum display_orientation orientation)
+{
+if (orientation == DISPLAY_ORIENTATION_NORMAL) {
+ return 0;
+}
+LOG_ERR("Changing display orientation not implemented");
+ return -ENOTSUP;
+}
+
+static void ili9340_get_capabilities(const struct device *dev,
+ struct display_capabilities *capabilities)
+{
+ memset(capabilities, 0, sizeof(struct display_capabilities));
+ capabilities->x_resolution = 320;
+ capabilities->y_resolution = 240;
+ capabilities->supported_pixel_formats = PIXEL_FORMAT_RGB_888;
+ capabilities->current_pixel_format = PIXEL_FORMAT_RGB_888;
+ capabilities->current_orientation = DISPLAY_ORIENTATION_NORMAL;
+}
+
+void ili9340_transmit(struct ili9340_data *data, u8_t cmd, void *tx_data,
+ size_t tx_len)
+{
+ int i;
+ char * buf1 = tx_data;
+ data = (struct ili9340_data *) &ili9340_data1;
+ struct spi_buf tx_buf = { .buf = &cmd, .len = 1 };
+ struct spi_buf_set tx_bufs = { .buffers = &tx_buf, .count = 1 };
+
+ gpio_pin_write(data->command_data_gpio, DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN,
+ ILI9340_CMD_DATA_PIN_COMMAND);
+ spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, NULL);
+ if (tx_data != NULL) {
+ tx_buf.buf = tx_data;
+ tx_buf.len = tx_len;
+ gpio_pin_write(data->command_data_gpio,
+ DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN,
+ ILI9340_CMD_DATA_PIN_DATA);
+ spi_transceive(data->spi_dev, &data->spi_config, &tx_bufs, NULL);
+ }
+}
+
+struct display_driver_api ili9340_api1 =
+ { .blanking_on = ili9340_display_blanking_on, .blanking_off =
+ ili9340_display_blanking_off, .write = ili9340_write, .read =
+ ili9340_read, .get_framebuffer = ili9340_get_framebuffer,
+ .set_brightness = ili9340_set_brightness, .set_contrast =
+ ili9340_set_contrast, .get_capabilities =
+ ili9340_get_capabilities, .set_pixel_format =
+ ili9340_set_pixel_format, .set_orientation =
+ ili9340_set_orientation, };
+
+/*
+ DEVICE_AND_API_INIT(ili9340, DT_ILITEK_ILI9340_0_LABEL, &ili9340_init,
+ &ili9340_data, NULL, APPLICATION,
+ CONFIG_APPLICATION_INIT_PRIORITY, &ili9340_api);
+ */
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.h b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.h
new file mode 100644
index 0000000000..8aab97a651
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340.h
@@ -0,0 +1,68 @@
+/*
+ * Copyright (c) 2017 Jan Van Winkel
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+#ifndef ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9340_H_
+#define ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9340_H_
+#include "board_config.h"
+#include
+#include
+
+#define ILI9340_CMD_ENTER_SLEEP 0x10
+#define ILI9340_CMD_EXIT_SLEEP 0x11
+#define ILI9340_CMD_GAMMA_SET 0x26
+#define ILI9340_CMD_DISPLAY_OFF 0x28
+#define ILI9340_CMD_DISPLAY_ON 0x29
+#define ILI9340_CMD_COLUMN_ADDR 0x2a
+#define ILI9340_CMD_PAGE_ADDR 0x2b
+#define ILI9340_CMD_MEM_WRITE 0x2c
+#define ILI9340_CMD_MEM_ACCESS_CTRL 0x36
+#define ILI9340_CMD_PIXEL_FORMAT_SET 0x3A
+#define ILI9340_CMD_FRAME_CTRL_NORMAL_MODE 0xB1
+#define ILI9340_CMD_DISPLAY_FUNCTION_CTRL 0xB6
+#define ILI9340_CMD_POWER_CTRL_1 0xC0
+#define ILI9340_CMD_POWER_CTRL_2 0xC1
+#define ILI9340_CMD_VCOM_CTRL_1 0xC5
+#define ILI9340_CMD_VCOM_CTRL_2 0xC7
+#define ILI9340_CMD_POSITVE_GAMMA_CORRECTION 0xE0
+#define ILI9340_CMD_NEGATIVE_GAMMA_CORRECTION 0xE1
+
+#define ILI9340_DATA_MEM_ACCESS_CTRL_MY 0x80
+#define ILI9340_DATA_MEM_ACCESS_CTRL_MX 0x40
+#define ILI9340_DATA_MEM_ACCESS_CTRL_MV 0x20
+#define ILI9340_DATA_MEM_ACCESS_CTRL_ML 0x10
+#define ILI9340_DATA_MEM_ACCESS_CTRL_BGR 0x08
+#define ILI9340_DATA_MEM_ACCESS_CTRL_MH 0x04
+
+#define ILI9340_DATA_PIXEL_FORMAT_RGB_18_BIT 0x60
+#define ILI9340_DATA_PIXEL_FORMAT_RGB_16_BIT 0x50
+#define ILI9340_DATA_PIXEL_FORMAT_MCU_18_BIT 0x06
+#define ILI9340_DATA_PIXEL_FORMAT_MCU_16_BIT 0x05
+
+struct ili9340_data;
+
+/**
+ * Send data to ILI9340 display controller
+ *
+ * @param data Device data structure
+ * @param cmd Command to send to display controller
+ * @param tx_data Data to transmit to the display controller
+ * In case no data should be transmitted pass a NULL pointer
+ * @param tx_len Number of bytes in tx_data buffer
+ *
+ */
+void ili9340_transmit(struct ili9340_data *data, u8_t cmd, void *tx_data,
+ size_t tx_len);
+
+/**
+ * Perform LCD specific initialization
+ *
+ * @param data Device data structure
+ */
+void ili9340_lcd_init(struct ili9340_data *data);
+
+#define DT_ILITEK_ILI9340_0_LABEL "DISPLAY"
+#define CONFIG_DISPLAY_LOG_LEVEL 0
+
+#endif /* ZEPHYR_DRIVERS_DISPLAY_DISPLAY_ILI9340_H_ */
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340_adafruit_1480.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340_adafruit_1480.c
new file mode 100644
index 0000000000..a8581a72d3
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_ili9340_adafruit_1480.c
@@ -0,0 +1,79 @@
+/*
+ * Copyright (c) 2017 Jan Van Winkel
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ */
+
+#include "display_ili9340.h"
+
+void ili9340_lcd_init(struct ili9340_data *data)
+{
+ u8_t tx_data[15];
+
+ tx_data[0] = 0x23;
+ ili9340_transmit(data, ILI9340_CMD_POWER_CTRL_1, tx_data, 1);
+
+ tx_data[0] = 0x10;
+ ili9340_transmit(data, ILI9340_CMD_POWER_CTRL_2, tx_data, 1);
+
+ tx_data[0] = 0x3e;
+ tx_data[1] = 0x28;
+ ili9340_transmit(data, ILI9340_CMD_VCOM_CTRL_1, tx_data, 2);
+
+ tx_data[0] = 0x86;
+ ili9340_transmit(data, ILI9340_CMD_VCOM_CTRL_2, tx_data, 1);
+
+ tx_data[0] =
+ ILI9340_DATA_MEM_ACCESS_CTRL_MV | ILI9340_DATA_MEM_ACCESS_CTRL_BGR;
+ ili9340_transmit(data, ILI9340_CMD_MEM_ACCESS_CTRL, tx_data, 1);
+
+ tx_data[0] = ILI9340_DATA_PIXEL_FORMAT_MCU_18_BIT |
+ ILI9340_DATA_PIXEL_FORMAT_RGB_18_BIT;
+ ili9340_transmit(data, ILI9340_CMD_PIXEL_FORMAT_SET, tx_data, 1);
+
+ tx_data[0] = 0x00;
+ tx_data[1] = 0x18;
+ ili9340_transmit(data, ILI9340_CMD_FRAME_CTRL_NORMAL_MODE, tx_data, 2);
+
+ tx_data[0] = 0x08;
+ tx_data[1] = 0x82;
+ tx_data[2] = 0x27;
+ ili9340_transmit(data, ILI9340_CMD_DISPLAY_FUNCTION_CTRL, tx_data, 3);
+
+ tx_data[0] = 0x01;
+ ili9340_transmit(data, ILI9340_CMD_GAMMA_SET, tx_data, 1);
+
+ tx_data[0] = 0x0F;
+ tx_data[1] = 0x31;
+ tx_data[2] = 0x2B;
+ tx_data[3] = 0x0C;
+ tx_data[4] = 0x0E;
+ tx_data[5] = 0x08;
+ tx_data[6] = 0x4E;
+ tx_data[7] = 0xF1;
+ tx_data[8] = 0x37;
+ tx_data[9] = 0x07;
+ tx_data[10] = 0x10;
+ tx_data[11] = 0x03;
+ tx_data[12] = 0x0E;
+ tx_data[13] = 0x09;
+ tx_data[14] = 0x00;
+ ili9340_transmit(data, ILI9340_CMD_POSITVE_GAMMA_CORRECTION, tx_data, 15);
+
+ tx_data[0] = 0x00;
+ tx_data[1] = 0x0E;
+ tx_data[2] = 0x14;
+ tx_data[3] = 0x03;
+ tx_data[4] = 0x11;
+ tx_data[5] = 0x07;
+ tx_data[6] = 0x31;
+ tx_data[7] = 0xC1;
+ tx_data[8] = 0x48;
+ tx_data[9] = 0x08;
+ tx_data[10] = 0x0F;
+ tx_data[11] = 0x0C;
+ tx_data[12] = 0x31;
+ tx_data[13] = 0x36;
+ tx_data[14] = 0x0F;
+ ili9340_transmit(data, ILI9340_CMD_NEGATIVE_GAMMA_CORRECTION, tx_data, 15);
+}
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c
new file mode 100644
index 0000000000..1ed562c028
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/display_indev.c
@@ -0,0 +1,119 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include
+#include
+#include "display_indev.h"
+#include "display.h"
+#include "wasm_export.h"
+
+#define MONITOR_HOR_RES 320
+#define MONITOR_VER_RES 240
+#ifndef MONITOR_ZOOM
+#define MONITOR_ZOOM 1
+#endif
+int lcd_initialized = 0;
+void display_init(void)
+{
+ if (lcd_initialized != 0) {
+ return;
+ }
+ lcd_initialized = 1;
+ xpt2046_init();
+ ili9340_init();
+ display_blanking_off(NULL);
+}
+
+void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ int32 color_p_offset)
+{
+ wasm_module_inst_t module_inst = wasm_runtime_get_current_module_inst();
+ if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
+ return;
+ lv_color_t * color_p = wasm_runtime_addr_app_to_native(module_inst,
+ color_p_offset);
+
+ u16_t w = x2 - x1 + 1;
+ u16_t h = y2 - y1 + 1;
+ struct display_buffer_descriptor desc;
+
+ desc.buf_size = 3 * w * h;
+ desc.width = w;
+ desc.pitch = w;
+ desc.height = h;
+ display_write(NULL, x1, y1, &desc, (void *) color_p);
+
+ /*lv_flush_ready();*/
+}
+void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color_p)
+{
+
+}
+void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+
+}
+
+bool display_input_read(int32 data_p_offset)
+{
+ wasm_module_inst_t module_inst = wasm_runtime_get_current_module_inst();
+ if (!wasm_runtime_validate_app_addr(module_inst, data_p_offset, 1))
+ return false;
+ lv_indev_data_t * data = wasm_runtime_addr_app_to_native(module_inst,
+ data_p_offset);
+
+ return touchscreen_read(data);
+
+}
+
+void display_deinit(void)
+{
+
+}
+
+void display_vdb_write(int32 buf_offset, lv_coord_t buf_w, lv_coord_t x,
+ lv_coord_t y, int32 color_p_offset, lv_opa_t opa)
+{
+ wasm_module_inst_t module_inst = wasm_runtime_get_current_module_inst();
+ if (!wasm_runtime_validate_app_addr(module_inst, color_p_offset, 1))
+ return;
+ lv_color_t *color = wasm_runtime_addr_app_to_native(module_inst,
+ color_p_offset);
+
+ void *buf = wasm_runtime_addr_app_to_native(module_inst, buf_offset);
+
+ u8_t *buf_xy = buf + 3 * x + 3 * y * buf_w;
+ /*
+ if (opa != LV_OPA_COVER) {
+ lv_color_t mix_color;
+
+ mix_color.red = *buf_xy;
+ mix_color.green = *(buf_xy+1);
+ mix_color.blue = *(buf_xy+2);
+ color = lv_color_mix(color, mix_color, opa);
+ }
+ */
+ *buf_xy = color->red;
+ *(buf_xy + 1) = color->green;
+ *(buf_xy + 2) = color->blue;
+}
+
+int time_get_ms()
+{
+ return k_uptime_get_32();
+}
+
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c
new file mode 100644
index 0000000000..23be02a56f
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/iwasm_main.c
@@ -0,0 +1,113 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#include "bh_platform.h"
+#include "runtime_lib.h"
+#include "native_interface.h"
+#include "app-manager-export.h"
+#include "board_config.h"
+#include "bh_common.h"
+#include "bh_queue.h"
+#include "bh_thread.h"
+#include "bh_memory.h"
+#include "runtime_sensor.h"
+#include "attr-container.h"
+#include "module_wasm_app.h"
+#include "wasm_export.h"
+
+extern void * thread_timer_check(void *);
+extern void init_sensor_framework();
+extern int aee_host_msg_callback(void *msg, uint16_t msg_len);
+
+#include
+#include
+#include
+
+int uart_char_cnt = 0;
+
+static void uart_irq_callback(struct device *dev)
+{
+ unsigned char ch;
+ int size = 0;
+
+ while (uart_poll_in(dev, &ch) == 0) {
+
+ uart_char_cnt++;
+ aee_host_msg_callback(&ch, 1);
+ }
+}
+
+struct device *uart_dev = NULL;
+
+static bool host_init()
+{
+ uart_dev = device_get_binding(HOST_DEVICE_COMM_UART_NAME);
+ if (!uart_dev) {
+ printf("UART: Device driver not found.\n");
+ return;
+ }
+ uart_irq_rx_enable(uart_dev);
+ uart_irq_callback_set(uart_dev, uart_irq_callback);
+ return true;
+}
+
+int host_send(void * ctx, const char *buf, int size)
+{
+ for (int i = 0; i < size; i++)
+ uart_poll_out(uart_dev, buf[i]);
+
+ return size;
+}
+
+void host_destroy()
+{
+
+}
+
+
+#define DEFAULT_THREAD_STACKSIZE (8 * 1024)
+
+host_interface interface = { .init = host_init, .send =
+ host_send, .destroy = host_destroy };
+timer_ctx_t timer_ctx;
+static char global_heap_buf[ 498*1024] = { 0 };
+extern void display_init(void);
+int iwasm_main()
+{
+ korp_thread tid, tm_tid;
+
+ host_init();
+
+ if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf))
+ != 0) {
+ printf("Init global heap failed.\n");
+ return -1;
+ }
+
+ if (vm_thread_sys_init() != 0) {
+ goto fail1;
+ }
+
+ display_init();
+
+ // timer manager
+ init_wasm_timer();
+
+ // TODO:
+ app_manager_startup(&interface);
+
+ fail1: bh_memory_destroy();
+ return -1;
+}
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c
new file mode 100644
index 0000000000..a4313df91f
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/main.c
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include "wasm_assert.h"
+#include "wasm_log.h"
+#include "wasm_platform.h"
+#include "wasm_platform_log.h"
+#include "wasm_thread.h"
+#include "wasm_export.h"
+#include "wasm_memory.h"
+#include "bh_memory.h"
+extern void display_init(void);
+extern int iwasm_main();
+void main(void)
+{
+ display_init();
+ iwasm_main();
+ for(;;){
+ k_sleep(1000);
+ }
+}
+
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/pin_config_jlf.h b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/pin_config_jlf.h
new file mode 100644
index 0000000000..5381b72db4
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/pin_config_jlf.h
@@ -0,0 +1,37 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __PIN_CONFIG_JLF_H__
+#define __PIN_CONFIG_JLF_H__
+
+#define DT_ILITEK_ILI9340_0_BUS_NAME "SPI_2"
+#define DT_ILITEK_ILI9340_0_SPI_MAX_FREQUENCY 10*1000
+
+#define DT_ILITEK_ILI9340_0_BASE_ADDRESS 1
+#define DT_ILITEK_ILI9340_0_RESET_GPIOS_CONTROLLER "GPIO_0"
+#define DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN 5
+#define DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_CONTROLLER "GPIO_0"
+#define DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN 4
+
+#define XPT2046_SPI_DEVICE_NAME "SPI_2"
+#define XPT2046_SPI_MAX_FREQUENCY 10*1000
+#define XPT2046_CS_GPIO_CONTROLLER "GPIO_0"
+#define XPT2046_CS_GPIO_PIN 6
+
+#define XPT2046_PEN_GPIO_CONTROLLER "GPIO_0"
+#define XPT2046_PEN_GPIO_PIN 7
+
+#define HOST_DEVICE_COMM_UART_NAME "UART_1"
+#endif /* __PIN_CONFIG_JLF_H__ */
diff --git a/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/pin_config_stm32.h b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/pin_config_stm32.h
new file mode 100644
index 0000000000..0ab295eb0c
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/src/platform/zephyr/pin_config_stm32.h
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+#ifndef __PIN_CONFIG_STM32_H__
+#define __PIN_CONFIG_STM32_H__
+
+#define DT_ILITEK_ILI9340_0_BUS_NAME "SPI_1"
+#define DT_ILITEK_ILI9340_0_SPI_MAX_FREQUENCY 24*1000*1000
+
+#define DT_ILITEK_ILI9340_0_BASE_ADDRESS 1
+#define DT_ILITEK_ILI9340_0_RESET_GPIOS_CONTROLLER "GPIOC"
+#define DT_ILITEK_ILI9340_0_RESET_GPIOS_PIN 12
+#define DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_CONTROLLER "GPIOC"
+#define DT_ILITEK_ILI9340_0_CMD_DATA_GPIOS_PIN 11
+
+#define DT_ILITEK_ILI9340_0_CS_GPIO_CONTROLLER "GPIOC"
+#define DT_ILITEK_ILI9340_0_CS_GPIO_PIN 10
+
+#define XPT2046_SPI_DEVICE_NAME "SPI_1"
+#define XPT2046_SPI_MAX_FREQUENCY 12*1000*1000
+#define XPT2046_CS_GPIO_CONTROLLER "GPIOD"
+#define XPT2046_CS_GPIO_PIN 0
+
+#define XPT2046_PEN_GPIO_CONTROLLER "GPIOD"
+#define XPT2046_PEN_GPIO_PIN 1
+
+#define HOST_DEVICE_COMM_UART_NAME "UART_6"
+
+#endif /* __PIN_CONFIG_STM32_H__ */
diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt
new file mode 100644
index 0000000000..a3b186ddce
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/CMakeLists.txt
@@ -0,0 +1,118 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+cmake_minimum_required(VERSION 3.8.2)
+
+include($ENV{ZEPHYR_BASE}/cmake/app/boilerplate.cmake NO_POLICY_SCOPE)
+project(NONE)
+
+enable_language (ASM)
+
+zephyr_compile_definitions (-DNVALGRIND
+ -D__JLF__
+ -D__ZEPHYR__
+ -DWASM_ENABLE_BASE_LIB
+ -Dattr_container_malloc=bh_malloc
+ -Dattr_container_free=bh_free)
+
+set (IWASM_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/core/iwasm)
+set (APP_MGR_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/core/app-mgr)
+set (SHARED_LIB_ROOT ${IWASM_ROOT}/../shared-lib)
+
+target_include_directories(app PRIVATE ${IWASM_ROOT}/runtime/include
+ ${IWASM_ROOT}/runtime/platform/zephyr
+ ${IWASM_ROOT}/runtime/platform/include
+ ${IWASM_ROOT}/runtime/utils
+ ${IWASM_ROOT}/runtime/vmcore_wasm
+ ${IWASM_ROOT}/lib/native/base
+ ${IWASM_ROOT}/lib/native/libc
+ ${IWASM_ROOT}/lib/native/extension/sensor
+ ${IWASM_ROOT}/lib/native-interface
+ ${APP_MGR_ROOT}/app-manager
+ ${APP_MGR_ROOT}/app-mgr-shared
+ ${SHARED_LIB_ROOT}/include
+ ${SHARED_LIB_ROOT}/platform/include
+ ${SHARED_LIB_ROOT}/platform/zephyr
+ ${SHARED_LIB_ROOT}/mem-alloc/ems
+ ${SHARED_LIB_ROOT}/utils
+ ${SHARED_LIB_ROOT}/coap/er-coap
+ ${SHARED_LIB_ROOT}/coap/extension
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr
+ )
+
+set (IWASM_SRCS ${IWASM_ROOT}/runtime/platform/zephyr/wasm_math.c
+ ${IWASM_ROOT}/runtime/platform/zephyr/wasm_native.c
+ ${IWASM_ROOT}/runtime/platform/zephyr/wasm_platform.c
+ ${IWASM_ROOT}/runtime/utils/wasm_dlfcn.c
+ ${IWASM_ROOT}/runtime/utils/wasm_hashmap.c
+ ${IWASM_ROOT}/runtime/utils/wasm_log.c
+ ${IWASM_ROOT}/runtime/utils/wasm_vector.c
+ ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_application.c
+ ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_interp.c
+ ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_loader.c
+ ${IWASM_ROOT}/runtime/vmcore-wasm/wasm_runtime.c
+ ${IWASM_ROOT}/runtime/vmcore-wasm/invokeNative_general.c
+ ${IWASM_ROOT}/lib/native/base/base_lib_export.c
+ ${IWASM_ROOT}/lib/native/base/request_response.c
+ ${IWASM_ROOT}/lib/native/base/timer_wrapper.c
+ ${IWASM_ROOT}/lib/native/libc/libc_wrapper.c
+ ${IWASM_ROOT}/lib/native/extension/sensor/runtime_sensor.c
+ ${IWASM_ROOT}/lib/native-interface/attr_container.c
+ ${IWASM_ROOT}/lib/native-interface/restful_utils.c
+ ${APP_MGR_ROOT}/app-manager/app_manager.c
+ ${APP_MGR_ROOT}/app-manager/app_manager_host.c
+ ${APP_MGR_ROOT}/app-manager/ble_msg.c
+ ${APP_MGR_ROOT}/app-manager/event.c
+ ${APP_MGR_ROOT}/app-manager/message.c
+ ${APP_MGR_ROOT}/app-manager/module_jeff.c
+ ${APP_MGR_ROOT}/app-manager/module_utils.c
+ ${APP_MGR_ROOT}/app-manager/module_wasm_app.c
+ ${APP_MGR_ROOT}/app-manager/module_wasm_lib.c
+ ${APP_MGR_ROOT}/app-manager/resource_reg.c
+ ${APP_MGR_ROOT}/app-manager/watchdog.c
+ ${APP_MGR_ROOT}/app-manager/platform/zephyr/app_mgr_zephyr.c
+ ${SHARED_LIB_ROOT}/platform/zephyr/bh_assert.c
+ ${SHARED_LIB_ROOT}/platform/zephyr/bh_definition.c
+ ${SHARED_LIB_ROOT}/platform/zephyr/bh_platform.c
+ ${SHARED_LIB_ROOT}/platform/zephyr/bh_platform_log.c
+ ${SHARED_LIB_ROOT}/platform/zephyr/bh_thread.c
+ ${SHARED_LIB_ROOT}/platform/zephyr/bh_time.c
+ ${SHARED_LIB_ROOT}/mem-alloc/bh_memory.c
+ ${SHARED_LIB_ROOT}/mem-alloc/mem_alloc.c
+ ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_alloc.c
+ ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_hmu.c
+ ${SHARED_LIB_ROOT}/mem-alloc/ems/ems_kfc.c
+ ${SHARED_LIB_ROOT}/mem-alloc/tlsf/tlsf.c
+ ${SHARED_LIB_ROOT}/utils/bh_list.c
+ ${SHARED_LIB_ROOT}/utils/bh_log.c
+ ${SHARED_LIB_ROOT}/utils/bh_queue.c
+ ${SHARED_LIB_ROOT}/utils/runtime_timer.c
+ ${SHARED_LIB_ROOT}/coap/er-coap/er-coap.c
+ ${SHARED_LIB_ROOT}/coap/extension/coap_conversion.c
+ ${SHARED_LIB_ROOT}/coap/extension/coap_over_tcp.c
+ )
+
+ set (LVGL_DRV_SRCS
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_ili9340_adafruit_1480.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_ili9340.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/display_indev.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/XPT2046.c
+ )
+
+target_sources(app PRIVATE ${IWASM_SRCS}
+ ${LVGL_DRV_SRCS}
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/platform/zephyr/iwasm_main.c
+ ${CMAKE_CURRENT_SOURCE_DIR}/../src/ext_lib_export.c)
diff --git a/samples/littlevgl/vgl-wasm-runtime/zephyr-build/prj.conf b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/prj.conf
new file mode 100644
index 0000000000..2375969e15
--- /dev/null
+++ b/samples/littlevgl/vgl-wasm-runtime/zephyr-build/prj.conf
@@ -0,0 +1,7 @@
+CONFIG_SPI=y
+CONFIG_SPI_STM32=y
+CONFIG_SPI_1=y
+CONFIG_PRINTK=y
+CONFIG_LOG=y
+#CONFIG_UART_2=y
+CONFIG_UART_INTERRUPT_DRIVEN=y
diff --git a/samples/littlevgl/wasm-apps/Makefile_wasm_app b/samples/littlevgl/wasm-apps/Makefile_wasm_app
new file mode 100644
index 0000000000..801aed4adf
--- /dev/null
+++ b/samples/littlevgl/wasm-apps/Makefile_wasm_app
@@ -0,0 +1,55 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+CC = emcc
+LVGL_DIR = ${shell pwd}
+CFLAGS += -O3 -DLV_CONF_INCLUDE_SIMPLE=1 -I$(LVGL_DIR)/ -I$(LVGL_DIR)/lvgl/ -I$(LVGL_DIR)/lv_drivers/ -I$(LVGL_DIR)/src/ -I../../../core/iwasm/lib/app-libs/base/ -I../../../core/iwasm/lib/native-interface/ -I../../../core/iwasm/lib/app-libs/extension/sensor
+
+SRCS += lvgl/lv_draw/lv_draw_line.c lvgl/lv_draw/lv_draw_rbasic.c
+SRCS += lvgl/lv_draw/lv_draw_img.c lvgl/lv_draw/lv_draw_arc.c
+SRCS += lvgl/lv_draw/lv_draw_rect.c lvgl/lv_draw/lv_draw_triangle.c
+SRCS += lvgl/lv_draw/lv_draw.c lvgl/lv_draw/lv_draw_label.c
+SRCS += lvgl/lv_draw/lv_draw_vbasic.c lvgl/lv_fonts/lv_font_builtin.c
+SRCS += lvgl/lv_fonts/lv_font_dejavu_20.c
+SRCS += lvgl/lv_objx/lv_img.c
+SRCS += lvgl/lv_objx/lv_roller.c lvgl/lv_objx/lv_cb.c lvgl/lv_objx/lv_led.c lvgl/lv_objx/lv_cont.c
+SRCS += lvgl/lv_objx/lv_calendar.c lvgl/lv_objx/lv_gauge.c lvgl/lv_objx/lv_page.c
+SRCS += lvgl/lv_objx/lv_list.c lvgl/lv_objx/lv_bar.c lvgl/lv_objx/lv_tabview.c
+SRCS += lvgl/lv_objx/lv_mbox.c lvgl/lv_objx/lv_objx_templ.c lvgl/lv_objx/lv_sw.c
+SRCS += lvgl/lv_objx/lv_label.c lvgl/lv_objx/lv_slider.c lvgl/lv_objx/lv_ddlist.c
+SRCS += lvgl/lv_objx/lv_imgbtn.c lvgl/lv_objx/lv_line.c lvgl/lv_objx/lv_chart.c
+SRCS += lvgl/lv_objx/lv_btnm.c lvgl/lv_objx/lv_arc.c lvgl/lv_objx/lv_preload.c
+SRCS += lvgl/lv_objx/lv_win.c lvgl/lv_objx/lv_lmeter.c lvgl/lv_objx/lv_btn.c
+SRCS += lvgl/lv_objx/lv_ta.c lvgl/lv_misc/lv_log.c lvgl/lv_misc/lv_fs.c
+SRCS += lvgl/lv_misc/lv_task.c lvgl/lv_misc/lv_circ.c lvgl/lv_misc/lv_anim.c
+SRCS += lvgl/lv_misc/lv_color.c lvgl/lv_misc/lv_txt.c lvgl/lv_misc/lv_math.c
+SRCS += lvgl/lv_misc/lv_mem.c lvgl/lv_misc/lv_font.c lvgl/lv_misc/lv_ll.c
+SRCS += lvgl/lv_misc/lv_area.c lvgl/lv_misc/lv_templ.c lvgl/lv_misc/lv_ufs.c
+SRCS += lvgl/lv_misc/lv_area.c lvgl/lv_misc/lv_templ.c lvgl/lv_misc/lv_gc.c
+SRCS += lvgl/lv_hal/lv_hal_tick.c lvgl/lv_hal/lv_hal_indev.c lvgl/lv_hal/lv_hal_disp.c
+SRCS += lvgl/lv_themes/lv_theme_mono.c lvgl/lv_themes/lv_theme_templ.c
+SRCS += lvgl/lv_themes/lv_theme_material.c lvgl/lv_themes/lv_theme.c
+SRCS += lvgl/lv_themes/lv_theme_night.c lvgl/lv_themes/lv_theme_zen.c lvgl/lv_themes/lv_theme_nemo.c
+SRCS += lvgl/lv_themes/lv_theme_alien.c lvgl/lv_themes/lv_theme_default.c
+SRCS += lvgl/lv_core/lv_group.c lvgl/lv_core/lv_style.c lvgl/lv_core/lv_indev.c
+SRCS += lvgl/lv_core/lv_vdb.c lvgl/lv_core/lv_obj.c lvgl/lv_core/lv_refr.c
+SRCS += $(LVGL_DIR)/src/main.c
+
+SRCS += ../../../core/iwasm/lib/app-libs/base/timer.c
+all:
+ @$(CC) $(CFLAGS) $(SRCS) \
+ -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
+ -s TOTAL_MEMORY=131072 -s TOTAL_STACK=8096 \
+ -s "EXPORTED_FUNCTIONS=['_on_init', '_on_request', '_on_sensor_event', '_on_timer_callback']" \
+ -o ui_app.wasm
diff --git a/samples/littlevgl/wasm-apps/build_wasm_app.sh b/samples/littlevgl/wasm-apps/build_wasm_app.sh
new file mode 100755
index 0000000000..a88d2a76b7
--- /dev/null
+++ b/samples/littlevgl/wasm-apps/build_wasm_app.sh
@@ -0,0 +1,20 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+
+#!/bin/sh
+if [ ! -d "lvgl" ]; then
+ git clone https://github.com/littlevgl/lvgl.git --branch v5.3
+fi
+make -f Makefile_wasm_app
+
diff --git a/samples/littlevgl/wasm-apps/src/display_indev.h b/samples/littlevgl/wasm-apps/src/display_indev.h
new file mode 100644
index 0000000000..7188bd4446
--- /dev/null
+++ b/samples/littlevgl/wasm-apps/src/display_indev.h
@@ -0,0 +1,33 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DISPLAY_INDEV_H_
+#define DISPLAY_INDEV_H_
+#include
+#include
+
+#include "lvgl/lv_misc/lv_color.h"
+#include "lvgl/lv_hal/lv_hal_indev.h"
+extern void display_init(void);
+extern void display_flush(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p);
+extern bool display_input_read(lv_indev_data_t * data);
+extern void display_deinit(void);
+extern void display_vdb_write(void *buf, lv_coord_t buf_w, lv_coord_t x,
+ lv_coord_t y, lv_color_t *color, lv_opa_t opa);
+extern uint32_t time_get_ms(void);
+
+#endif
diff --git a/samples/littlevgl/wasm-apps/src/lv_conf.h b/samples/littlevgl/wasm-apps/src/lv_conf.h
new file mode 100644
index 0000000000..76533a8e1b
--- /dev/null
+++ b/samples/littlevgl/wasm-apps/src/lv_conf.h
@@ -0,0 +1,389 @@
+/**
+ * @file lv_conf.h
+ *
+ */
+
+#if 1 /*Set it to "1" to enable content*/
+
+#ifndef LV_CONF_H
+#define LV_CONF_H
+/*===================
+ Dynamic memory
+ *===================*/
+
+/* Memory size which will be used by the library
+ * to store the graphical objects and other data */
+#define LV_MEM_CUSTOM 1 /*1: use custom malloc/free, 0: use the built-in lv_mem_alloc/lv_mem_free*/
+#if LV_MEM_CUSTOM == 0
+# define LV_MEM_SIZE (64U * 1024U) /*Size memory used by `lv_mem_alloc` in bytes (>= 2kB)*/
+# define LV_MEM_ATTR /*Complier prefix for big array declaration*/
+# define LV_MEM_ADR 0 /*Set an address for memory pool instead of allocation it as an array. Can be in external SRAM too.*/
+# define LV_MEM_AUTO_DEFRAG 1 /*Automatically defrag on free*/
+#else /*LV_MEM_CUSTOM*/
+# define LV_MEM_CUSTOM_INCLUDE /*Header for the dynamic memory function*/
+# define LV_MEM_CUSTOM_ALLOC malloc /*Wrapper to malloc*/
+# define LV_MEM_CUSTOM_FREE free /*Wrapper to free*/
+#endif /*LV_MEM_CUSTOM*/
+
+/* Garbage Collector settings
+ * Used if lvgl is binded to higher language and the memory is managed by that language */
+#define LV_ENABLE_GC 0
+#if LV_ENABLE_GC != 0
+# define LV_MEM_CUSTOM_REALLOC your_realloc /*Wrapper to realloc*/
+# define LV_MEM_CUSTOM_GET_SIZE your_mem_get_size /*Wrapper to lv_mem_get_size*/
+# define LV_GC_INCLUDE "gc.h" /*Include Garbage Collector related things*/
+#endif /* LV_ENABLE_GC */
+
+/*===================
+ Graphical settings
+ *===================*/
+
+/* Horizontal and vertical resolution of the library.*/
+#define LV_HOR_RES (320)
+#define LV_VER_RES (240)
+
+/* Dot Per Inch: used to initialize default sizes. E.g. a button with width = LV_DPI / 2 -> half inch wide
+ * (Not so important, you can adjust it to modify default sizes and spaces)*/
+#define LV_DPI 100
+
+/* Enable anti-aliasing (lines, and radiuses will be smoothed) */
+#define LV_ANTIALIAS 0 /*1: Enable anti-aliasing*/
+
+/*Screen refresh period in milliseconds*/
+#define LV_REFR_PERIOD 30
+
+/*-----------------
+ * VDB settings
+ *----------------*/
+
+/* VDB (Virtual Display Buffer) is an internal graphics buffer.
+ * The GUI will be drawn into this buffer first and then
+ * the buffer will be passed to your `disp_drv.disp_flush` function to
+ * copy it to your frame buffer.
+ * VDB is required for: buffered drawing, opacity, anti-aliasing and shadows
+ * Learn more: https://docs.littlevgl.com/#Drawing*/
+
+/* Size of the VDB in pixels. Typical size: ~1/10 screen. Must be >= LV_HOR_RES
+ * Setting it to 0 will disable VDB and `disp_drv.disp_fill` and `disp_drv.disp_map` functions
+ * will be called to draw to the frame buffer directly*/
+#define LV_VDB_SIZE ((LV_VER_RES * LV_HOR_RES) / 10)
+
+/* Bit-per-pixel of VDB. Useful for monochrome or non-standard color format displays.
+ * Special formats are handled with `disp_drv.vdb_wr`)*/
+#define LV_VDB_PX_BPP LV_COLOR_SIZE /*LV_COLOR_SIZE comes from LV_COLOR_DEPTH below to set 8, 16 or 32 bit pixel size automatically */
+
+/* Place VDB to a specific address (e.g. in external RAM)
+ * 0: allocate automatically into RAM
+ * LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/
+#define LV_VDB_ADR 0
+
+/* Use two Virtual Display buffers (VDB) to parallelize rendering and flushing
+ * The flushing should use DMA to write the frame buffer in the background */
+#define LV_VDB_DOUBLE 0
+
+/* Place VDB2 to a specific address (e.g. in external RAM)
+ * 0: allocate automatically into RAM
+ * LV_VDB_ADR_INV: to replace it later with `lv_vdb_set_adr()`*/
+#define LV_VDB2_ADR 0
+
+/* Using true double buffering in `disp_drv.disp_flush` you will always get the image of the whole screen.
+ * Your only task is to set the rendered image (`color_p` parameter) as frame buffer address or send it to your display.
+ * The best if you do in the blank period of you display to avoid tearing effect.
+ * Requires:
+ * - LV_VDB_SIZE = LV_HOR_RES * LV_VER_RES
+ * - LV_VDB_DOUBLE = 1
+ */
+#define LV_VDB_TRUE_DOUBLE_BUFFERED 0
+
+/*=================
+ Misc. setting
+ *=================*/
+
+/*Input device settings*/
+#define LV_INDEV_READ_PERIOD 50 /*Input device read period in milliseconds*/
+#define LV_INDEV_POINT_MARKER 0 /*Mark the pressed points (required: USE_LV_REAL_DRAW = 1)*/
+#define LV_INDEV_DRAG_LIMIT 10 /*Drag threshold in pixels */
+#define LV_INDEV_DRAG_THROW 20 /*Drag throw slow-down in [%]. Greater value means faster slow-down */
+#define LV_INDEV_LONG_PRESS_TIME 400 /*Long press time in milliseconds*/
+#define LV_INDEV_LONG_PRESS_REP_TIME 100 /*Repeated trigger period in long press [ms] */
+
+/*Color settings*/
+#define LV_COLOR_DEPTH 32 /*Color depth: 1/8/16/32*/
+#define LV_COLOR_16_SWAP 0 /*Swap the 2 bytes of RGB565 color. Useful if the display has a 8 bit interface (e.g. SPI)*/
+#define LV_COLOR_SCREEN_TRANSP 0 /*1: Enable screen transparency. Useful for OSD or other overlapping GUIs. Requires ARGB8888 colors*/
+#define LV_COLOR_TRANSP LV_COLOR_LIME /*Images pixels with this color will not be drawn (with chroma keying)*/
+
+/*Text settings*/
+#define LV_TXT_UTF8 1 /*Enable UTF-8 coded Unicode character usage */
+#define LV_TXT_BREAK_CHARS " ,.;:-_" /*Can break texts on these chars*/
+#define LV_TXT_LINE_BREAK_LONG_LEN 12 /* If a character is at least this long, will break wherever "prettiest" */
+#define LV_TXT_LINE_BREAK_LONG_PRE_MIN_LEN 3 /* Minimum number of characters of a word to put on a line before a break */
+#define LV_TXT_LINE_BREAK_LONG_POST_MIN_LEN 1 /* Minimum number of characters of a word to put on a line after a break */
+
+/*Feature usage*/
+#define USE_LV_ANIMATION 1 /*1: Enable all animations*/
+#define USE_LV_SHADOW 1 /*1: Enable shadows*/
+#define USE_LV_GROUP 1 /*1: Enable object groups (for keyboards)*/
+#define USE_LV_GPU 0 /*1: Enable GPU interface*/
+#define USE_LV_REAL_DRAW 1 /*1: Enable function which draw directly to the frame buffer instead of VDB (required if LV_VDB_SIZE = 0)*/
+#define USE_LV_FILESYSTEM 0 /*1: Enable file system (might be required for images*/
+#define USE_LV_MULTI_LANG 0 /* Number of languages for labels to store (0: to disable this feature)*/
+
+/*Compiler settings*/
+#define LV_ATTRIBUTE_TICK_INC /* Define a custom attribute to `lv_tick_inc` function */
+#define LV_ATTRIBUTE_TASK_HANDLER /* Define a custom attribute to `lv_task_handler` function */
+#define LV_COMPILER_VLA_SUPPORTED 1 /* 1: Variable length array is supported*/
+#define LV_COMPILER_NON_CONST_INIT_SUPPORTED 1 /* 1: Initialization with non constant values are supported */
+
+/*HAL settings*/
+#define LV_TICK_CUSTOM 1 /*1: use a custom tick source (removing the need to manually update the tick with `lv_tick_inc`) */
+#if LV_TICK_CUSTOM == 1
+#define LV_TICK_CUSTOM_INCLUDE "system_header.h" /*Header for the sys time function*/
+#define LV_TICK_CUSTOM_SYS_TIME_EXPR (time_get_ms()) /*Expression evaluating to current systime in ms*/
+#endif /*LV_TICK_CUSTOM*/
+
+/*Log settings*/
+#define USE_LV_LOG 1 /*Enable/disable the log module*/
+#if USE_LV_LOG
+/* How important log should be added:
+ * LV_LOG_LEVEL_TRACE A lot of logs to give detailed information
+ * LV_LOG_LEVEL_INFO Log important events
+ * LV_LOG_LEVEL_WARN Log if something unwanted happened but didn't caused problem
+ * LV_LOG_LEVEL_ERROR Only critical issue, when the system may fail
+ */
+# define LV_LOG_LEVEL LV_LOG_LEVEL_WARN
+/* 1: Print the log with 'printf'; 0: user need to register a callback*/
+
+# define LV_LOG_PRINTF 0
+#endif /*USE_LV_LOG*/
+
+/*================
+ * THEME USAGE
+ *================*/
+#define LV_THEME_LIVE_UPDATE 1 /*1: Allow theme switching at run time. Uses 8..10 kB of RAM*/
+
+#define USE_LV_THEME_TEMPL 0 /*Just for test*/
+#define USE_LV_THEME_DEFAULT 1 /*Built mainly from the built-in styles. Consumes very few RAM*/
+#define USE_LV_THEME_ALIEN 0 /*Dark futuristic theme*/
+#define USE_LV_THEME_NIGHT 0 /*Dark elegant theme*/
+#define USE_LV_THEME_MONO 0 /*Mono color theme for monochrome displays*/
+#define USE_LV_THEME_MATERIAL 0 /*Flat theme with bold colors and light shadows*/
+#define USE_LV_THEME_ZEN 0 /*Peaceful, mainly light theme */
+#define USE_LV_THEME_NEMO 0 /*Water-like theme based on the movie "Finding Nemo"*/
+
+/*==================
+ * FONT USAGE
+ *===================*/
+
+/* More info about fonts: https://docs.littlevgl.com/#Fonts
+ * To enable a built-in font use 1,2,4 or 8 values
+ * which will determine the bit-per-pixel. Higher value means smoother fonts */
+#define USE_LV_FONT_DEJAVU_10 0
+#define USE_LV_FONT_DEJAVU_10_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_10_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_10 0
+
+#define USE_LV_FONT_DEJAVU_20 4
+#define USE_LV_FONT_DEJAVU_20_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_20_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_20 0
+
+#define USE_LV_FONT_DEJAVU_30 0
+#define USE_LV_FONT_DEJAVU_30_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_30_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_30 0
+
+#define USE_LV_FONT_DEJAVU_40 0
+#define USE_LV_FONT_DEJAVU_40_LATIN_SUP 0
+#define USE_LV_FONT_DEJAVU_40_CYRILLIC 0
+#define USE_LV_FONT_SYMBOL_40 0
+
+#define USE_LV_FONT_MONOSPACE_8 1
+
+/* Optionally declare your custom fonts here.
+ * You can use these fonts as default font too
+ * and they will be available globally. E.g.
+ * #define LV_FONT_CUSTOM_DECLARE LV_FONT_DECLARE(my_font_1) \
+ * LV_FONT_DECLARE(my_font_2) \
+ */
+#define LV_FONT_CUSTOM_DECLARE
+
+#define LV_FONT_DEFAULT &lv_font_dejavu_20 /*Always set a default font from the built-in fonts*/
+
+/*===================
+ * LV_OBJ SETTINGS
+ *==================*/
+#define LV_OBJ_FREE_NUM_TYPE uint32_t /*Type of free number attribute (comment out disable free number)*/
+#define LV_OBJ_FREE_PTR 1 /*Enable the free pointer attribute*/
+#define LV_OBJ_REALIGN 1 /*Enable `lv_obj_realaign()` based on `lv_obj_align()` parameters*/
+
+/*==================
+ * LV OBJ X USAGE
+ *================*/
+/*
+ * Documentation of the object types: https://docs.littlevgl.com/#Object-types
+ */
+
+/*****************
+ * Simple object
+ *****************/
+
+/*Label (dependencies: -*/
+#define USE_LV_LABEL 1
+#if USE_LV_LABEL != 0
+# define LV_LABEL_SCROLL_SPEED 25 /*Hor, or ver. scroll speed [px/sec] in 'LV_LABEL_LONG_SCROLL/ROLL' mode*/
+#endif
+
+/*Image (dependencies: lv_label*/
+#define USE_LV_IMG 1
+#if USE_LV_IMG != 0
+# define LV_IMG_CF_INDEXED 1 /*Enable indexed (palette) images*/
+# define LV_IMG_CF_ALPHA 1 /*Enable alpha indexed images*/
+#endif
+
+/*Line (dependencies: -*/
+#define USE_LV_LINE 1
+
+/*Arc (dependencies: -)*/
+#define USE_LV_ARC 1
+
+/*******************
+ * Container objects
+ *******************/
+
+/*Container (dependencies: -*/
+#define USE_LV_CONT 1
+
+/*Page (dependencies: lv_cont)*/
+#define USE_LV_PAGE 1
+
+/*Window (dependencies: lv_cont, lv_btn, lv_label, lv_img, lv_page)*/
+#define USE_LV_WIN 1
+
+/*Tab (dependencies: lv_page, lv_btnm)*/
+#define USE_LV_TABVIEW 1
+# if USE_LV_TABVIEW != 0
+# define LV_TABVIEW_ANIM_TIME 300 /*Time of slide animation [ms] (0: no animation)*/
+#endif
+
+/*Tileview (dependencies: lv_page) */
+#define USE_LV_TILEVIEW 1
+#if USE_LV_TILEVIEW
+# define LV_TILEVIEW_ANIM_TIME 300 /*Time of slide animation [ms] (0: no animation)*/
+#endif
+
+/*************************
+ * Data visualizer objects
+ *************************/
+
+/*Bar (dependencies: -)*/
+#define USE_LV_BAR 1
+
+/*Line meter (dependencies: *;)*/
+#define USE_LV_LMETER 1
+
+/*Gauge (dependencies:lv_bar, lv_lmeter)*/
+#define USE_LV_GAUGE 1
+
+/*Chart (dependencies: -)*/
+#define USE_LV_CHART 1
+
+/*Table (dependencies: lv_label)*/
+#define USE_LV_TABLE 1
+#if USE_LV_TABLE
+# define LV_TABLE_COL_MAX 12
+#endif
+
+/*LED (dependencies: -)*/
+#define USE_LV_LED 1
+
+/*Message box (dependencies: lv_rect, lv_btnm, lv_label)*/
+#define USE_LV_MBOX 1
+
+/*Text area (dependencies: lv_label, lv_page)*/
+#define USE_LV_TA 1
+#if USE_LV_TA != 0
+# define LV_TA_CURSOR_BLINK_TIME 400 /*ms*/
+# define LV_TA_PWD_SHOW_TIME 1500 /*ms*/
+#endif
+
+/*Spinbox (dependencies: lv_ta)*/
+#define USE_LV_SPINBOX 1
+
+/*Calendar (dependencies: -)*/
+#define USE_LV_CALENDAR 1
+
+/*Preload (dependencies: lv_arc)*/
+#define USE_LV_PRELOAD 1
+#if USE_LV_PRELOAD != 0
+# define LV_PRELOAD_DEF_ARC_LENGTH 60 /*[deg]*/
+# define LV_PRELOAD_DEF_SPIN_TIME 1000 /*[ms]*/
+# define LV_PRELOAD_DEF_ANIM LV_PRELOAD_TYPE_SPINNING_ARC
+#endif
+
+/*Canvas (dependencies: lv_img)*/
+#define USE_LV_CANVAS 1
+/*************************
+ * User input objects
+ *************************/
+
+/*Button (dependencies: lv_cont*/
+#define USE_LV_BTN 1
+#if USE_LV_BTN != 0
+# define LV_BTN_INK_EFFECT 1 /*Enable button-state animations - draw a circle on click (dependencies: USE_LV_ANIMATION)*/
+#endif
+
+/*Image Button (dependencies: lv_btn*/
+#define USE_LV_IMGBTN 1
+#if USE_LV_IMGBTN
+# define LV_IMGBTN_TILED 0 /*1: The imgbtn requires left, mid and right parts and the width can be set freely*/
+#endif
+
+/*Button matrix (dependencies: -)*/
+#define USE_LV_BTNM 1
+
+/*Keyboard (dependencies: lv_btnm)*/
+#define USE_LV_KB 1
+
+/*Check box (dependencies: lv_btn, lv_label)*/
+#define USE_LV_CB 1
+
+/*List (dependencies: lv_page, lv_btn, lv_label, (lv_img optionally for icons ))*/
+#define USE_LV_LIST 1
+#if USE_LV_LIST != 0
+# define LV_LIST_FOCUS_TIME 100 /*Default animation time of focusing to a list element [ms] (0: no animation) */
+#endif
+
+/*Drop down list (dependencies: lv_page, lv_label, lv_symbol_def.h)*/
+#define USE_LV_DDLIST 1
+#if USE_LV_DDLIST != 0
+# define LV_DDLIST_ANIM_TIME 200 /*Open and close default animation time [ms] (0: no animation)*/
+#endif
+
+/*Roller (dependencies: lv_ddlist)*/
+#define USE_LV_ROLLER 1
+#if USE_LV_ROLLER != 0
+# define LV_ROLLER_ANIM_TIME 200 /*Focus animation time [ms] (0: no animation)*/
+#endif
+
+/*Slider (dependencies: lv_bar)*/
+#define USE_LV_SLIDER 1
+
+/*Switch (dependencies: lv_slider)*/
+#define USE_LV_SW 1
+
+/*************************
+ * Non-user section
+ *************************/
+#if defined(_MSC_VER) && !defined(_CRT_SECURE_NO_WARNINGS) /* Disable warnings for Visual Studio*/
+# define _CRT_SECURE_NO_WARNINGS
+#endif
+
+/*--END OF LV_CONF_H--*/
+
+/*Be sure every define has a default value*/
+#include "lvgl/lv_conf_checker.h"
+
+#endif /*LV_CONF_H*/
+
+#endif /*End of "Content enable"*/
diff --git a/samples/littlevgl/wasm-apps/src/main.c b/samples/littlevgl/wasm-apps/src/main.c
new file mode 100644
index 0000000000..7bb50c20b3
--- /dev/null
+++ b/samples/littlevgl/wasm-apps/src/main.c
@@ -0,0 +1,165 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+/**
+ * @file main
+ *
+ */
+
+/*********************
+ * INCLUDES
+ *********************/
+#include
+//#include
+#include
+#include "lvgl/lvgl.h"
+#include "display_indev.h"
+#include "wasm_app.h"
+/*********************
+ * DEFINES
+ *********************/
+
+/**********************
+ * TYPEDEFS
+ **********************/
+
+/**********************
+ * STATIC PROTOTYPES
+ **********************/
+static void hal_init(void);
+//static int tick_thread(void * data);
+//static void memory_monitor(void * param);
+
+/**********************
+ * STATIC VARIABLES
+ **********************/
+
+/**********************
+ * MACROS
+ **********************/
+
+/**********************
+ * GLOBAL FUNCTIONS
+ **********************/
+uint32_t count = 0;
+char count_str[11] = { 0 };
+lv_obj_t *hello_world_label;
+lv_obj_t *count_label;
+lv_obj_t * btn1;
+
+lv_obj_t * label_count1;
+int label_count1_value = 0;
+char label_count1_str[11] = { 0 };
+
+void timer1_update(user_timer_t timer1)
+{
+ if ((count % 100) == 0) {
+ sprintf(count_str, "%d", count / 100);
+ lv_label_set_text(count_label, count_str);
+ }
+ lv_task_handler();
+ ++count;
+}
+
+
+static lv_res_t btn_rel_action(lv_obj_t * btn)
+{
+ label_count1_value++;
+ sprintf(label_count1_str, "%d", label_count1_value);
+ lv_label_set_text(label_count1, label_count1_str);
+ return LV_RES_OK;
+}
+
+
+void on_init()
+{
+ /*Initialize LittlevGL*/
+ lv_init();
+
+ /*Initialize the HAL (display, input devices, tick) for LittlevGL*/
+ hal_init();
+
+ hello_world_label = lv_label_create(lv_scr_act(), NULL);
+ lv_label_set_text(hello_world_label, "Hello world!");
+ lv_obj_align(hello_world_label, NULL, LV_ALIGN_IN_TOP_LEFT, 0, 0);
+
+ count_label = lv_label_create(lv_scr_act(), NULL);
+ lv_obj_align(count_label, NULL, LV_ALIGN_IN_TOP_MID, 0, 0);
+
+ btn1 = lv_btn_create(lv_scr_act(), NULL); /*Create a button on the currently loaded screen*/
+ lv_btn_set_action(btn1, LV_BTN_ACTION_CLICK, btn_rel_action); /*Set function to be called when the button is released*/
+ lv_obj_align(btn1, NULL, LV_ALIGN_CENTER, 0, 20); /*Align below the label*/
+
+ /*Create a label on the button*/
+ lv_obj_t * btn_label = lv_label_create(btn1, NULL);
+ lv_label_set_text(btn_label, "Click ++");
+
+ label_count1 = lv_label_create(lv_scr_act(), NULL);
+ lv_label_set_text(label_count1, "0");
+ lv_obj_align(label_count1, NULL, LV_ALIGN_IN_BOTTOM_MID, 0, 0);
+
+ /* set up a timer */
+ user_timer_t timer;
+ timer = api_timer_create(10, true, false, timer1_update);
+ api_timer_restart(timer, 10);
+}
+
+/**********************
+ * STATIC FUNCTIONS
+ **********************/
+
+/**
+ * Initialize the Hardware Abstraction Layer (HAL) for the Littlev graphics library
+ */
+void display_flush_wrapper(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p)
+{
+ display_flush(x1, y1, x2, y2, color_p);
+ lv_flush_ready();
+}
+void display_vdb_write_wrapper(uint8_t *buf, lv_coord_t buf_w, lv_coord_t x,
+ lv_coord_t y, lv_color_t color, lv_opa_t opa)
+{
+ display_vdb_write(buf, buf_w, x, y, &color, opa);
+}
+extern void display_fill(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ lv_color_t color_p);
+extern void display_map(int32_t x1, int32_t y1, int32_t x2, int32_t y2,
+ const lv_color_t * color_p);
+static void hal_init(void)
+{
+ /* Add a display*/
+ lv_disp_drv_t disp_drv;
+ lv_disp_drv_init(&disp_drv); /*Basic initialization*/
+ disp_drv.disp_flush = display_flush_wrapper; /*Used when `LV_VDB_SIZE != 0` in lv_conf.h (buffered drawing)*/
+ disp_drv.disp_fill = display_fill; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
+ disp_drv.disp_map = display_map; /*Used when `LV_VDB_SIZE == 0` in lv_conf.h (unbuffered drawing)*/
+#if LV_VDB_SIZE != 0
+ disp_drv.vdb_wr = display_vdb_write_wrapper;
+#endif
+ lv_disp_drv_register(&disp_drv);
+
+ /* Add the mouse as input device
+ * Use the 'mouse' driver which reads the PC's mouse*/
+// mouse_init();
+ lv_indev_drv_t indev_drv;
+ lv_indev_drv_init(&indev_drv); /*Basic initialization*/
+ indev_drv.type = LV_INDEV_TYPE_POINTER;
+ indev_drv.read = display_input_read; /*This function will be called periodically (by the library) to get the mouse position and state*/
+ lv_indev_t * mouse_indev = lv_indev_drv_register(&indev_drv);
+
+}
+
diff --git a/samples/littlevgl/wasm-apps/src/system_header.h b/samples/littlevgl/wasm-apps/src/system_header.h
new file mode 100644
index 0000000000..5333432b3e
--- /dev/null
+++ b/samples/littlevgl/wasm-apps/src/system_header.h
@@ -0,0 +1,19 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+
+uint32_t time_get_ms(void);
diff --git a/samples/simple/CMakeLists.txt b/samples/simple/CMakeLists.txt
new file mode 100644
index 0000000000..a02e415f4f
--- /dev/null
+++ b/samples/simple/CMakeLists.txt
@@ -0,0 +1,95 @@
+cmake_minimum_required (VERSION 2.8)
+
+project (simple)
+
+set (TARGET_PLATFORM "linux")
+
+# Reset default linker flags
+set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "")
+set (CMAKE_SHARED_LIBRARY_LINK_CXX_FLAGS "")
+
+# Enable repl mode if want to test spec cases
+# add_definitions(-DWASM_ENABLE_REPL)
+
+if (NOT ("$ENV{VALGRIND}" STREQUAL "YES"))
+ add_definitions(-DNVALGRIND)
+endif ()
+
+# Currently build as 32-bit by default.
+set (BUILD_AS_64BIT_SUPPORT "NO")
+
+if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+if (${BUILD_AS_64BIT_SUPPORT} STREQUAL "YES")
+ # Add -fPIC flag if build as 64-bit
+ set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -fPIC")
+ set (CMAKE_SHARED_LIBRARY_LINK_C_FLAGS "${CMAKE_SHARED_LIBRARY_LINK_C_FLAGS} -fPIC")
+else ()
+ add_definitions (-m32)
+ set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -m32")
+ set (CMAKE_SHARED_LINKER_FLAGS "${CMAKE_SHARED_LINKER_FLAGS} -m32")
+endif ()
+endif ()
+
+if (NOT CMAKE_BUILD_TYPE)
+SET(CMAKE_BUILD_TYPE Debug)
+endif (NOT CMAKE_BUILD_TYPE)
+message ("CMAKE_BUILD_TYPE = " ${CMAKE_BUILD_TYPE})
+
+if (NOT PLATFORM)
+SET(PLATFORM linux)
+endif (NOT PLATFORM)
+message ("PLATFORM = " ${PLATFORM})
+
+set (CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Wl,--gc-sections")
+set (CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -ffunction-sections -fdata-sections -Wall -Wno-unused-parameter -Wno-pedantic")
+
+set(REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../../..)
+set(WASM_DIR ${REPO_ROOT_DIR}/wamr/core/iwasm)
+set(APP_MGR_DIR ${REPO_ROOT_DIR}/wamr/core/app-mgr)
+set(SHARED_DIR ${REPO_ROOT_DIR}/wamr/core/shared-lib)
+
+
+enable_language (ASM)
+
+include (${WASM_DIR}/runtime/platform/${TARGET_PLATFORM}/platform.cmake)
+include (${WASM_DIR}/runtime/utils/utils.cmake)
+include (${WASM_DIR}/runtime/vmcore-wasm/vmcore.cmake)
+include (${WASM_DIR}/lib/native/base/wasm_lib_base.cmake)
+include (${WASM_DIR}/lib/native/libc/wasm_libc.cmake)
+include (${WASM_DIR}/lib/native/extension/sensor/wasm_lib_sensor.cmake)
+include (${WASM_DIR}/lib/native-interface/native_interface.cmake)
+include (${APP_MGR_DIR}/app-manager/app_mgr.cmake)
+include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake)
+include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake)
+include (${SHARED_DIR}/utils/shared_utils.cmake)
+include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
+include (${SHARED_DIR}/coap/lib_coap.cmake)
+
+
+include_directories(${SHARED_DIR}/include)
+
+#Note: uncomment below line to use UART mode
+#add_definitions (-DCONNECTION_UART)
+add_definitions (-DWASM_ENABLE_BASE_LIB)
+add_definitions (-Dattr_container_malloc=bh_malloc)
+add_definitions (-Dattr_container_free=bh_free)
+
+add_library (vmlib
+ ${WASM_PLATFORM_LIB_SOURCE}
+ ${WASM_UTILS_LIB_SOURCE}
+ ${VMCORE_LIB_SOURCE}
+ ${WASM_LIBC_SOURCE}
+ ${APP_MGR_SOURCE}
+ ${WASM_LIB_BASE_SOURCE}
+ ${WASM_LIB_EXT_SOURCE}
+ ${WASM_LIB_SENSOR_SOURCE}
+ ${PLATFORM_SHARED_SOURCE}
+ ${UTILS_SHARED_SOURCE}
+ ${MEM_ALLOC_SHARED_SOURCE}
+ ${NATIVE_INTERFACE_SOURCE}
+ )
+
+add_executable (simple src/main.c src/iwasm_main.c src/ext_lib_export.c)
+
+target_link_libraries (simple vmlib -lm -ldl -lpthread)
+
diff --git a/samples/simple/README.md b/samples/simple/README.md
new file mode 100644
index 0000000000..01a71bd0fd
--- /dev/null
+++ b/samples/simple/README.md
@@ -0,0 +1,323 @@
+Introduction
+==============
+This project builds out both host tools running on the host side, an application running on the device side. The device application consists of iwasm, application library, application manager, timers and sensors support. The device runs on Linux OS and interacts with host tools.
+
+It demonstrates an end to end scenario, the wasm applications life cycle management and communication programming models.
+
+Directory structure
+------------------------------
+```
+simple/
+├── build.sh
+├── CMakeLists.txt
+├── README.md
+├── src
+│ ├── ext_lib_export.c
+│ ├── iwasm_main.c
+│ └── main.c
+└── wasm-apps
+ ├── event_publisher
+ │ └── event_publisher.c
+ ├── event_subscriber
+ │ └── event_subscriber.c
+ ├── request_handler
+ │ └── request_handler.c
+ ├── request_sender
+ │ └── request_sender.c
+ ├── sensor
+ │ └── sensor.c
+ └── timer
+ └── timer.c
+```
+
+- build.sh
+ The script to build all binaries.
+- CMakeLists.txt
+ CMake file used to build the simple application.
+- README.md
+ The file you are reading currently.
+- src/ext_lib_export.c
+ This file is used to export native APIs. See the `The mechanism of exporting Native API to WASM application` section in WAMR README.md for detail.
+- src/iwam_main.c
+ This file is the implementation by platform integrator. It implements the interfaces that enable the application manager communicating with the host side. See `{WAMR_ROOT}/core/app-mgr/app-mgr-shared/app_manager_export.h` for the definition of the host interface.
+```
+/* Interfaces of host communication */
+typedef struct host_interface {
+ host_init_func init;
+ host_send_fun send;
+ host_destroy_fun destroy;
+} host_interface;
+```
+```
+host_interface interface = {
+ .init = host_init,
+ .send = host_send,
+ .destroy = host_destroy
+};
+```
+This interface is passed to application manager by calling
+```
+app_manager_startup(&interface);
+```
+
+The `host_init_func` is called when the application manager starts up. And `host_send_fun` is called by the application manager to send data to the host.
+>**Note:** Currently application manager keeps running and never exit, `host_destroy_fun` has no chance to get executed. So you can leave this API implementation empty.
+
+- src/main.c
+ The main file.
+- wasm-apps
+ Source files of sample wasm applications.
+
+Build all binaries
+==============
+Execute the build.sh script then all binaries including wasm application files would be generated in 'out' directory.
+`./build.sh`
+
+Out directory structure
+------------------------------
+ ```
+out/
+├── host_tool
+├── simple
+└── wasm-apps
+ ├── event_publisher.wasm
+ ├── event_subscriber.wasm
+ ├── request_handler.wasm
+ ├── request_sender.wasm
+ ├── sensor.wasm
+ └── timer.wasm
+ ```
+
+- host_tool:
+ A small testing tool to interact with WAMR. See the usage of this tool by executing "./host_tool -h".
+ `./host_tool -h`
+
+- simple:
+ A simple testing tool running on the host side that interact with WAMR. It is used to install, uninstall and query WASM applications in WAMR, and send request or subscribe event, etc. See the usage of this application by executing "./simple -h".
+ `./simple -h`
+>****Note:**** The connection between simple and host_tool is TCP by default and is what this guide uses. The simple application works as a server and the host_tool works as a client. You can also use UART connection. To achieve this you have to uncomment the below line in CMakeLists.txt and rebuild. You have to set up a UART hardware connection between 2 machines one of which runs the host_tool and the other runs the simple application. See the help of host_tool and the simple application to know how to specify UART device parameters.
+`#add_definitions (-DCONNECTION_UART)`
+
+- wasm-apps:
+ Sample wasm applications that demonstrate all APIs of the WAMR programming model. The source codes are in the wasm-apps directory under the root of this project.
+ + event_publisher.wasm
+ This application shows the sub/pub programming model. The pub application publishes the event "alert/overheat" by calling api_publish_event() API. The subscriber could be host_tool or other wasm application.
+ + event_subscriber.wasm
+ This application shows the sub/pub programming model. The sub application subscribes the "alert/overheat" event by calling api_subscribe_event() API so that it is able to receive the event once generated and published by the pub application. To make the process clear to interpret, the sub application dumps the event when receiving it.
+ + request_handler.wasm
+ This application shows the request/response programming model. The request handler application registers 2 resources(/url1 and /url2) by calling api_register_resource_handler() API. The request sender could be host_tool or other wasm application.
+ + request_sender.wasm
+ This application shows the request/response programming model. The sender application sends 2 requests, one is "/app/request_handler/url1" and the other is "url1". The former is an accurate request which explicitly specifies the name of request handler application in the middle of the URL and the later is a general request.
+ + sensor.wasm
+ This application shows the sensor programming model. It opens a test sensor and configures the sensor event generating interval to 1 second. To make the process clear to interpret, the application dumps the sensor event when receiving it.
+ + timer.wasm
+ This application shows the timer programming model. It creates a periodic timer that prints the current expiry number in every second.
+
+Run the scenario
+==========================
+- Enter the out directory
+```
+$ cd ./out/
+```
+
+- Startup the 'simple' process works in TCP server mode and you would see "App Manager started." is printed.
+```
+$ ./simple -s
+App Manager started.
+```
+
+- Query all installed applications
+```
+$ ./host_tool -q
+
+response status 69
+{
+ "num": 0
+}
+```
+
+The `69` stands for response status to this query request which means query success and a payload is attached with the response. See `{WAMR_ROOT}/core/iwasm/lib/app-libs/base/wasm_app.h` for the definitions of response codes. The payload is printed with JSON format where the `num` stands for application installations number and value `0` means currently no application is installed yet.
+
+- Install the request handler wasm application
+```
+$ ./host_tool -i request_handler -f ./wasm-apps/request_handler.wasm
+
+response status 65
+```
+The `65` stands for response status to this installation request which means success.
+
+Output of simple
+```
+Install WASM app success!
+sent 16 bytes to host
+WASM app 'request_handler' started
+```
+
+Now the request handler application is running and waiting for host or other wasm application to send a request.
+
+- Query again
+```
+$ ./host_tool -q
+
+response status 69
+{
+ "num": 1,
+ "applet1": "request_handler",
+ "heap1": 49152
+}
+```
+In the payload, we can see `num` is 1 which means 1 application is installed. `applet1`stands for the name of the 1st application. `heap1` stands for the heap size of the 1st application.
+
+- Send request from host to specific wasm application
+```
+$ ./host_tool -r /app/request_handler/url1 -A GET
+
+response status 69
+{
+ "key1": "value1",
+ "key2": "value2"
+}
+```
+
+We can see a response with status `69` and a payload is received.
+
+Output of simple
+```
+connection established!
+Send request to applet: request_handler
+Send request to app request_handler success.
+App request_handler got request, url url1, action 1
+[resp] ### user resource 1 handler called
+sent 150 bytes to host
+Wasm app process request success.
+```
+
+- Send a general request from host (not specify target application name)
+```
+$ ./host_tool -r /url1 -A GET
+
+response status 69
+{
+ "key1": "value1",
+ "key2": "value2"
+}
+```
+
+Output of simple
+```
+connection established!
+Send request to app request_handler success.
+App request_handler got request, url /url1, action 1
+[resp] ### user resource 1 handler called
+sent 150 bytes to host
+Wasm app process request success.
+```
+
+- Install the event publisher wasm application
+```
+$ ./host_tool -i pub -f ./wasm-apps/event_publisher.wasm
+
+response status 65
+```
+
+- Subscribe event by host_tool
+```
+$ ./host_tool -s /alert/overheat -a 3000
+
+response status 69
+
+received an event alert/overheat
+{
+ "warning": "temperature is over high"
+}
+received an event alert/overheat
+{
+ "warning": "temperature is over high"
+}
+received an event alert/overheat
+{
+ "warning": "temperature is over high"
+}
+received an event alert/overheat
+{
+ "warning": "temperature is over high"
+}
+```
+We can see 4 `alert/overheat` events are received in 3 seconds which is published by the `pub` application.
+
+Output of simple
+```
+connection established!
+am_register_event adding url:(alert/overheat)
+client: -3 registered event (alert/overheat)
+sent 16 bytes to host
+sent 142 bytes to host
+sent 142 bytes to host
+sent 142 bytes to host
+sent 142 bytes to host
+```
+- Install the event subscriber wasm application
+```
+$ ./host_tool -i sub -f ./wasm-apps/event_subscriber.wasm
+
+response status 65
+```
+The `sub` application is installed.
+
+Output of simple
+```
+connection established!
+Install WASM app success!
+WASM app 'sub' started
+am_register_event adding url:(alert/overheat)
+client: 3 registered event (alert/overheat)
+sent 16 bytes to host
+Send request to app sub success.
+App sub got request, url alert/overheat, action 6
+### user over heat event handler called
+Attribute container dump:
+Tag:
+Attribute list:
+ key: warning, type: string, value: temperature is over high
+
+Wasm app process request success.
+```
+
+We can see the `sub` application receives the `alert/overheat` event and dumps it out.
+At device side, the event is represented by an attribute container which contains key-value pairs like below:
+```
+Attribute container dump:
+Tag:
+Attribute list:
+ key: warning, type: string, value: temperature is over high
+```
+`warning` is the key's name. `string` means this is a string value and `temperature is over high` is the value.
+
+- Uninstall the wasm application
+```
+$ ./host_tool -u request_handler
+
+response status 66
+
+$ ./host_tool -u pub
+
+response status 66
+
+$ ./host_tool -u sub
+
+response status 66
+```
+
+- Query again
+```
+$ ./host_tool -q
+
+response status 69
+{
+ "num": 0
+}
+```
+
+ >**Note:** Here we only installed part of the sample WASM applications. You can try others by yourself.
+
+ >**Note:** You have to manually kill the simple process by Ctrl+C after use.
diff --git a/samples/simple/build.sh b/samples/simple/build.sh
new file mode 100755
index 0000000000..7fe76126d3
--- /dev/null
+++ b/samples/simple/build.sh
@@ -0,0 +1,102 @@
+#!/bin/bash
+
+CURR_DIR=$PWD
+ROOT_DIR=${PWD}/../../..
+OUT_DIR=${PWD}/out
+BUILD_DIR=${PWD}/build
+
+IWASM_ROOT=${PWD}/../../core/iwasm
+APP_LIBS=${IWASM_ROOT}/lib/app-libs
+NATIVE_LIBS=${IWASM_ROOT}/lib/native-interface
+APP_LIB_SRC="${APP_LIBS}/base/*.c ${APP_LIBS}/extension/sensor/*.c ${NATIVE_LIBS}/*.c"
+WASM_APPS=${PWD}/wasm-apps
+
+rm -rf ${OUT_DIR}
+mkdir ${OUT_DIR}
+mkdir ${OUT_DIR}/wasm-apps
+
+cd ${ROOT_DIR}/wamr/core/shared-lib/mem-alloc
+if [ ! -d "tlsf" ]; then
+ git clone https://github.com/mattconte/tlsf
+fi
+
+echo "#####################build simple project"
+cd ${CURR_DIR}
+mkdir -p cmake_build
+cd cmake_build
+cmake ..
+make
+if [ $? != 0 ];then
+ echo "BUILD_FAIL simple exit as $?\n"
+ exit 2
+fi
+cp -a simple ${OUT_DIR}
+echo "#####################build simple project success"
+
+echo "#####################build host-tool"
+cd ${ROOT_DIR}/wamr/test-tools/host-tool
+mkdir -p bin
+cd bin
+cmake ..
+make
+if [ $? != 0 ];then
+ echo "BUILD_FAIL host tool exit as $?\n"
+ exit 2
+fi
+cp host_tool ${OUT_DIR}
+echo "#####################build host-tool success"
+
+
+echo "#####################build wasm apps"
+
+cd ${CURR_DIR}
+
+APP_SRC="${WASM_APPS}/timer/timer.c ${APP_LIB_SRC}"
+emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \
+ -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
+ -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
+ -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \
+ '_on_sensor_event', '_on_timer_callback']" \
+ -o ${OUT_DIR}/wasm-apps/timer.wasm ${APP_SRC}
+
+APP_SRC="${WASM_APPS}/request_handler/request_handler.c ${APP_LIB_SRC}"
+emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \
+ -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
+ -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
+ -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \
+ '_on_sensor_event', '_on_timer_callback']" \
+ -o ${OUT_DIR}/wasm-apps/request_handler.wasm ${APP_SRC}
+
+APP_SRC="${WASM_APPS}/request_sender/request_sender.c ${APP_LIB_SRC}"
+emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \
+ -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
+ -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
+ -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \
+ '_on_sensor_event', '_on_timer_callback']" \
+ -o ${OUT_DIR}/wasm-apps/request_sender.wasm ${APP_SRC}
+
+APP_SRC="${WASM_APPS}/event_publisher/event_publisher.c ${APP_LIB_SRC}"
+emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \
+ -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
+ -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
+ -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \
+ '_on_sensor_event', '_on_timer_callback']" \
+ -o ${OUT_DIR}/wasm-apps/event_publisher.wasm ${APP_SRC}
+
+APP_SRC="${WASM_APPS}/event_subscriber/event_subscriber.c ${APP_LIB_SRC}"
+emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \
+ -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
+ -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
+ -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \
+ '_on_sensor_event', '_on_timer_callback']" \
+ -o ${OUT_DIR}/wasm-apps/event_subscriber.wasm ${APP_SRC}
+
+APP_SRC="${WASM_APPS}/sensor/sensor.c ${APP_LIB_SRC}"
+emcc -O3 -I${APP_LIBS}/base -I${APP_LIBS}/extension/sensor -I${NATIVE_LIBS} \
+ -s WASM=1 -s SIDE_MODULE=1 -s ASSERTIONS=1 -s STACK_OVERFLOW_CHECK=2 \
+ -s TOTAL_MEMORY=65536 -s TOTAL_STACK=4096 \
+ -s "EXPORTED_FUNCTIONS=['_on_init', '_on_destroy', '_on_request', '_on_response', \
+ '_on_sensor_event', '_on_timer_callback']" \
+ -o ${OUT_DIR}/wasm-apps/sensor.wasm ${APP_SRC}
+
+echo "#####################build wasm apps success"
diff --git a/samples/simple/src/ext_lib_export.c b/samples/simple/src/ext_lib_export.c
new file mode 100644
index 0000000000..89e572005d
--- /dev/null
+++ b/samples/simple/src/ext_lib_export.c
@@ -0,0 +1,8 @@
+#include "lib_export.h"
+#include "sensor_api.h"
+
+static NativeSymbol extended_native_symbol_defs[] = {
+#include "runtime_sensor.inl"
+ };
+
+#include "ext_lib_export.h"
diff --git a/samples/simple/src/iwasm_main.c b/samples/simple/src/iwasm_main.c
new file mode 100644
index 0000000000..d70b7e4d3c
--- /dev/null
+++ b/samples/simple/src/iwasm_main.c
@@ -0,0 +1,465 @@
+
+#ifndef CONNECTION_UART
+#include
+#include
+#include
+#include
+#else
+#include
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "runtime_lib.h"
+#include "runtime_timer.h"
+#include "native_interface.h"
+#include "app_manager_export.h"
+#include "bh_common.h"
+#include "bh_queue.h"
+#include "bh_thread.h"
+#include "bh_memory.h"
+#include "runtime_sensor.h"
+#include "attr_container.h"
+#include "module_wasm_app.h"
+#include "wasm_export.h"
+#define MAX 2048
+
+#ifndef CONNECTION_UART
+#define SA struct sockaddr
+static char *host_address = "127.0.0.1";
+static int port = 8888;
+#else
+static char *uart_device = "/dev/ttyS2";
+static int baudrate = B115200;
+#endif
+
+extern void * thread_timer_check(void *);
+extern void init_sensor_framework();
+extern int aee_host_msg_callback(void *msg, uint16_t msg_len);
+
+#ifndef CONNECTION_UART
+int listenfd = -1;
+int sockfd = -1;
+static pthread_mutex_t sock_lock = PTHREAD_MUTEX_INITIALIZER;
+#else
+int uartfd = -1;
+#endif
+
+#ifndef CONNECTION_UART
+static bool server_mode = false;
+
+// Function designed for chat between client and server.
+void* func(void* arg)
+{
+ char buff[MAX];
+ int n;
+ struct sockaddr_in servaddr;
+
+ while (1) {
+ if (sockfd != -1)
+ close(sockfd);
+ // socket create and verification
+ sockfd = socket(AF_INET, SOCK_STREAM, 0);
+ if (sockfd == -1) {
+ printf("socket creation failed...\n");
+ return NULL;
+ } else
+ printf("Socket successfully created..\n");
+ bzero(&servaddr, sizeof(servaddr));
+ // assign IP, PORT
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = inet_addr(host_address);
+ servaddr.sin_port = htons(port);
+
+ // connect the client socket to server socket
+ if (connect(sockfd, (SA*) &servaddr, sizeof(servaddr)) != 0) {
+ printf("connection with the server failed...\n");
+ sleep(10);
+ continue;
+ } else {
+ printf("connected to the server..\n");
+ }
+
+ // infinite loop for chat
+ for (;;) {
+ bzero(buff, MAX);
+
+ // read the message from client and copy it in buffer
+ n = read(sockfd, buff, sizeof(buff));
+ // print buffer which contains the client contents
+ //fprintf(stderr, "recieved %d bytes from host: %s", n, buff);
+
+ // socket disconnected
+ if (n <= 0)
+ break;
+
+ aee_host_msg_callback(buff, n);
+ }
+ }
+
+ // After chatting close the socket
+ close(sockfd);
+}
+
+static bool host_init()
+{
+ return true;
+}
+
+int host_send(void * ctx, const char *buf, int size)
+{
+ int ret;
+
+ if (pthread_mutex_trylock(&sock_lock) == 0) {
+ if (sockfd == -1) {
+ pthread_mutex_unlock(&sock_lock);
+ return 0;
+ }
+
+ ret = write(sockfd, buf, size);
+
+ pthread_mutex_unlock(&sock_lock);
+ return ret;
+ }
+
+ return -1;
+}
+
+void host_destroy()
+{
+ if (server_mode)
+ close(listenfd);
+
+ pthread_mutex_lock(&sock_lock);
+ close(sockfd);
+ pthread_mutex_unlock(&sock_lock);
+}
+
+host_interface interface = {
+ .init = host_init,
+ .send = host_send,
+ .destroy = host_destroy
+};
+
+void* func_server_mode(void* arg)
+{
+ int clilent;
+ struct sockaddr_in serv_addr, cli_addr;
+ int n;
+ char buff[MAX];
+
+ struct sigaction sa;
+ sa.sa_handler = SIG_IGN;
+ sigaction(SIGPIPE, &sa, 0);
+
+ /* First call to socket() function */
+ listenfd = socket(AF_INET, SOCK_STREAM, 0);
+
+ if (listenfd < 0) {
+ perror("ERROR opening socket");
+ exit(1);
+ }
+
+ /* Initialize socket structure */
+ bzero((char *) &serv_addr, sizeof(serv_addr));
+
+ serv_addr.sin_family = AF_INET;
+ serv_addr.sin_addr.s_addr = INADDR_ANY;
+ serv_addr.sin_port = htons(port);
+
+ /* Now bind the host address using bind() call.*/
+ if (bind(listenfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
+ perror("ERROR on binding");
+ exit(1);
+ }
+
+ listen(listenfd, 5);
+ clilent = sizeof(cli_addr);
+
+ while (1) {
+ pthread_mutex_lock(&sock_lock);
+
+ sockfd = accept(listenfd, (struct sockaddr *) &cli_addr, &clilent);
+
+ pthread_mutex_unlock(&sock_lock);
+
+ if (sockfd < 0) {
+ perror("ERROR on accept");
+ exit(1);
+ }
+
+ printf("connection established!\n");
+
+ for (;;) {
+ bzero(buff, MAX);
+
+ // read the message from client and copy it in buffer
+ n = read(sockfd, buff, sizeof(buff));
+
+ // socket disconnected
+ if (n <= 0) {
+ pthread_mutex_lock(&sock_lock);
+ close(sockfd);
+ sockfd = -1;
+ pthread_mutex_unlock(&sock_lock);
+
+ sleep(2);
+ break;
+ }
+
+ aee_host_msg_callback(buff, n);
+ }
+ }
+}
+
+#else
+static int parse_baudrate(int baud)
+{
+ switch (baud) {
+ case 9600:
+ return B9600;
+ case 19200:
+ return B19200;
+ case 38400:
+ return B38400;
+ case 57600:
+ return B57600;
+ case 115200:
+ return B115200;
+ case 230400:
+ return B230400;
+ case 460800:
+ return B460800;
+ case 500000:
+ return B500000;
+ case 576000:
+ return B576000;
+ case 921600:
+ return B921600;
+ case 1000000:
+ return B1000000;
+ case 1152000:
+ return B1152000;
+ case 1500000:
+ return B1500000;
+ case 2000000:
+ return B2000000;
+ case 2500000:
+ return B2500000;
+ case 3000000:
+ return B3000000;
+ case 3500000:
+ return B3500000;
+ case 4000000:
+ return B4000000;
+ default:
+ return -1;
+ }
+}
+static bool uart_init(const char *device, int baudrate, int *fd)
+{
+ int uart_fd;
+ struct termios uart_term;
+
+ uart_fd = open(device, O_RDWR | O_NOCTTY);
+
+ if (uart_fd <= 0)
+ return false;
+
+ memset(&uart_term, 0, sizeof(uart_term));
+ uart_term.c_cflag = baudrate | CS8 | CLOCAL | CREAD;
+ uart_term.c_iflag = IGNPAR;
+ uart_term.c_oflag = 0;
+
+ /* set noncanonical mode */
+ uart_term.c_lflag = 0;
+ uart_term.c_cc[VTIME] = 30;
+ uart_term.c_cc[VMIN] = 1;
+ tcflush(uart_fd, TCIFLUSH);
+
+ if (tcsetattr(uart_fd, TCSANOW, &uart_term) != 0) {
+ close(uart_fd);
+ return false;
+ }
+
+ *fd = uart_fd;
+
+ return true;
+}
+
+static void *func_uart_mode(void *arg)
+{
+ int n;
+ char buff[MAX];
+
+ if (!uart_init(uart_device, baudrate, &uartfd)) {
+ printf("open uart fail! %s\n", uart_device);
+ return NULL;
+ }
+
+ for (;;) {
+ bzero(buff, MAX);
+
+ n = read(uartfd, buff, sizeof(buff));
+
+ if (n <= 0) {
+ close(uartfd);
+ uartfd = -1;
+ break;
+ }
+
+ aee_host_msg_callback(buff, n);
+ }
+
+ return NULL;
+}
+
+static int uart_send(void * ctx, const char *buf, int size)
+{
+ int ret;
+
+ ret = write(uartfd, buf, size);
+
+ return ret;
+}
+
+static void uart_destroy()
+{
+ close(uartfd);
+}
+
+static host_interface interface = { .send = uart_send, .destroy = uart_destroy };
+
+#endif
+
+static char global_heap_buf[512 * 1024] = { 0 };
+
+static void showUsage()
+{
+#ifndef CONNECTION_UART
+ printf("Usage:\n");
+ printf("\nWork as TCP server mode:\n");
+ printf("\tsimple -s|--server_mode -p|--port \n");
+ printf("where\n");
+ printf("\t represents the port that would be listened on and the default is 8888\n");
+ printf("\nWork as TCP client mode:\n");
+ printf("\tsimple -a|--host_address -p|--port \n");
+ printf("where\n");
+ printf("\t represents the network address of host and the default is 127.0.0.1\n");
+ printf("\t represents the listen port of host and the default is 8888\n");
+#else
+ printf("Usage:\n");
+ printf("\tsimple -u -b \n\n");
+ printf("where\n");
+ printf("\t represents the UART device name and the default is /dev/ttyS2\n");
+ printf("\t represents the UART device baudrate and the default is 115200\n");
+#endif
+}
+
+static bool parse_args(int argc, char *argv[])
+{
+ int c;
+
+ while (1) {
+ int optIndex = 0;
+ static struct option longOpts[] = {
+#ifndef CONNECTION_UART
+ { "server_mode", no_argument, NULL, 's' },
+ { "host_address", required_argument, NULL, 'a' },
+ { "port", required_argument, NULL, 'p' },
+#else
+ { "uart", required_argument, NULL, 'u' },
+ { "baudrate", required_argument, NULL, 'b' },
+#endif
+ { "help", required_argument, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long(argc, argv, "sa:p:u:b:h", longOpts, &optIndex);
+ if (c == -1)
+ break;
+
+ switch (c) {
+#ifndef CONNECTION_UART
+ case 's':
+ server_mode = true;
+ break;
+ case 'a':
+ host_address = optarg;
+ printf("host address: %s\n", host_address);
+ break;
+ case 'p':
+ port = atoi(optarg);
+ printf("port: %d\n", port);
+ break;
+#else
+ case 'u':
+ uart_device = optarg;
+ printf("uart device: %s\n", uart_device);
+ break;
+ case 'b':
+ baudrate = parse_baudrate(atoi(optarg));
+ printf("uart baudrate: %s\n", optarg);
+ break;
+#endif
+ case 'h':
+ showUsage();
+ return false;
+ default:
+ showUsage();
+ return false;
+ }
+ }
+
+ return true;
+}
+
+// Driver function
+int iwasm_main(int argc, char *argv[])
+{
+ korp_thread tid;
+
+ if (!parse_args(argc, argv))
+ return -1;
+
+ if (bh_memory_init_with_pool(global_heap_buf, sizeof(global_heap_buf))
+ != 0) {
+ printf("Init global heap failed.\n");
+ return -1;
+ }
+
+ if (vm_thread_sys_init() != 0) {
+ goto fail1;
+ }
+
+ init_sensor_framework();
+
+ // timer manager
+ init_wasm_timer();
+
+#ifndef CONNECTION_UART
+ if (server_mode)
+ vm_thread_create(&tid, func_server_mode, NULL,
+ BH_APPLET_PRESERVED_STACK_SIZE);
+ else
+ vm_thread_create(&tid, func, NULL, BH_APPLET_PRESERVED_STACK_SIZE);
+#else
+ vm_thread_create(&tid, func_uart_mode, NULL, BH_APPLET_PRESERVED_STACK_SIZE);
+#endif
+
+ // TODO:
+ app_manager_startup(&interface);
+
+ fail1: bh_memory_destroy();
+ return -1;
+}
diff --git a/samples/simple/src/main.c b/samples/simple/src/main.c
new file mode 100644
index 0000000000..14afb07808
--- /dev/null
+++ b/samples/simple/src/main.c
@@ -0,0 +1,5 @@
+extern void iwasm_main();
+int main(int argc, char *argv[])
+{
+ iwasm_main(argc, argv);
+}
diff --git a/samples/simple/wasm-apps/event_publisher/event_publisher.c b/samples/simple/wasm-apps/event_publisher/event_publisher.c
new file mode 100644
index 0000000000..96717eecab
--- /dev/null
+++ b/samples/simple/wasm-apps/event_publisher/event_publisher.c
@@ -0,0 +1,57 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm_app.h"
+
+int num = 0;
+
+void publish_overheat_event()
+{
+ attr_container_t *event;
+
+ event = attr_container_create("event");
+ attr_container_set_string(&event, "warning", "temperature is over high");
+
+ api_publish_event("alert/overheat", FMT_ATTR_CONTAINER, event,
+ attr_container_get_serialize_length(event));
+
+ attr_container_destroy(event);
+}
+
+/* Timer callback */
+void timer1_update(user_timer_t timer)
+{
+ publish_overheat_event();
+}
+
+void start_timer()
+{
+ user_timer_t timer;
+
+ /* set up a timer */
+ timer = api_timer_create(1000, true, false, timer1_update);
+ api_timer_restart(timer, 1000);
+}
+
+void on_init()
+{
+ start_timer();
+}
+
+void on_destroy()
+{
+ /* real destroy work including killing timer and closing sensor is accomplished in wasm app library version of on_destroy() */
+}
diff --git a/samples/simple/wasm-apps/event_subscriber/event_subscriber.c b/samples/simple/wasm-apps/event_subscriber/event_subscriber.c
new file mode 100644
index 0000000000..aea0d77ffb
--- /dev/null
+++ b/samples/simple/wasm-apps/event_subscriber/event_subscriber.c
@@ -0,0 +1,36 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm_app.h"
+
+void over_heat_event_handler(request_t *request)
+{
+ printf("### user over heat event handler called\n");
+
+ if (request->payload != NULL && request->fmt == FMT_ATTR_CONTAINER)
+ attr_container_dump((attr_container_t *) request->payload);
+}
+
+void on_init()
+{
+ api_subscribe_event("alert/overheat", over_heat_event_handler);
+}
+
+void on_destroy()
+{
+ /* real destroy work including killing timer and closing sensor is
+ accomplished in wasm app library version of on_destroy() */
+}
diff --git a/samples/simple/wasm-apps/request_handler/request_handler.c b/samples/simple/wasm-apps/request_handler/request_handler.c
new file mode 100644
index 0000000000..b4820930d4
--- /dev/null
+++ b/samples/simple/wasm-apps/request_handler/request_handler.c
@@ -0,0 +1,67 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm_app.h"
+
+static void url1_request_handler(request_t *request)
+{
+ response_t response[1];
+ attr_container_t *payload;
+
+ printf("[resp] ### user resource 1 handler called\n");
+
+ if (request->payload != NULL && request->fmt == FMT_ATTR_CONTAINER)
+ attr_container_dump((attr_container_t *) request->payload);
+
+ payload = attr_container_create("wasm app response payload");
+ if (payload == NULL)
+ return;
+
+ attr_container_set_string(&payload, "key1", "value1");
+ attr_container_set_string(&payload, "key2", "value2");
+
+ make_response_for_request(request, response);
+ set_response(response, CONTENT_2_05,
+ FMT_ATTR_CONTAINER,
+ (void *)payload,
+ attr_container_get_serialize_length(payload));
+ api_response_send(response);
+
+ attr_container_destroy(payload);
+}
+
+static void url2_request_handler(request_t *request)
+{
+ response_t response[1];
+ make_response_for_request(request, response);
+ set_response(response, DELETED_2_02, 0, NULL, 0);
+ api_response_send(response);
+
+ printf("### user resource 2 handler called\n");
+}
+
+void on_init()
+{
+ /* register resource uri */
+ api_register_resource_handler("/url1", url1_request_handler);
+ api_register_resource_handler("/url2", url2_request_handler);
+}
+
+void on_destroy()
+{
+ /* real destroy work including killing timer and closing sensor is
+ accomplished in wasm app library version of on_destroy() */
+}
diff --git a/samples/simple/wasm-apps/request_sender/request_sender.c b/samples/simple/wasm-apps/request_sender/request_sender.c
new file mode 100644
index 0000000000..f1a9952bdc
--- /dev/null
+++ b/samples/simple/wasm-apps/request_sender/request_sender.c
@@ -0,0 +1,58 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm_app.h"
+
+static void my_response_handler(response_t *response, void *user_data)
+{
+ char *tag = (char *) user_data;
+
+ if (response == NULL) {
+ printf("[req] request timeout!\n");
+ return;
+ }
+
+ printf("[req] response handler called mid:%d, status:%d, fmt:%d, payload:%p, len:%d, tag:%s\n",
+ response->mid, response->status, response->fmt, response->payload,
+ response->payload_len, tag);
+
+ if (response->payload != NULL
+ && response->payload_len > 0
+ && response->fmt == FMT_ATTR_CONTAINER) {
+ printf("[req] dump the response payload:\n");
+ attr_container_dump((attr_container_t *) response->payload);
+ }
+}
+
+static void test_send_request(char *url, char *tag)
+{
+ request_t request[1];
+
+ init_request(request, url, COAP_PUT, 0, NULL, 0);
+ api_send_request(request, my_response_handler, tag);
+}
+
+void on_init()
+{
+ test_send_request("/app/request_handler/url1", "a request to target app");
+ test_send_request("url1", "a general request");
+}
+
+void on_destroy()
+{
+ /* real destroy work including killing timer and closing sensor is
+ accomplished in wasm app library version of on_destroy() */
+}
diff --git a/samples/simple/wasm-apps/sensor/sensor.c b/samples/simple/wasm-apps/sensor/sensor.c
new file mode 100644
index 0000000000..32705889a6
--- /dev/null
+++ b/samples/simple/wasm-apps/sensor/sensor.c
@@ -0,0 +1,59 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm_app.h"
+
+static sensor_t sensor = NULL;
+
+/* Sensor event callback*/
+void sensor_event_handler(sensor_t sensor, attr_container_t *event,
+ void *user_data)
+{
+ printf("### app get sensor event\n");
+ attr_container_dump(event);
+}
+
+void on_init()
+{
+ char *user_data;
+ attr_container_t *config;
+
+ printf("### app on_init 1\n");
+ /* open a sensor */
+ user_data = malloc(100);
+ printf("### app on_init 2\n");
+ sensor = sensor_open("sensor_test", 0, sensor_event_handler, user_data);
+ printf("### app on_init 3\n");
+
+ /* config the sensor */
+ sensor_config(sensor, 1000, 0, 0);
+ printf("### app on_init 4\n");
+
+ /*
+ config = attr_container_create("sensor config");
+ sensor_config(sensor, config);
+ attr_container_destroy(config);
+ */
+}
+
+void on_destroy()
+{
+ if (NULL != sensor) {
+ sensor_config(sensor, 0, 0, 0);
+ }
+ /* real destroy work including killing timer and closing sensor is
+ accomplished in wasm app library version of on_destroy() */
+}
diff --git a/samples/simple/wasm-apps/timer/timer.c b/samples/simple/wasm-apps/timer/timer.c
new file mode 100644
index 0000000000..d6605fe4e2
--- /dev/null
+++ b/samples/simple/wasm-apps/timer/timer.c
@@ -0,0 +1,41 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "wasm_app.h"
+
+/* User global variable */
+static int num = 0;
+
+/* Timer callback */
+void timer1_update(user_timer_t timer)
+{
+ printf("Timer update %d\n", num++);
+}
+
+void on_init()
+{
+ user_timer_t timer;
+
+ /* set up a timer */
+ timer = api_timer_create(1000, true, false, timer1_update);
+ api_timer_restart(timer, 1000);
+}
+
+void on_destroy()
+{
+ /* real destroy work including killing timer and closing sensor is
+ accomplished in wasm app library version of on_destroy() */
+}
diff --git a/test-tools/host-tool/CMakeLists.txt b/test-tools/host-tool/CMakeLists.txt
new file mode 100644
index 0000000000..00a4cd82ac
--- /dev/null
+++ b/test-tools/host-tool/CMakeLists.txt
@@ -0,0 +1,71 @@
+# Copyright (C) 2019 Intel Corporation. All rights reserved.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# http://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+cmake_minimum_required (VERSION 2.8.3)
+project (host-agent)
+
+if (NOT CMAKE_BUILD_TYPE)
+ SET(CMAKE_BUILD_TYPE Debug)
+endif (NOT CMAKE_BUILD_TYPE)
+
+if (NOT TARGET_PLATFORM)
+ set (TARGET_PLATFORM "linux")
+endif (NOT TARGET_PLATFORM)
+
+message ("TARGET_PLATFORM = " ${TARGET_PLATFORM})
+
+set(REPO_ROOT_DIR ${CMAKE_CURRENT_LIST_DIR}/../..)
+set(WASM_DIR ${REPO_ROOT_DIR}/core/iwasm)
+set(APP_MGR_DIR ${REPO_ROOT_DIR}/core/app-mgr)
+set(SHARED_DIR ${REPO_ROOT_DIR}/core/shared-lib)
+#TODO: use soft-plc/tools/iec-runtime/external/cJSON instead
+set(CJSON_DIR ${CMAKE_CURRENT_LIST_DIR}/external/cJSON)
+set(SSG_LIB_DIR ${REPO_ROOT_DIR}/../host-agent/lib)
+
+include (${WASM_DIR}/lib/native-interface/native_interface.cmake)
+include (${APP_MGR_DIR}/app-mgr-shared/app_mgr_shared.cmake)
+include (${SHARED_DIR}/platform/${TARGET_PLATFORM}/shared_platform.cmake)
+include (${SHARED_DIR}/utils/shared_utils.cmake)
+include (${SHARED_DIR}/mem-alloc/mem_alloc.cmake)
+include (${CJSON_DIR}/cjson.cmake)
+include (${SHARED_DIR}/coap/lib_coap.cmake)
+include (${SSG_LIB_DIR}/host_agent_lib.cmake)
+
+if (CMAKE_SIZEOF_VOID_P EQUAL 8)
+ SET(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -m32")
+ SET(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} -m32")
+endif ()
+
+add_definitions(-Wall -Wno-pointer-sign -DMALLOC_MEMORY_FROM_SYSTEM)
+
+include_directories(
+ ${CMAKE_CURRENT_LIST_DIR}/src
+)
+
+file (GLOB_RECURSE HOST_TOOL_SRC src/*.c)
+
+
+SET(SOURCES
+ ${HOST_TOOL_SRC}
+ ${PLATFORM_SHARED_SOURCE}
+ ${UTILS_SHARED_SOURCE}
+ ${MEM_ALLOC_DIR}/bh_memory.c
+ ${NATIVE_INTERFACE_SOURCE}
+ ${CJSON_SOURCE}
+ ${LIB_HOST_AGENT_SOURCE}
+ )
+
+add_executable(host_tool ${SOURCES})
+target_link_libraries(host_tool pthread)
diff --git a/test-tools/host-tool/external/cJSON/LICENSE b/test-tools/host-tool/external/cJSON/LICENSE
new file mode 100644
index 0000000000..78deb0406d
--- /dev/null
+++ b/test-tools/host-tool/external/cJSON/LICENSE
@@ -0,0 +1,20 @@
+Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+Permission is hereby granted, free of charge, to any person obtaining a copy
+of this software and associated documentation files (the "Software"), to deal
+in the Software without restriction, including without limitation the rights
+to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+copies of the Software, and to permit persons to whom the Software is
+furnished to do so, subject to the following conditions:
+
+The above copyright notice and this permission notice shall be included in
+all copies or substantial portions of the Software.
+
+THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+THE SOFTWARE.
+
diff --git a/test-tools/host-tool/external/cJSON/cJSON.c b/test-tools/host-tool/external/cJSON/cJSON.c
new file mode 100644
index 0000000000..2776ce6715
--- /dev/null
+++ b/test-tools/host-tool/external/cJSON/cJSON.c
@@ -0,0 +1,2750 @@
+/*
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+/* cJSON */
+/* JSON parser in C. */
+
+/* disable warnings about old C89 functions in MSVC */
+#if !defined(_CRT_SECURE_NO_DEPRECATE) && defined(_MSC_VER)
+#define _CRT_SECURE_NO_DEPRECATE
+#endif
+
+#ifdef __GNUC__
+#pragma GCC visibility push(default)
+#endif
+#if defined(_MSC_VER)
+#pragma warning (push)
+/* disable warning about single line comments in system headers */
+#pragma warning (disable : 4001)
+#endif
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#ifdef ENABLE_LOCALES
+#include
+#endif
+
+#if defined(_MSC_VER)
+#pragma warning (pop)
+#endif
+#ifdef __GNUC__
+#pragma GCC visibility pop
+#endif
+
+#include "cJSON.h"
+
+/* define our own boolean type */
+#define true ((cJSON_bool)1)
+#define false ((cJSON_bool)0)
+
+typedef struct {
+ const unsigned char *json;
+ size_t position;
+} error;
+static error global_error = { NULL, 0 };
+
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void)
+{
+ return (const char*) (global_error.json + global_error.position);
+}
+
+CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item) {
+ if (!cJSON_IsString(item)) {
+ return NULL;
+ }
+
+ return item->valuestring;
+}
+
+/* This is a safeguard to prevent copy-pasters from using incompatible C and header files */
+#if (CJSON_VERSION_MAJOR != 1) || (CJSON_VERSION_MINOR != 7) || (CJSON_VERSION_PATCH != 10)
+#error cJSON.h and cJSON.c have different versions. Make sure that both have the same.
+#endif
+
+CJSON_PUBLIC(const char*) cJSON_Version(void)
+{
+ static char version[15];
+ sprintf(version, "%i.%i.%i", CJSON_VERSION_MAJOR, CJSON_VERSION_MINOR, CJSON_VERSION_PATCH);
+
+ return version;
+}
+
+/* Case insensitive string comparison, doesn't consider two NULL pointers equal though */
+static int case_insensitive_strcmp(const unsigned char *string1,
+ const unsigned char *string2)
+{
+ if ((string1 == NULL) || (string2 == NULL)) {
+ return 1;
+ }
+
+ if (string1 == string2) {
+ return 0;
+ }
+
+ for (; tolower(*string1) == tolower(*string2);
+ (void) string1++, string2++) {
+ if (*string1 == '\0') {
+ return 0;
+ }
+ }
+
+ return tolower(*string1) - tolower(*string2);
+}
+
+typedef struct internal_hooks {
+ void *(CJSON_CDECL *allocate)(size_t size);
+ void (CJSON_CDECL *deallocate)(void *pointer);
+ void *(CJSON_CDECL *reallocate)(void *pointer, size_t size);
+} internal_hooks;
+
+#if defined(_MSC_VER)
+/* work around MSVC error C2322: '...' address of dillimport '...' is not static */
+static void * CJSON_CDECL internal_malloc(size_t size)
+{
+ return malloc(size);
+}
+static void CJSON_CDECL internal_free(void *pointer)
+{
+ free(pointer);
+}
+static void * CJSON_CDECL internal_realloc(void *pointer, size_t size)
+{
+ return realloc(pointer, size);
+}
+#else
+#define internal_malloc malloc
+#define internal_free free
+#define internal_realloc realloc
+#endif
+
+static internal_hooks global_hooks = { internal_malloc, internal_free,
+internal_realloc };
+
+static unsigned char* cJSON_strdup(const unsigned char* string,
+ const internal_hooks * const hooks)
+{
+ size_t length = 0;
+ unsigned char *copy = NULL;
+
+ if (string == NULL) {
+ return NULL;
+ }
+
+ length = strlen((const char*) string) + sizeof("");
+ copy = (unsigned char*) hooks->allocate(length);
+ if (copy == NULL) {
+ return NULL;
+ }
+ memcpy(copy, string, length);
+
+ return copy;
+}
+
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks)
+{
+ if (hooks == NULL) {
+ /* Reset hooks */
+ global_hooks.allocate = malloc;
+ global_hooks.deallocate = free;
+ global_hooks.reallocate = realloc;
+ return;
+ }
+
+ global_hooks.allocate = malloc;
+ if (hooks->malloc_fn != NULL) {
+ global_hooks.allocate = hooks->malloc_fn;
+ }
+
+ global_hooks.deallocate = free;
+ if (hooks->free_fn != NULL) {
+ global_hooks.deallocate = hooks->free_fn;
+ }
+
+ /* use realloc only if both free and malloc are used */
+ global_hooks.reallocate = NULL;
+ if ((global_hooks.allocate == malloc)
+ && (global_hooks.deallocate == free)) {
+ global_hooks.reallocate = realloc;
+ }
+}
+
+/* Internal constructor. */
+static cJSON *cJSON_New_Item(const internal_hooks * const hooks)
+{
+ cJSON* node = (cJSON*) hooks->allocate(sizeof(cJSON));
+ if (node) {
+ memset(node, '\0', sizeof(cJSON));
+ }
+
+ return node;
+}
+
+/* Delete a cJSON structure. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *item)
+{
+ cJSON *next = NULL;
+ while (item != NULL) {
+ next = item->next;
+ if (!(item->type & cJSON_IsReference) && (item->child != NULL)) {
+ cJSON_Delete(item->child);
+ }
+ if (!(item->type & cJSON_IsReference) && (item->valuestring != NULL)) {
+ global_hooks.deallocate(item->valuestring);
+ }
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
+ global_hooks.deallocate(item->string);
+ }
+ global_hooks.deallocate(item);
+ item = next;
+ }
+}
+
+/* get the decimal point character of the current locale */
+static unsigned char get_decimal_point(void)
+{
+#ifdef ENABLE_LOCALES
+ struct lconv *lconv = localeconv();
+ return (unsigned char) lconv->decimal_point[0];
+#else
+ return '.';
+#endif
+}
+
+typedef struct {
+ const unsigned char *content;
+ size_t length;
+ size_t offset;
+ size_t depth; /* How deeply nested (in arrays/objects) is the input at the current offset. */
+ internal_hooks hooks;
+} parse_buffer;
+
+/* check if the given size is left to read in a given parse buffer (starting with 1) */
+#define can_read(buffer, size) ((buffer != NULL) && (((buffer)->offset + size) <= (buffer)->length))
+/* check if the buffer can be accessed at the given index (starting with 0) */
+#define can_access_at_index(buffer, index) ((buffer != NULL) && (((buffer)->offset + index) < (buffer)->length))
+#define cannot_access_at_index(buffer, index) (!can_access_at_index(buffer, index))
+/* get a pointer to the buffer at the position */
+#define buffer_at_offset(buffer) ((buffer)->content + (buffer)->offset)
+
+/* Parse the input text to generate a number, and populate the result into item. */
+static cJSON_bool parse_number(cJSON * const item,
+ parse_buffer * const input_buffer)
+{
+ double number = 0;
+ unsigned char *after_end = NULL;
+ unsigned char number_c_string[64];
+ unsigned char decimal_point = get_decimal_point();
+ size_t i = 0;
+
+ if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
+ return false;
+ }
+
+ /* copy the number into a temporary buffer and replace '.' with the decimal point
+ * of the current locale (for strtod)
+ * This also takes care of '\0' not necessarily being available for marking the end of the input */
+ for (i = 0;
+ (i < (sizeof(number_c_string) - 1))
+ && can_access_at_index(input_buffer, i); i++) {
+ switch (buffer_at_offset(input_buffer)[i]) {
+ case '0':
+ case '1':
+ case '2':
+ case '3':
+ case '4':
+ case '5':
+ case '6':
+ case '7':
+ case '8':
+ case '9':
+ case '+':
+ case '-':
+ case 'e':
+ case 'E':
+ number_c_string[i] = buffer_at_offset(input_buffer)[i];
+ break;
+
+ case '.':
+ number_c_string[i] = decimal_point;
+ break;
+
+ default:
+ goto loop_end;
+ }
+ }
+ loop_end: number_c_string[i] = '\0';
+
+ number = strtod((const char*) number_c_string, (char**) &after_end);
+ if (number_c_string == after_end) {
+ return false; /* parse_error */
+ }
+
+ item->valuedouble = number;
+
+ /* use saturation in case of overflow */
+ if (number >= INT_MAX) {
+ item->valueint = INT_MAX;
+ } else if (number <= (double) INT_MIN) {
+ item->valueint = INT_MIN;
+ } else {
+ item->valueint = (int) number;
+ }
+
+ item->type = cJSON_Number;
+
+ input_buffer->offset += (size_t)(after_end - number_c_string);
+ return true;
+}
+
+/* don't ask me, but the original cJSON_SetNumberValue returns an integer or double */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number)
+{
+ if (number >= INT_MAX) {
+ object->valueint = INT_MAX;
+ } else if (number <= (double) INT_MIN) {
+ object->valueint = INT_MIN;
+ } else {
+ object->valueint = (int) number;
+ }
+
+ return object->valuedouble = number;
+}
+
+typedef struct {
+ unsigned char *buffer;
+ size_t length;
+ size_t offset;
+ size_t depth; /* current nesting depth (for formatted printing) */
+ cJSON_bool noalloc;
+ cJSON_bool format; /* is this print a formatted print */
+ internal_hooks hooks;
+} printbuffer;
+
+/* realloc printbuffer if necessary to have at least "needed" bytes more */
+static unsigned char* ensure(printbuffer * const p, size_t needed)
+{
+ unsigned char *newbuffer = NULL;
+ size_t newsize = 0;
+
+ if ((p == NULL) || (p->buffer == NULL)) {
+ return NULL;
+ }
+
+ if ((p->length > 0) && (p->offset >= p->length)) {
+ /* make sure that offset is valid */
+ return NULL;
+ }
+
+ if (needed > INT_MAX) {
+ /* sizes bigger than INT_MAX are currently not supported */
+ return NULL;
+ }
+
+ needed += p->offset + 1;
+ if (needed <= p->length) {
+ return p->buffer + p->offset;
+ }
+
+ if (p->noalloc) {
+ return NULL;
+ }
+
+ /* calculate new buffer size */
+ if (needed > (INT_MAX / 2)) {
+ /* overflow of int, use INT_MAX if possible */
+ if (needed <= INT_MAX) {
+ newsize = INT_MAX;
+ } else {
+ return NULL;
+ }
+ } else {
+ newsize = needed * 2;
+ }
+
+ if (p->hooks.reallocate != NULL) {
+ /* reallocate with realloc if available */
+ newbuffer = (unsigned char*) p->hooks.reallocate(p->buffer, newsize);
+ if (newbuffer == NULL) {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ } else {
+ /* otherwise reallocate manually */
+ newbuffer = (unsigned char*) p->hooks.allocate(newsize);
+ if (!newbuffer) {
+ p->hooks.deallocate(p->buffer);
+ p->length = 0;
+ p->buffer = NULL;
+
+ return NULL;
+ }
+ if (newbuffer) {
+ memcpy(newbuffer, p->buffer, p->offset + 1);
+ }
+ p->hooks.deallocate(p->buffer);
+ }
+ p->length = newsize;
+ p->buffer = newbuffer;
+
+ return newbuffer + p->offset;
+}
+
+/* calculate the new length of the string in a printbuffer and update the offset */
+static void update_offset(printbuffer * const buffer)
+{
+ const unsigned char *buffer_pointer = NULL;
+ if ((buffer == NULL) || (buffer->buffer == NULL)) {
+ return;
+ }
+ buffer_pointer = buffer->buffer + buffer->offset;
+
+ buffer->offset += strlen((const char*) buffer_pointer);
+}
+
+/* Render the number nicely from the given item into a string. */
+static cJSON_bool print_number(const cJSON * const item,
+ printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ double d = item->valuedouble;
+ int length = 0;
+ size_t i = 0;
+ unsigned char number_buffer[26]; /* temporary buffer to print the number into */
+ unsigned char decimal_point = get_decimal_point();
+ double test;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* This checks for NaN and Infinity */
+ if ((d * 0) != 0) {
+ length = sprintf((char*) number_buffer, "null");
+ } else {
+ /* Try 15 decimal places of precision to avoid nonsignificant nonzero digits */
+ length = sprintf((char*) number_buffer, "%1.15g", d);
+
+ /* Check whether the original double can be recovered */
+ if ((sscanf((char*) number_buffer, "%lg", &test) != 1)
+ || ((double) test != d)) {
+ /* If not, print with 17 decimal places of precision */
+ length = sprintf((char*) number_buffer, "%1.17g", d);
+ }
+ }
+
+ /* sprintf failed or buffer overrun occured */
+ if ((length < 0) || (length > (int) (sizeof(number_buffer) - 1))) {
+ return false;
+ }
+
+ /* reserve appropriate space in the output */
+ output_pointer = ensure(output_buffer, (size_t) length + sizeof(""));
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ /* copy the printed number to the output and replace locale
+ * dependent decimal point with '.' */
+ for (i = 0; i < ((size_t) length); i++) {
+ if (number_buffer[i] == decimal_point) {
+ output_pointer[i] = '.';
+ continue;
+ }
+
+ output_pointer[i] = number_buffer[i];
+ }
+ output_pointer[i] = '\0';
+
+ output_buffer->offset += (size_t) length;
+
+ return true;
+}
+
+/* parse 4 digit hexadecimal number */
+static unsigned parse_hex4(const unsigned char * const input)
+{
+ unsigned int h = 0;
+ size_t i = 0;
+
+ for (i = 0; i < 4; i++) {
+ /* parse digit */
+ if ((input[i] >= '0') && (input[i] <= '9')) {
+ h += (unsigned int) input[i] - '0';
+ } else if ((input[i] >= 'A') && (input[i] <= 'F')) {
+ h += (unsigned int) 10 + input[i] - 'A';
+ } else if ((input[i] >= 'a') && (input[i] <= 'f')) {
+ h += (unsigned int) 10 + input[i] - 'a';
+ } else /* invalid */
+ {
+ return 0;
+ }
+
+ if (i < 3) {
+ /* shift left to make place for the next nibble */
+ h = h << 4;
+ }
+ }
+
+ return h;
+}
+
+/* converts a UTF-16 literal to UTF-8
+ * A literal can be one or two sequences of the form \uXXXX */
+static unsigned char utf16_literal_to_utf8(
+ const unsigned char * const input_pointer,
+ const unsigned char * const input_end, unsigned char **output_pointer)
+{
+ long unsigned int codepoint = 0;
+ unsigned int first_code = 0;
+ const unsigned char *first_sequence = input_pointer;
+ unsigned char utf8_length = 0;
+ unsigned char utf8_position = 0;
+ unsigned char sequence_length = 0;
+ unsigned char first_byte_mark = 0;
+
+ if ((input_end - first_sequence) < 6) {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ /* get the first utf16 sequence */
+ first_code = parse_hex4(first_sequence + 2);
+
+ /* check that the code is valid */
+ if (((first_code >= 0xDC00) && (first_code <= 0xDFFF))) {
+ goto fail;
+ }
+
+ /* UTF16 surrogate pair */
+ if ((first_code >= 0xD800) && (first_code <= 0xDBFF)) {
+ const unsigned char *second_sequence = first_sequence + 6;
+ unsigned int second_code = 0;
+ sequence_length = 12; /* \uXXXX\uXXXX */
+
+ if ((input_end - second_sequence) < 6) {
+ /* input ends unexpectedly */
+ goto fail;
+ }
+
+ if ((second_sequence[0] != '\\') || (second_sequence[1] != 'u')) {
+ /* missing second half of the surrogate pair */
+ goto fail;
+ }
+
+ /* get the second utf16 sequence */
+ second_code = parse_hex4(second_sequence + 2);
+ /* check that the code is valid */
+ if ((second_code < 0xDC00) || (second_code > 0xDFFF)) {
+ /* invalid second half of the surrogate pair */
+ goto fail;
+ }
+
+ /* calculate the unicode codepoint from the surrogate pair */
+ codepoint = 0x10000
+ + (((first_code & 0x3FF) << 10) | (second_code & 0x3FF));
+ } else {
+ sequence_length = 6; /* \uXXXX */
+ codepoint = first_code;
+ }
+
+ /* encode as UTF-8
+ * takes at maximum 4 bytes to encode:
+ * 11110xxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ if (codepoint < 0x80) {
+ /* normal ascii, encoding 0xxxxxxx */
+ utf8_length = 1;
+ } else if (codepoint < 0x800) {
+ /* two bytes, encoding 110xxxxx 10xxxxxx */
+ utf8_length = 2;
+ first_byte_mark = 0xC0; /* 11000000 */
+ } else if (codepoint < 0x10000) {
+ /* three bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 3;
+ first_byte_mark = 0xE0; /* 11100000 */
+ } else if (codepoint <= 0x10FFFF) {
+ /* four bytes, encoding 1110xxxx 10xxxxxx 10xxxxxx 10xxxxxx */
+ utf8_length = 4;
+ first_byte_mark = 0xF0; /* 11110000 */
+ } else {
+ /* invalid unicode codepoint */
+ goto fail;
+ }
+
+ /* encode as utf8 */
+ for (utf8_position = (unsigned char) (utf8_length - 1); utf8_position > 0;
+ utf8_position--) {
+ /* 10xxxxxx */
+ (*output_pointer)[utf8_position] = (unsigned char) ((codepoint | 0x80)
+ & 0xBF);
+ codepoint >>= 6;
+ }
+ /* encode first byte */
+ if (utf8_length > 1) {
+ (*output_pointer)[0] = (unsigned char) ((codepoint | first_byte_mark)
+ & 0xFF);
+ } else {
+ (*output_pointer)[0] = (unsigned char) (codepoint & 0x7F);
+ }
+
+ *output_pointer += utf8_length;
+
+ return sequence_length;
+
+ fail: return 0;
+}
+
+/* Parse the input text into an unescaped cinput, and populate item. */
+static cJSON_bool parse_string(cJSON * const item,
+ parse_buffer * const input_buffer)
+{
+ const unsigned char *input_pointer = buffer_at_offset(input_buffer) + 1;
+ const unsigned char *input_end = buffer_at_offset(input_buffer) + 1;
+ unsigned char *output_pointer = NULL;
+ unsigned char *output = NULL;
+
+ /* not a string */
+ if (buffer_at_offset(input_buffer)[0] != '\"') {
+ goto fail;
+ }
+
+ {
+ /* calculate approximate size of the output (overestimate) */
+ size_t allocation_length = 0;
+ size_t skipped_bytes = 0;
+ while (((size_t)(input_end - input_buffer->content)
+ < input_buffer->length) && (*input_end != '\"')) {
+ /* is escape sequence */
+ if (input_end[0] == '\\') {
+ if ((size_t)(input_end + 1 - input_buffer->content)
+ >= input_buffer->length) {
+ /* prevent buffer overflow when last input character is a backslash */
+ goto fail;
+ }
+ skipped_bytes++;
+ input_end++;
+ }
+ input_end++;
+ }
+ if (((size_t)(input_end - input_buffer->content) >= input_buffer->length)
+ || (*input_end != '\"')) {
+ goto fail;
+ /* string ended unexpectedly */
+ }
+
+ /* This is at most how much we need for the output */
+ allocation_length = (size_t)(input_end - buffer_at_offset(input_buffer))
+ - skipped_bytes;
+ output = (unsigned char*) input_buffer->hooks.allocate(
+ allocation_length + sizeof(""));
+ if (output == NULL) {
+ goto fail;
+ /* allocation failure */
+ }
+ }
+
+ output_pointer = output;
+ /* loop through the string literal */
+ while (input_pointer < input_end) {
+ if (*input_pointer != '\\') {
+ *output_pointer++ = *input_pointer++;
+ }
+ /* escape sequence */
+ else {
+ unsigned char sequence_length = 2;
+ if ((input_end - input_pointer) < 1) {
+ goto fail;
+ }
+
+ switch (input_pointer[1]) {
+ case 'b':
+ *output_pointer++ = '\b';
+ break;
+ case 'f':
+ *output_pointer++ = '\f';
+ break;
+ case 'n':
+ *output_pointer++ = '\n';
+ break;
+ case 'r':
+ *output_pointer++ = '\r';
+ break;
+ case 't':
+ *output_pointer++ = '\t';
+ break;
+ case '\"':
+ case '\\':
+ case '/':
+ *output_pointer++ = input_pointer[1];
+ break;
+
+ /* UTF-16 literal */
+ case 'u':
+ sequence_length = utf16_literal_to_utf8(input_pointer,
+ input_end, &output_pointer);
+ if (sequence_length == 0) {
+ /* failed to convert UTF16-literal to UTF-8 */
+ goto fail;
+ }
+ break;
+
+ default:
+ goto fail;
+ }
+ input_pointer += sequence_length;
+ }
+ }
+
+ /* zero terminate the output */
+ *output_pointer = '\0';
+
+ item->type = cJSON_String;
+ item->valuestring = (char*) output;
+
+ input_buffer->offset = (size_t)(input_end - input_buffer->content);
+ input_buffer->offset++;
+
+ return true;
+
+ fail: if (output != NULL) {
+ input_buffer->hooks.deallocate(output);
+ }
+
+ if (input_pointer != NULL) {
+ input_buffer->offset = (size_t)(input_pointer - input_buffer->content);
+ }
+
+ return false;
+}
+
+/* Render the cstring provided to an escaped version that can be printed. */
+static cJSON_bool print_string_ptr(const unsigned char * const input,
+ printbuffer * const output_buffer)
+{
+ const unsigned char *input_pointer = NULL;
+ unsigned char *output = NULL;
+ unsigned char *output_pointer = NULL;
+ size_t output_length = 0;
+ /* numbers of additional characters needed for escaping */
+ size_t escape_characters = 0;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* empty string */
+ if (input == NULL) {
+ output = ensure(output_buffer, sizeof("\"\""));
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char*) output, "\"\"");
+
+ return true;
+ }
+
+ /* set "flag" to 1 if something needs to be escaped */
+ for (input_pointer = input; *input_pointer; input_pointer++) {
+ switch (*input_pointer) {
+ case '\"':
+ case '\\':
+ case '\b':
+ case '\f':
+ case '\n':
+ case '\r':
+ case '\t':
+ /* one character escape sequence */
+ escape_characters++;
+ break;
+ default:
+ if (*input_pointer < 32) {
+ /* UTF-16 escape sequence uXXXX */
+ escape_characters += 5;
+ }
+ break;
+ }
+ }
+ output_length = (size_t)(input_pointer - input) + escape_characters;
+
+ output = ensure(output_buffer, output_length + sizeof("\"\""));
+ if (output == NULL) {
+ return false;
+ }
+
+ /* no characters have to be escaped */
+ if (escape_characters == 0) {
+ output[0] = '\"';
+ memcpy(output + 1, input, output_length);
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+ }
+
+ output[0] = '\"';
+ output_pointer = output + 1;
+ /* copy the string */
+ for (input_pointer = input; *input_pointer != '\0';
+ (void) input_pointer++, output_pointer++) {
+ if ((*input_pointer > 31) && (*input_pointer != '\"')
+ && (*input_pointer != '\\')) {
+ /* normal character, copy */
+ *output_pointer = *input_pointer;
+ } else {
+ /* character needs to be escaped */
+ *output_pointer++ = '\\';
+ switch (*input_pointer) {
+ case '\\':
+ *output_pointer = '\\';
+ break;
+ case '\"':
+ *output_pointer = '\"';
+ break;
+ case '\b':
+ *output_pointer = 'b';
+ break;
+ case '\f':
+ *output_pointer = 'f';
+ break;
+ case '\n':
+ *output_pointer = 'n';
+ break;
+ case '\r':
+ *output_pointer = 'r';
+ break;
+ case '\t':
+ *output_pointer = 't';
+ break;
+ default:
+ /* escape and print as unicode codepoint */
+ sprintf((char*) output_pointer, "u%04x", *input_pointer);
+ output_pointer += 4;
+ break;
+ }
+ }
+ }
+ output[output_length + 1] = '\"';
+ output[output_length + 2] = '\0';
+
+ return true;
+}
+
+/* Invoke print_string_ptr (which is useful) on an item. */
+static cJSON_bool print_string(const cJSON * const item, printbuffer * const p)
+{
+ return print_string_ptr((unsigned char*) item->valuestring, p);
+}
+
+/* Predeclare these prototypes. */
+static cJSON_bool parse_value(cJSON * const item,
+ parse_buffer * const input_buffer);
+static cJSON_bool print_value(const cJSON * const item,
+ printbuffer * const output_buffer);
+static cJSON_bool parse_array(cJSON * const item,
+ parse_buffer * const input_buffer);
+static cJSON_bool print_array(const cJSON * const item,
+ printbuffer * const output_buffer);
+static cJSON_bool parse_object(cJSON * const item,
+ parse_buffer * const input_buffer);
+static cJSON_bool print_object(const cJSON * const item,
+ printbuffer * const output_buffer);
+
+/* Utility to jump whitespace and cr/lf */
+static parse_buffer *buffer_skip_whitespace(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL)) {
+ return NULL;
+ }
+
+ while (can_access_at_index(buffer, 0) && (buffer_at_offset(buffer)[0] <= 32)) {
+ buffer->offset++;
+ }
+
+ if (buffer->offset == buffer->length) {
+ buffer->offset--;
+ }
+
+ return buffer;
+}
+
+/* skip the UTF-8 BOM (byte order mark) if it is at the beginning of a buffer */
+static parse_buffer *skip_utf8_bom(parse_buffer * const buffer)
+{
+ if ((buffer == NULL) || (buffer->content == NULL)
+ || (buffer->offset != 0)) {
+ return NULL;
+ }
+
+ if (can_access_at_index(buffer, 4)
+ && (strncmp((const char*) buffer_at_offset(buffer), "\xEF\xBB\xBF",
+ 3) == 0)) {
+ buffer->offset += 3;
+ }
+
+ return buffer;
+}
+
+/* Parse an object - create a new root, and populate. */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated)
+{
+ parse_buffer buffer = {0, 0, 0, 0, {0, 0, 0}};
+ cJSON *item = NULL;
+
+ /* reset error position */
+ global_error.json = NULL;
+ global_error.position = 0;
+
+ if (value == NULL)
+ {
+ goto fail;
+ }
+
+ buffer.content = (const unsigned char*)value;
+ buffer.length = strlen((const char*)value) + sizeof("");
+ buffer.offset = 0;
+ buffer.hooks = global_hooks;
+
+ item = cJSON_New_Item(&global_hooks);
+ if (item == NULL) /* memory fail */
+ {
+ goto fail;
+ }
+
+ if (!parse_value(item, buffer_skip_whitespace(skip_utf8_bom(&buffer))))
+ {
+ /* parse failure. ep is set. */
+ goto fail;
+ }
+
+ /* if we require null-terminated JSON without appended garbage, skip and then check for a null terminator */
+ if (require_null_terminated)
+ {
+ buffer_skip_whitespace(&buffer);
+ if ((buffer.offset >= buffer.length) || buffer_at_offset(&buffer)[0] != '\0')
+ {
+ goto fail;
+ }
+ }
+ if (return_parse_end)
+ {
+ *return_parse_end = (const char*)buffer_at_offset(&buffer);
+ }
+
+ return item;
+
+ fail:
+ if (item != NULL)
+ {
+ cJSON_Delete(item);
+ }
+
+ if (value != NULL)
+ {
+ error local_error;
+ local_error.json = (const unsigned char*)value;
+ local_error.position = 0;
+
+ if (buffer.offset < buffer.length)
+ {
+ local_error.position = buffer.offset;
+ }
+ else if (buffer.length > 0)
+ {
+ local_error.position = buffer.length - 1;
+ }
+
+ if (return_parse_end != NULL)
+ {
+ *return_parse_end = (const char*)local_error.json + local_error.position;
+ }
+
+ global_error = local_error;
+ }
+
+ return NULL;
+}
+
+/* Default options for cJSON_Parse */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value)
+{
+ return cJSON_ParseWithOpts(value, 0, 0);
+}
+
+#define cjson_min(a, b) ((a < b) ? a : b)
+
+static unsigned char *print(const cJSON * const item, cJSON_bool format,
+ const internal_hooks * const hooks)
+{
+ static const size_t default_buffer_size = 256;
+ printbuffer buffer[1];
+ unsigned char *printed = NULL;
+
+ memset(buffer, 0, sizeof(buffer));
+
+ /* create buffer */
+ buffer->buffer = (unsigned char*) hooks->allocate(default_buffer_size);
+ buffer->length = default_buffer_size;
+ buffer->format = format;
+ buffer->hooks = *hooks;
+ if (buffer->buffer == NULL) {
+ goto fail;
+ }
+
+ /* print the value */
+ if (!print_value(item, buffer)) {
+ goto fail;
+ }
+ update_offset(buffer);
+
+ /* check if reallocate is available */
+ if (hooks->reallocate != NULL) {
+ printed = (unsigned char*) hooks->reallocate(buffer->buffer,
+ buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ buffer->buffer = NULL;
+ } else /* otherwise copy the JSON over to a new buffer */
+ {
+ printed = (unsigned char*) hooks->allocate(buffer->offset + 1);
+ if (printed == NULL) {
+ goto fail;
+ }
+ memcpy(printed, buffer->buffer,
+ cjson_min(buffer->length, buffer->offset + 1));
+ printed[buffer->offset] = '\0'; /* just to be sure */
+
+ /* free the buffer */
+ hooks->deallocate(buffer->buffer);
+ }
+
+ return printed;
+
+ fail: if (buffer->buffer != NULL) {
+ hooks->deallocate(buffer->buffer);
+ }
+
+ if (printed != NULL) {
+ hooks->deallocate(printed);
+ }
+
+ return NULL;
+}
+
+/* Render a cJSON item/entity/structure to text. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item)
+{
+ return (char*)print(item, true, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item)
+{
+ return (char*)print(item, false, &global_hooks);
+}
+
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt)
+{
+ printbuffer p = {0, 0, 0, 0, 0, 0, {0, 0, 0}};
+
+ if (prebuffer < 0)
+ {
+ return NULL;
+ }
+
+ p.buffer = (unsigned char*)global_hooks.allocate((size_t)prebuffer);
+ if (!p.buffer)
+ {
+ return NULL;
+ }
+
+ p.length = (size_t)prebuffer;
+ p.offset = 0;
+ p.noalloc = false;
+ p.format = fmt;
+ p.hooks = global_hooks;
+
+ if (!print_value(item, &p))
+ {
+ global_hooks.deallocate(p.buffer);
+ return NULL;
+ }
+
+ return (char*)p.buffer;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buf,
+ const int len, const cJSON_bool fmt)
+{
+ printbuffer p = { 0, 0, 0, 0, 0, 0, { 0, 0, 0 } };
+
+ if ((len < 0) || (buf == NULL)) {
+ return false;
+ }
+
+ p.buffer = (unsigned char*) buf;
+ p.length = (size_t) len;
+ p.offset = 0;
+ p.noalloc = true;
+ p.format = fmt;
+ p.hooks = global_hooks;
+
+ return print_value(item, &p);
+}
+
+/* Parser core - when encountering text, process appropriately. */
+static cJSON_bool parse_value(cJSON * const item,
+ parse_buffer * const input_buffer)
+{
+ if ((input_buffer == NULL) || (input_buffer->content == NULL)) {
+ return false; /* no input */
+ }
+
+ /* parse the different types of values */
+ /* null */
+ if (can_read(input_buffer, 4)
+ && (strncmp((const char*) buffer_at_offset(input_buffer), "null", 4)
+ == 0)) {
+ item->type = cJSON_NULL;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* false */
+ if (can_read(input_buffer, 5)
+ && (strncmp((const char*) buffer_at_offset(input_buffer), "false",
+ 5) == 0)) {
+ item->type = cJSON_False;
+ input_buffer->offset += 5;
+ return true;
+ }
+ /* true */
+ if (can_read(input_buffer, 4)
+ && (strncmp((const char*) buffer_at_offset(input_buffer), "true", 4)
+ == 0)) {
+ item->type = cJSON_True;
+ item->valueint = 1;
+ input_buffer->offset += 4;
+ return true;
+ }
+ /* string */
+ if (can_access_at_index(input_buffer, 0)
+ && (buffer_at_offset(input_buffer)[0] == '\"')) {
+ return parse_string(item, input_buffer);
+ }
+ /* number */
+ if (can_access_at_index(input_buffer, 0)
+ && ((buffer_at_offset(input_buffer)[0] == '-')
+ || ((buffer_at_offset(input_buffer)[0] >= '0')
+ && (buffer_at_offset(input_buffer)[0] <= '9')))) {
+ return parse_number(item, input_buffer);
+ }
+ /* array */
+ if (can_access_at_index(input_buffer, 0)
+ && (buffer_at_offset(input_buffer)[0] == '[')) {
+ return parse_array(item, input_buffer);
+ }
+ /* object */
+ if (can_access_at_index(input_buffer, 0)
+ && (buffer_at_offset(input_buffer)[0] == '{')) {
+ return parse_object(item, input_buffer);
+ }
+
+ return false;
+}
+
+/* Render a value to text. */
+static cJSON_bool print_value(const cJSON * const item,
+ printbuffer * const output_buffer)
+{
+ unsigned char *output = NULL;
+
+ if ((item == NULL) || (output_buffer == NULL)) {
+ return false;
+ }
+
+ switch ((item->type) & 0xFF) {
+ case cJSON_NULL:
+ output = ensure(output_buffer, 5);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char*) output, "null");
+ return true;
+
+ case cJSON_False:
+ output = ensure(output_buffer, 6);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char*) output, "false");
+ return true;
+
+ case cJSON_True:
+ output = ensure(output_buffer, 5);
+ if (output == NULL) {
+ return false;
+ }
+ strcpy((char*) output, "true");
+ return true;
+
+ case cJSON_Number:
+ return print_number(item, output_buffer);
+
+ case cJSON_Raw: {
+ size_t raw_length = 0;
+ if (item->valuestring == NULL) {
+ return false;
+ }
+
+ raw_length = strlen(item->valuestring) + sizeof("");
+ output = ensure(output_buffer, raw_length);
+ if (output == NULL) {
+ return false;
+ }
+ memcpy(output, item->valuestring, raw_length);
+ return true;
+ }
+
+ case cJSON_String:
+ return print_string(item, output_buffer);
+
+ case cJSON_Array:
+ return print_array(item, output_buffer);
+
+ case cJSON_Object:
+ return print_object(item, output_buffer);
+
+ default:
+ return false;
+ }
+}
+
+/* Build an array from input text. */
+static cJSON_bool parse_array(cJSON * const item,
+ parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* head of the linked list */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (buffer_at_offset(input_buffer)[0] != '[') {
+ /* not an array */
+ goto fail;
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0)
+ && (buffer_at_offset(input_buffer)[0] == ']')) {
+ /* empty array */
+ goto success;
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0)) {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL) {
+ goto fail;
+ /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL) {
+ /* start the linked list */
+ current_item = head = new_item;
+ } else {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse next value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer)) {
+ goto fail;
+ /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ } while (can_access_at_index(input_buffer, 0)
+ && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0)
+ || buffer_at_offset(input_buffer)[0] != ']') {
+ goto fail;
+ /* expected end of array */
+ }
+
+ success: input_buffer->depth--;
+
+ item->type = cJSON_Array;
+ item->child = head;
+
+ input_buffer->offset++;
+
+ return true;
+
+ fail: if (head != NULL) {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an array to text */
+static cJSON_bool print_array(const cJSON * const item,
+ printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_element = item->child;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* Compose the output array. */
+ /* opening square bracket */
+ output_pointer = ensure(output_buffer, 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ *output_pointer = '[';
+ output_buffer->offset++;
+ output_buffer->depth++;
+
+ while (current_element != NULL) {
+ if (!print_value(current_element, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+ if (current_element->next) {
+ length = (size_t)(output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ',';
+ if (output_buffer->format) {
+ *output_pointer++ = ' ';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+ }
+ current_element = current_element->next;
+ }
+
+ output_pointer = ensure(output_buffer, 2);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ']';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Build an object from the text. */
+static cJSON_bool parse_object(cJSON * const item,
+ parse_buffer * const input_buffer)
+{
+ cJSON *head = NULL; /* linked list head */
+ cJSON *current_item = NULL;
+
+ if (input_buffer->depth >= CJSON_NESTING_LIMIT) {
+ return false; /* to deeply nested */
+ }
+ input_buffer->depth++;
+
+ if (cannot_access_at_index(input_buffer, 0)
+ || (buffer_at_offset(input_buffer)[0] != '{')) {
+ goto fail;
+ /* not an object */
+ }
+
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (can_access_at_index(input_buffer, 0)
+ && (buffer_at_offset(input_buffer)[0] == '}')) {
+ goto success;
+ /* empty object */
+ }
+
+ /* check if we skipped to the end of the buffer */
+ if (cannot_access_at_index(input_buffer, 0)) {
+ input_buffer->offset--;
+ goto fail;
+ }
+
+ /* step back to character in front of the first element */
+ input_buffer->offset--;
+ /* loop through the comma separated array elements */
+ do {
+ /* allocate next item */
+ cJSON *new_item = cJSON_New_Item(&(input_buffer->hooks));
+ if (new_item == NULL) {
+ goto fail;
+ /* allocation failure */
+ }
+
+ /* attach next item to list */
+ if (head == NULL) {
+ /* start the linked list */
+ current_item = head = new_item;
+ } else {
+ /* add to the end and advance */
+ current_item->next = new_item;
+ new_item->prev = current_item;
+ current_item = new_item;
+ }
+
+ /* parse the name of the child */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_string(current_item, input_buffer)) {
+ goto fail;
+ /* faile to parse name */
+ }
+ buffer_skip_whitespace(input_buffer);
+
+ /* swap valuestring and string, because we parsed the name */
+ current_item->string = current_item->valuestring;
+ current_item->valuestring = NULL;
+
+ if (cannot_access_at_index(input_buffer, 0)
+ || (buffer_at_offset(input_buffer)[0] != ':')) {
+ goto fail;
+ /* invalid object */
+ }
+
+ /* parse the value */
+ input_buffer->offset++;
+ buffer_skip_whitespace(input_buffer);
+ if (!parse_value(current_item, input_buffer)) {
+ goto fail;
+ /* failed to parse value */
+ }
+ buffer_skip_whitespace(input_buffer);
+ } while (can_access_at_index(input_buffer, 0)
+ && (buffer_at_offset(input_buffer)[0] == ','));
+
+ if (cannot_access_at_index(input_buffer, 0)
+ || (buffer_at_offset(input_buffer)[0] != '}')) {
+ goto fail;
+ /* expected end of object */
+ }
+
+ success: input_buffer->depth--;
+
+ item->type = cJSON_Object;
+ item->child = head;
+
+ input_buffer->offset++;
+ return true;
+
+ fail: if (head != NULL) {
+ cJSON_Delete(head);
+ }
+
+ return false;
+}
+
+/* Render an object to text. */
+static cJSON_bool print_object(const cJSON * const item,
+ printbuffer * const output_buffer)
+{
+ unsigned char *output_pointer = NULL;
+ size_t length = 0;
+ cJSON *current_item = item->child;
+
+ if (output_buffer == NULL) {
+ return false;
+ }
+
+ /* Compose the output: */
+ length = (size_t)(output_buffer->format ? 2 : 1); /* fmt: {\n */
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+
+ *output_pointer++ = '{';
+ output_buffer->depth++;
+ if (output_buffer->format) {
+ *output_pointer++ = '\n';
+ }
+ output_buffer->offset += length;
+
+ while (current_item) {
+ if (output_buffer->format) {
+ size_t i;
+ output_pointer = ensure(output_buffer, output_buffer->depth);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ for (i = 0; i < output_buffer->depth; i++) {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += output_buffer->depth;
+ }
+
+ /* print key */
+ if (!print_string_ptr((unsigned char*) current_item->string,
+ output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ length = (size_t)(output_buffer->format ? 2 : 1);
+ output_pointer = ensure(output_buffer, length);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ *output_pointer++ = ':';
+ if (output_buffer->format) {
+ *output_pointer++ = '\t';
+ }
+ output_buffer->offset += length;
+
+ /* print value */
+ if (!print_value(current_item, output_buffer)) {
+ return false;
+ }
+ update_offset(output_buffer);
+
+ /* print comma if not last */
+ length = ((size_t)(output_buffer->format ? 1 : 0)
+ + (size_t)(current_item->next ? 1 : 0));
+ output_pointer = ensure(output_buffer, length + 1);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ if (current_item->next) {
+ *output_pointer++ = ',';
+ }
+
+ if (output_buffer->format) {
+ *output_pointer++ = '\n';
+ }
+ *output_pointer = '\0';
+ output_buffer->offset += length;
+
+ current_item = current_item->next;
+ }
+
+ output_pointer = ensure(output_buffer,
+ output_buffer->format ? (output_buffer->depth + 1) : 2);
+ if (output_pointer == NULL) {
+ return false;
+ }
+ if (output_buffer->format) {
+ size_t i;
+ for (i = 0; i < (output_buffer->depth - 1); i++) {
+ *output_pointer++ = '\t';
+ }
+ }
+ *output_pointer++ = '}';
+ *output_pointer = '\0';
+ output_buffer->depth--;
+
+ return true;
+}
+
+/* Get Array size/item / object item. */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array)
+{
+ cJSON *child = NULL;
+ size_t size = 0;
+
+ if (array == NULL) {
+ return 0;
+ }
+
+ child = array->child;
+
+ while (child != NULL) {
+ size++;
+ child = child->next;
+ }
+
+ /* FIXME: Can overflow here. Cannot be fixed without breaking the API */
+
+ return (int) size;
+}
+
+static cJSON* get_array_item(const cJSON *array, size_t index)
+{
+ cJSON *current_child = NULL;
+
+ if (array == NULL) {
+ return NULL;
+ }
+
+ current_child = array->child;
+ while ((current_child != NULL) && (index > 0)) {
+ index--;
+ current_child = current_child->next;
+ }
+
+ return current_child;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index)
+{
+ if (index < 0)
+ {
+ return NULL;
+ }
+
+ return get_array_item(array, (size_t)index);
+}
+
+static cJSON *get_object_item(const cJSON * const object,
+ const char * const name, const cJSON_bool case_sensitive)
+{
+ cJSON *current_element = NULL;
+
+ if ((object == NULL) || (name == NULL)) {
+ return NULL;
+ }
+
+ current_element = object->child;
+ if (case_sensitive) {
+ while ((current_element != NULL) && (current_element->string != NULL)
+ && (strcmp(name, current_element->string) != 0)) {
+ current_element = current_element->next;
+ }
+ } else {
+ while ((current_element != NULL)
+ && (case_insensitive_strcmp((const unsigned char*) name,
+ (const unsigned char*) (current_element->string)) != 0)) {
+ current_element = current_element->next;
+ }
+ }
+
+ if ((current_element == NULL) || (current_element->string == NULL)) {
+ return NULL;
+ }
+
+ return current_element;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, false);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string)
+{
+ return get_object_item(object, string, true);
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object,
+ const char *string)
+{
+ return cJSON_GetObjectItem(object, string) ? 1 : 0;
+}
+
+/* Utility for array list handling. */
+static void suffix_object(cJSON *prev, cJSON *item)
+{
+ prev->next = item;
+ item->prev = prev;
+}
+
+/* Utility for handling references. */
+static cJSON *create_reference(const cJSON *item,
+ const internal_hooks * const hooks)
+{
+ cJSON *reference = NULL;
+ if (item == NULL) {
+ return NULL;
+ }
+
+ reference = cJSON_New_Item(hooks);
+ if (reference == NULL) {
+ return NULL;
+ }
+
+ memcpy(reference, item, sizeof(cJSON));
+ reference->string = NULL;
+ reference->type |= cJSON_IsReference;
+ reference->next = reference->prev = NULL;
+ return reference;
+}
+
+static cJSON_bool add_item_to_array(cJSON *array, cJSON *item)
+{
+ cJSON *child = NULL;
+
+ if ((item == NULL) || (array == NULL)) {
+ return false;
+ }
+
+ child = array->child;
+
+ if (child == NULL) {
+ /* list is empty, start new one */
+ array->child = item;
+ } else {
+ /* append to the end */
+ while (child->next) {
+ child = child->next;
+ }
+ suffix_object(child, item);
+ }
+
+ return true;
+}
+
+/* Add item to array/object. */
+CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item)
+{
+ add_item_to_array(array, item);
+}
+
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+#pragma GCC diagnostic push
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic ignored "-Wcast-qual"
+#endif
+/* helper function to cast away const */
+static void* cast_away_const(const void* string)
+{
+ return (void*) string;
+}
+#if defined(__clang__) || (defined(__GNUC__) && ((__GNUC__ > 4) || ((__GNUC__ == 4) && (__GNUC_MINOR__ > 5))))
+#pragma GCC diagnostic pop
+#endif
+
+static cJSON_bool add_item_to_object(cJSON * const object,
+ const char * const string, cJSON * const item,
+ const internal_hooks * const hooks, const cJSON_bool constant_key)
+{
+ char *new_key = NULL;
+ int new_type = cJSON_Invalid;
+
+ if ((object == NULL) || (string == NULL) || (item == NULL)) {
+ return false;
+ }
+
+ if (constant_key) {
+ new_key = (char*) cast_away_const(string);
+ new_type = item->type | cJSON_StringIsConst;
+ } else {
+ new_key = (char*) cJSON_strdup((const unsigned char*) string, hooks);
+ if (new_key == NULL) {
+ return false;
+ }
+
+ new_type = item->type & ~cJSON_StringIsConst;
+ }
+
+ if (!(item->type & cJSON_StringIsConst) && (item->string != NULL)) {
+ hooks->deallocate(item->string);
+ }
+
+ item->string = new_key;
+ item->type = new_type;
+
+ return add_item_to_array(object, item);
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string,
+ cJSON *item)
+{
+ add_item_to_object(object, string, item, &global_hooks, false);
+}
+
+/* Add an item to an object with constant string as key */
+CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string,
+ cJSON *item)
+{
+ add_item_to_object(object, string, item, &global_hooks, true);
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item)
+{
+ if (array == NULL) {
+ return;
+ }
+
+ add_item_to_array(array, create_reference(item, &global_hooks));
+}
+
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object,
+ const char *string, cJSON *item)
+{
+ if ((object == NULL) || (string == NULL)) {
+ return;
+ }
+
+ add_item_to_object(object, string, create_reference(item, &global_hooks),
+ &global_hooks, false);
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name)
+{
+ cJSON *null = cJSON_CreateNull();
+ if (add_item_to_object(object, name, null, &global_hooks, false))
+ {
+ return null;
+ }
+
+ cJSON_Delete(null);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name)
+{
+ cJSON *true_item = cJSON_CreateTrue();
+ if (add_item_to_object(object, name, true_item, &global_hooks, false))
+ {
+ return true_item;
+ }
+
+ cJSON_Delete(true_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name)
+{
+ cJSON *false_item = cJSON_CreateFalse();
+ if (add_item_to_object(object, name, false_item, &global_hooks, false))
+ {
+ return false_item;
+ }
+
+ cJSON_Delete(false_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean)
+{
+ cJSON *bool_item = cJSON_CreateBool(boolean);
+ if (add_item_to_object(object, name, bool_item, &global_hooks, false))
+ {
+ return bool_item;
+ }
+
+ cJSON_Delete(bool_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number)
+{
+ cJSON *number_item = cJSON_CreateNumber(number);
+ if (add_item_to_object(object, name, number_item, &global_hooks, false))
+ {
+ return number_item;
+ }
+
+ cJSON_Delete(number_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string)
+{
+ cJSON *string_item = cJSON_CreateString(string);
+ if (add_item_to_object(object, name, string_item, &global_hooks, false))
+ {
+ return string_item;
+ }
+
+ cJSON_Delete(string_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw)
+{
+ cJSON *raw_item = cJSON_CreateRaw(raw);
+ if (add_item_to_object(object, name, raw_item, &global_hooks, false))
+ {
+ return raw_item;
+ }
+
+ cJSON_Delete(raw_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name)
+{
+ cJSON *object_item = cJSON_CreateObject();
+ if (add_item_to_object(object, name, object_item, &global_hooks, false))
+ {
+ return object_item;
+ }
+
+ cJSON_Delete(object_item);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name)
+{
+ cJSON *array = cJSON_CreateArray();
+ if (add_item_to_object(object, name, array, &global_hooks, false))
+ {
+ return array;
+ }
+
+ cJSON_Delete(array);
+ return NULL;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item)
+{
+ if ((parent == NULL) || (item == NULL))
+ {
+ return NULL;
+ }
+
+ if (item->prev != NULL)
+ {
+ /* not the first element */
+ item->prev->next = item->next;
+ }
+ if (item->next != NULL)
+ {
+ /* not the last element */
+ item->next->prev = item->prev;
+ }
+
+ if (item == parent->child)
+ {
+ /* first element */
+ parent->child = item->next;
+ }
+ /* make sure the detached item doesn't point anywhere anymore */
+ item->prev = NULL;
+ item->next = NULL;
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which)
+{
+ if (which < 0)
+ {
+ return NULL;
+ }
+
+ return cJSON_DetachItemViaPointer(array, get_array_item(array, (size_t)which));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which)
+{
+ cJSON_Delete(cJSON_DetachItemFromArray(array, which));
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItem(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string)
+{
+ cJSON *to_detach = cJSON_GetObjectItemCaseSensitive(object, string);
+
+ return cJSON_DetachItemViaPointer(object, to_detach);
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObject(object, string));
+}
+
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object,
+ const char *string)
+{
+ cJSON_Delete(cJSON_DetachItemFromObjectCaseSensitive(object, string));
+}
+
+/* Replace array/object items with new ones. */
+CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which,
+ cJSON *newitem)
+{
+ cJSON *after_inserted = NULL;
+
+ if (which < 0) {
+ return;
+ }
+
+ after_inserted = get_array_item(array, (size_t) which);
+ if (after_inserted == NULL) {
+ add_item_to_array(array, newitem);
+ return;
+ }
+
+ newitem->next = after_inserted;
+ newitem->prev = after_inserted->prev;
+ after_inserted->prev = newitem;
+ if (after_inserted == array->child) {
+ array->child = newitem;
+ } else {
+ newitem->prev->next = newitem;
+ }
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent,
+ cJSON * const item, cJSON * replacement)
+{
+ if ((parent == NULL) || (replacement == NULL) || (item == NULL)) {
+ return false;
+ }
+
+ if (replacement == item) {
+ return true;
+ }
+
+ replacement->next = item->next;
+ replacement->prev = item->prev;
+
+ if (replacement->next != NULL) {
+ replacement->next->prev = replacement;
+ }
+ if (replacement->prev != NULL) {
+ replacement->prev->next = replacement;
+ }
+ if (parent->child == item) {
+ parent->child = replacement;
+ }
+
+ item->next = NULL;
+ item->prev = NULL;
+ cJSON_Delete(item);
+
+ return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which,
+ cJSON *newitem)
+{
+ if (which < 0) {
+ return;
+ }
+
+ cJSON_ReplaceItemViaPointer(array, get_array_item(array, (size_t) which),
+ newitem);
+}
+
+static cJSON_bool replace_item_in_object(cJSON *object, const char *string,
+ cJSON *replacement, cJSON_bool case_sensitive)
+{
+ if ((replacement == NULL) || (string == NULL)) {
+ return false;
+ }
+
+ /* replace the name in the replacement */
+ if (!(replacement->type & cJSON_StringIsConst)
+ && (replacement->string != NULL)) {
+ cJSON_free(replacement->string);
+ }
+ replacement->string = (char*) cJSON_strdup((const unsigned char*) string,
+ &global_hooks);
+ replacement->type &= ~cJSON_StringIsConst;
+
+ cJSON_ReplaceItemViaPointer(object,
+ get_object_item(object, string, case_sensitive), replacement);
+
+ return true;
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object, const char *string,
+ cJSON *newitem)
+{
+ replace_item_in_object(object, string, newitem, false);
+}
+
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,
+ const char *string, cJSON *newitem)
+{
+ replace_item_in_object(object, string, newitem, true);
+}
+
+/* Create basic types: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_NULL;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_True;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool b)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = b ? cJSON_True : cJSON_False;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Number;
+ item->valuedouble = num;
+
+ /* use saturation in case of overflow */
+ if (num >= INT_MAX)
+ {
+ item->valueint = INT_MAX;
+ }
+ else if (num <= (double)INT_MIN)
+ {
+ item->valueint = INT_MIN;
+ }
+ else
+ {
+ item->valueint = (int)num;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_String;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)string, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL)
+ {
+ item->type = cJSON_String | cJSON_IsReference;
+ item->valuestring = (char*)cast_away_const(string);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Object | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child) {
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item != NULL) {
+ item->type = cJSON_Array | cJSON_IsReference;
+ item->child = (cJSON*)cast_away_const(child);
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type = cJSON_Raw;
+ item->valuestring = (char*)cJSON_strdup((const unsigned char*)raw, &global_hooks);
+ if(!item->valuestring)
+ {
+ cJSON_Delete(item);
+ return NULL;
+ }
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if(item)
+ {
+ item->type=cJSON_Array;
+ }
+
+ return item;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void)
+{
+ cJSON *item = cJSON_New_Item(&global_hooks);
+ if (item)
+ {
+ item->type = cJSON_Object;
+ }
+
+ return item;
+}
+
+/* Create Arrays: */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if (!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber((double)numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (numbers == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for(i = 0;a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateNumber(numbers[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p, n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count)
+{
+ size_t i = 0;
+ cJSON *n = NULL;
+ cJSON *p = NULL;
+ cJSON *a = NULL;
+
+ if ((count < 0) || (strings == NULL))
+ {
+ return NULL;
+ }
+
+ a = cJSON_CreateArray();
+
+ for (i = 0; a && (i < (size_t)count); i++)
+ {
+ n = cJSON_CreateString(strings[i]);
+ if(!n)
+ {
+ cJSON_Delete(a);
+ return NULL;
+ }
+ if(!i)
+ {
+ a->child = n;
+ }
+ else
+ {
+ suffix_object(p,n);
+ }
+ p = n;
+ }
+
+ return a;
+}
+
+/* Duplication */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse)
+{
+ cJSON *newitem = NULL;
+ cJSON *child = NULL;
+ cJSON *next = NULL;
+ cJSON *newchild = NULL;
+
+ /* Bail on bad ptr */
+ if (!item)
+ {
+ goto fail;
+ }
+ /* Create new item */
+ newitem = cJSON_New_Item(&global_hooks);
+ if (!newitem)
+ {
+ goto fail;
+ }
+ /* Copy over all vars */
+ newitem->type = item->type & (~cJSON_IsReference);
+ newitem->valueint = item->valueint;
+ newitem->valuedouble = item->valuedouble;
+ if (item->valuestring)
+ {
+ newitem->valuestring = (char*)cJSON_strdup((unsigned char*)item->valuestring, &global_hooks);
+ if (!newitem->valuestring)
+ {
+ goto fail;
+ }
+ }
+ if (item->string)
+ {
+ newitem->string = (item->type&cJSON_StringIsConst) ? item->string : (char*)cJSON_strdup((unsigned char*)item->string, &global_hooks);
+ if (!newitem->string)
+ {
+ goto fail;
+ }
+ }
+ /* If non-recursive, then we're done! */
+ if (!recurse)
+ {
+ return newitem;
+ }
+ /* Walk the ->next chain for the child. */
+ child = item->child;
+ while (child != NULL)
+ {
+ newchild = cJSON_Duplicate(child, true); /* Duplicate (with recurse) each item in the ->next chain */
+ if (!newchild)
+ {
+ goto fail;
+ }
+ if (next != NULL)
+ {
+ /* If newitem->child already set, then crosswire ->prev and ->next and move on */
+ next->next = newchild;
+ newchild->prev = next;
+ next = newchild;
+ }
+ else
+ {
+ /* Set newitem->child and move to it */
+ newitem->child = newchild;
+ next = newchild;
+ }
+ child = child->next;
+ }
+
+ return newitem;
+
+ fail:
+ if (newitem != NULL)
+ {
+ cJSON_Delete(newitem);
+ }
+
+ return NULL;
+}
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json)
+{
+ unsigned char *into = (unsigned char*) json;
+
+ if (json == NULL) {
+ return;
+ }
+
+ while (*json) {
+ if (*json == ' ') {
+ json++;
+ } else if (*json == '\t') {
+ /* Whitespace characters. */
+ json++;
+ } else if (*json == '\r') {
+ json++;
+ } else if (*json == '\n') {
+ json++;
+ } else if ((*json == '/') && (json[1] == '/')) {
+ /* double-slash comments, to end of line. */
+ while (*json && (*json != '\n')) {
+ json++;
+ }
+ } else if ((*json == '/') && (json[1] == '*')) {
+ /* multiline comments. */
+ while (*json && !((*json == '*') && (json[1] == '/'))) {
+ json++;
+ }
+ json += 2;
+ } else if (*json == '\"') {
+ /* string literals, which are \" sensitive. */
+ *into++ = (unsigned char) *json++;
+ while (*json && (*json != '\"')) {
+ if (*json == '\\') {
+ *into++ = (unsigned char) *json++;
+ }
+ *into++ = (unsigned char) *json++;
+ }
+ *into++ = (unsigned char) *json++;
+ } else {
+ /* All other characters. */
+ *into++ = (unsigned char) *json++;
+ }
+ }
+
+ /* and null-terminate. */
+ *into = '\0';
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Invalid;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_False;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xff) == cJSON_True;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & (cJSON_True | cJSON_False)) != 0;
+}
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_NULL;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Number;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_String;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Array;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Object;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item)
+{
+ if (item == NULL) {
+ return false;
+ }
+
+ return (item->type & 0xFF) == cJSON_Raw;
+}
+
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a,
+ const cJSON * const b, const cJSON_bool case_sensitive)
+{
+ if ((a == NULL) || (b == NULL) || ((a->type & 0xFF) != (b->type & 0xFF))
+ || cJSON_IsInvalid(a)) {
+ return false;
+ }
+
+ /* check if type is valid */
+ switch (a->type & 0xFF) {
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ case cJSON_Number:
+ case cJSON_String:
+ case cJSON_Raw:
+ case cJSON_Array:
+ case cJSON_Object:
+ break;
+
+ default:
+ return false;
+ }
+
+ /* identical objects are equal */
+ if (a == b) {
+ return true;
+ }
+
+ switch (a->type & 0xFF) {
+ /* in these cases and equal type is enough */
+ case cJSON_False:
+ case cJSON_True:
+ case cJSON_NULL:
+ return true;
+
+ case cJSON_Number:
+ if (a->valuedouble == b->valuedouble) {
+ return true;
+ }
+ return false;
+
+ case cJSON_String:
+ case cJSON_Raw:
+ if ((a->valuestring == NULL) || (b->valuestring == NULL)) {
+ return false;
+ }
+ if (strcmp(a->valuestring, b->valuestring) == 0) {
+ return true;
+ }
+
+ return false;
+
+ case cJSON_Array: {
+ cJSON *a_element = a->child;
+ cJSON *b_element = b->child;
+
+ for (; (a_element != NULL) && (b_element != NULL);) {
+ if (!cJSON_Compare(a_element, b_element, case_sensitive)) {
+ return false;
+ }
+
+ a_element = a_element->next;
+ b_element = b_element->next;
+ }
+
+ /* one of the arrays is longer than the other */
+ if (a_element != b_element) {
+ return false;
+ }
+
+ return true;
+ }
+
+ case cJSON_Object: {
+ cJSON *a_element = NULL;
+ cJSON *b_element = NULL;
+ cJSON_ArrayForEach(a_element, a)
+ {
+ /* TODO This has O(n^2) runtime, which is horrible! */
+ b_element = get_object_item(b, a_element->string, case_sensitive);
+ if (b_element == NULL) {
+ return false;
+ }
+
+ if (!cJSON_Compare(a_element, b_element, case_sensitive)) {
+ return false;
+ }
+ }
+
+ /* doing this twice, once on a and b to prevent true comparison if a subset of b
+ * TODO: Do this the proper way, this is just a fix for now */
+ cJSON_ArrayForEach(b_element, b)
+ {
+ a_element = get_object_item(a, b_element->string, case_sensitive);
+ if (a_element == NULL) {
+ return false;
+ }
+
+ if (!cJSON_Compare(b_element, a_element, case_sensitive)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ default:
+ return false;
+ }
+}
+
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size)
+{
+ return global_hooks.allocate(size);
+}
+
+CJSON_PUBLIC(void) cJSON_free(void *object)
+{
+ global_hooks.deallocate(object);
+}
diff --git a/test-tools/host-tool/external/cJSON/cJSON.h b/test-tools/host-tool/external/cJSON/cJSON.h
new file mode 100644
index 0000000000..82e05af6e3
--- /dev/null
+++ b/test-tools/host-tool/external/cJSON/cJSON.h
@@ -0,0 +1,281 @@
+/*
+ Copyright (c) 2009-2017 Dave Gamble and cJSON contributors
+
+ Permission is hereby granted, free of charge, to any person obtaining a copy
+ of this software and associated documentation files (the "Software"), to deal
+ in the Software without restriction, including without limitation the rights
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ copies of the Software, and to permit persons to whom the Software is
+ furnished to do so, subject to the following conditions:
+
+ The above copyright notice and this permission notice shall be included in
+ all copies or substantial portions of the Software.
+
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ THE SOFTWARE.
+ */
+
+#ifndef cJSON__h
+#define cJSON__h
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#if !defined(__WINDOWS__) && (defined(WIN32) || defined(WIN64) || defined(_MSC_VER) || defined(_WIN32))
+#define __WINDOWS__
+#endif
+
+#ifdef __WINDOWS__
+
+/* When compiling for windows, we specify a specific calling convention to avoid issues where we are being called from a project with a different default calling convention. For windows you have 3 define options:
+
+ CJSON_HIDE_SYMBOLS - Define this in the case where you don't want to ever dllexport symbols
+ CJSON_EXPORT_SYMBOLS - Define this on library build when you want to dllexport symbols (default)
+ CJSON_IMPORT_SYMBOLS - Define this if you want to dllimport symbol
+
+ For *nix builds that support visibility attribute, you can define similar behavior by
+
+ setting default visibility to hidden by adding
+ -fvisibility=hidden (for gcc)
+ or
+ -xldscope=hidden (for sun cc)
+ to CFLAGS
+
+ then using the CJSON_API_VISIBILITY flag to "export" the same symbols the way CJSON_EXPORT_SYMBOLS does
+
+ */
+
+#define CJSON_CDECL __cdecl
+#define CJSON_STDCALL __stdcall
+
+/* export symbols by default, this is necessary for copy pasting the C and header file */
+#if !defined(CJSON_HIDE_SYMBOLS) && !defined(CJSON_IMPORT_SYMBOLS) && !defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_EXPORT_SYMBOLS
+#endif
+
+#if defined(CJSON_HIDE_SYMBOLS)
+#define CJSON_PUBLIC(type) type CJSON_STDCALL
+#elif defined(CJSON_EXPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllexport) type CJSON_STDCALL
+#elif defined(CJSON_IMPORT_SYMBOLS)
+#define CJSON_PUBLIC(type) __declspec(dllimport) type CJSON_STDCALL
+#endif
+#else /* !__WINDOWS__ */
+#define CJSON_CDECL
+#define CJSON_STDCALL
+
+#if (defined(__GNUC__) || defined(__SUNPRO_CC) || defined (__SUNPRO_C)) && defined(CJSON_API_VISIBILITY)
+#define CJSON_PUBLIC(type) __attribute__((visibility("default"))) type
+#else
+#define CJSON_PUBLIC(type) type
+#endif
+#endif
+
+/* project version */
+#define CJSON_VERSION_MAJOR 1
+#define CJSON_VERSION_MINOR 7
+#define CJSON_VERSION_PATCH 10
+
+#include
+
+/* cJSON Types: */
+#define cJSON_Invalid (0)
+#define cJSON_False (1 << 0)
+#define cJSON_True (1 << 1)
+#define cJSON_NULL (1 << 2)
+#define cJSON_Number (1 << 3)
+#define cJSON_String (1 << 4)
+#define cJSON_Array (1 << 5)
+#define cJSON_Object (1 << 6)
+#define cJSON_Raw (1 << 7) /* raw json */
+
+#define cJSON_IsReference 256
+#define cJSON_StringIsConst 512
+
+/* The cJSON structure: */
+typedef struct cJSON {
+ /* next/prev allow you to walk array/object chains. Alternatively, use GetArraySize/GetArrayItem/GetObjectItem */
+ struct cJSON *next;
+ struct cJSON *prev;
+ /* An array or object item will have a child pointer pointing to a chain of the items in the array/object. */
+ struct cJSON *child;
+
+ /* The type of the item, as above. */
+ int type;
+
+ /* The item's string, if type==cJSON_String and type == cJSON_Raw */
+ char *valuestring;
+ /* writing to valueint is DEPRECATED, use cJSON_SetNumberValue instead */
+ int valueint;
+ /* The item's number, if type==cJSON_Number */
+ double valuedouble;
+
+ /* The item's name string, if this item is the child of, or is in the list of subitems of an object. */
+ char *string;
+} cJSON;
+
+typedef struct cJSON_Hooks {
+ /* malloc/free are CDECL on Windows regardless of the default calling convention of the compiler, so ensure the hooks allow passing those functions directly. */
+ void *(CJSON_CDECL *malloc_fn)(size_t sz);
+ void (CJSON_CDECL *free_fn)(void *ptr);
+} cJSON_Hooks;
+
+typedef int cJSON_bool;
+
+/* Limits how deeply nested arrays/objects can be before cJSON rejects to parse them.
+ * This is to prevent stack overflows. */
+#ifndef CJSON_NESTING_LIMIT
+#define CJSON_NESTING_LIMIT 1000
+#endif
+
+/* returns the version of cJSON as a string */
+CJSON_PUBLIC(const char*) cJSON_Version(void);
+
+/* Supply malloc, realloc and free functions to cJSON */
+CJSON_PUBLIC(void) cJSON_InitHooks(cJSON_Hooks* hooks);
+
+/* Memory Management: the caller is always responsible to free the results from all variants of cJSON_Parse (with cJSON_Delete) and cJSON_Print (with stdlib free, cJSON_Hooks.free_fn, or cJSON_free as appropriate). The exception is cJSON_PrintPreallocated, where the caller has full responsibility of the buffer. */
+/* Supply a block of JSON, and this returns a cJSON object you can interrogate. */
+CJSON_PUBLIC(cJSON *) cJSON_Parse(const char *value);
+/* ParseWithOpts allows you to require (and check) that the JSON is null terminated, and to retrieve the pointer to the final byte parsed. */
+/* If you supply a ptr in return_parse_end and parsing fails, then return_parse_end will contain a pointer to the error so will match cJSON_GetErrorPtr(). */
+CJSON_PUBLIC(cJSON *) cJSON_ParseWithOpts(const char *value, const char **return_parse_end, cJSON_bool require_null_terminated);
+
+/* Render a cJSON entity to text for transfer/storage. */
+CJSON_PUBLIC(char *) cJSON_Print(const cJSON *item);
+/* Render a cJSON entity to text for transfer/storage without any formatting. */
+CJSON_PUBLIC(char *) cJSON_PrintUnformatted(const cJSON *item);
+/* Render a cJSON entity to text using a buffered strategy. prebuffer is a guess at the final size. guessing well reduces reallocation. fmt=0 gives unformatted, =1 gives formatted */
+CJSON_PUBLIC(char *) cJSON_PrintBuffered(const cJSON *item, int prebuffer, cJSON_bool fmt);
+/* Render a cJSON entity to text using a buffer already allocated in memory with given length. Returns 1 on success and 0 on failure. */
+/* NOTE: cJSON is not always 100% accurate in estimating how much memory it will use, so to be safe allocate 5 bytes more than you actually need */
+CJSON_PUBLIC(cJSON_bool) cJSON_PrintPreallocated(cJSON *item, char *buffer, const int length, const cJSON_bool format);
+/* Delete a cJSON entity and all subentities. */
+CJSON_PUBLIC(void) cJSON_Delete(cJSON *c);
+
+/* Returns the number of items in an array (or object). */
+CJSON_PUBLIC(int) cJSON_GetArraySize(const cJSON *array);
+/* Retrieve item number "index" from array "array". Returns NULL if unsuccessful. */
+CJSON_PUBLIC(cJSON *) cJSON_GetArrayItem(const cJSON *array, int index);
+/* Get item "string" from object. Case insensitive. */
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItem(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON *) cJSON_GetObjectItemCaseSensitive(const cJSON * const object, const char * const string);
+CJSON_PUBLIC(cJSON_bool) cJSON_HasObjectItem(const cJSON *object, const char *string);
+/* For analysing failed parses. This returns a pointer to the parse error. You'll probably need to look a few chars back to make sense of it. Defined when cJSON_Parse() returns 0. 0 when cJSON_Parse() succeeds. */
+CJSON_PUBLIC(const char *) cJSON_GetErrorPtr(void);
+
+/* Check if the item is a string and return its valuestring */
+CJSON_PUBLIC(char *) cJSON_GetStringValue(cJSON *item);
+
+/* These functions check the type of an item */
+CJSON_PUBLIC(cJSON_bool) cJSON_IsInvalid(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsFalse(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsTrue(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsBool(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNull(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsNumber(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsString(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsArray(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsObject(const cJSON * const item);
+CJSON_PUBLIC(cJSON_bool) cJSON_IsRaw(const cJSON * const item);
+
+/* These calls create a cJSON item of the appropriate type. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateNull(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateTrue(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFalse(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateBool(cJSON_bool boolean);
+CJSON_PUBLIC(cJSON *) cJSON_CreateNumber(double num);
+CJSON_PUBLIC(cJSON *) cJSON_CreateString(const char *string);
+/* raw json */
+CJSON_PUBLIC(cJSON *) cJSON_CreateRaw(const char *raw);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArray(void);
+CJSON_PUBLIC(cJSON *) cJSON_CreateObject(void);
+
+/* Create a string where valuestring references a string so
+ * it will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringReference(const char *string);
+/* Create an object/arrray that only references it's elements so
+ * they will not be freed by cJSON_Delete */
+CJSON_PUBLIC(cJSON *) cJSON_CreateObjectReference(const cJSON *child);
+CJSON_PUBLIC(cJSON *) cJSON_CreateArrayReference(const cJSON *child);
+
+/* These utilities create an Array of count items. */
+CJSON_PUBLIC(cJSON *) cJSON_CreateIntArray(const int *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateFloatArray(const float *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateDoubleArray(const double *numbers, int count);
+CJSON_PUBLIC(cJSON *) cJSON_CreateStringArray(const char **strings, int count);
+
+/* Append item to the specified array/object. */
+CJSON_PUBLIC(void) cJSON_AddItemToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(void) cJSON_AddItemToObject(cJSON *object, const char *string, cJSON *item);
+/* Use this when string is definitely const (i.e. a literal, or as good as), and will definitely survive the cJSON object.
+ * WARNING: When this function was used, make sure to always check that (item->type & cJSON_StringIsConst) is zero before
+ * writing to `item->string` */
+CJSON_PUBLIC(void) cJSON_AddItemToObjectCS(cJSON *object, const char *string, cJSON *item);
+/* Append reference to item to the specified array/object. Use this when you want to add an existing cJSON to a new cJSON, but don't want to corrupt your existing cJSON. */
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToArray(cJSON *array, cJSON *item);
+CJSON_PUBLIC(void) cJSON_AddItemReferenceToObject(cJSON *object, const char *string, cJSON *item);
+
+/* Remove/Detatch items from Arrays/Objects. */
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemViaPointer(cJSON *parent, cJSON * const item);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromArray(cJSON *array, int which);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(cJSON *) cJSON_DetachItemFromObjectCaseSensitive(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObject(cJSON *object, const char *string);
+CJSON_PUBLIC(void) cJSON_DeleteItemFromObjectCaseSensitive(cJSON *object, const char *string);
+
+/* Update array items. */
+CJSON_PUBLIC(void) cJSON_InsertItemInArray(cJSON *array, int which, cJSON *newitem); /* Shifts pre-existing items to the right. */
+CJSON_PUBLIC(cJSON_bool) cJSON_ReplaceItemViaPointer(cJSON * const parent, cJSON * const item, cJSON * replacement);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInArray(cJSON *array, int which, cJSON *newitem);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObject(cJSON *object,const char *string,cJSON *newitem);
+CJSON_PUBLIC(void) cJSON_ReplaceItemInObjectCaseSensitive(cJSON *object,const char *string,cJSON *newitem);
+
+/* Duplicate a cJSON item */
+CJSON_PUBLIC(cJSON *) cJSON_Duplicate(const cJSON *item, cJSON_bool recurse);
+/* Duplicate will create a new, identical cJSON item to the one you pass, in new memory that will
+ need to be released. With recurse!=0, it will duplicate any children connected to the item.
+ The item->next and ->prev pointers are always zero on return from Duplicate. */
+/* Recursively compare two cJSON items for equality. If either a or b is NULL or invalid, they will be considered unequal.
+ * case_sensitive determines if object keys are treated case sensitive (1) or case insensitive (0) */
+CJSON_PUBLIC(cJSON_bool) cJSON_Compare(const cJSON * const a, const cJSON * const b, const cJSON_bool case_sensitive);
+
+CJSON_PUBLIC(void) cJSON_Minify(char *json);
+
+/* Helper functions for creating and adding items to an object at the same time.
+ * They return the added item or NULL on failure. */
+CJSON_PUBLIC(cJSON*) cJSON_AddNullToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddTrueToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddFalseToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddBoolToObject(cJSON * const object, const char * const name, const cJSON_bool boolean);
+CJSON_PUBLIC(cJSON*) cJSON_AddNumberToObject(cJSON * const object, const char * const name, const double number);
+CJSON_PUBLIC(cJSON*) cJSON_AddStringToObject(cJSON * const object, const char * const name, const char * const string);
+CJSON_PUBLIC(cJSON*) cJSON_AddRawToObject(cJSON * const object, const char * const name, const char * const raw);
+CJSON_PUBLIC(cJSON*) cJSON_AddObjectToObject(cJSON * const object, const char * const name);
+CJSON_PUBLIC(cJSON*) cJSON_AddArrayToObject(cJSON * const object, const char * const name);
+
+/* When assigning an integer value, it needs to be propagated to valuedouble too. */
+#define cJSON_SetIntValue(object, number) ((object) ? (object)->valueint = (object)->valuedouble = (number) : (number))
+/* helper for the cJSON_SetNumberValue macro */
+CJSON_PUBLIC(double) cJSON_SetNumberHelper(cJSON *object, double number);
+#define cJSON_SetNumberValue(object, number) ((object != NULL) ? cJSON_SetNumberHelper(object, (double)number) : (number))
+
+/* Macro for iterating over an array or object */
+#define cJSON_ArrayForEach(element, array) for(element = (array != NULL) ? (array)->child : NULL; element != NULL; element = element->next)
+
+/* malloc/free objects using the malloc/free functions that have been set with cJSON_InitHooks */
+CJSON_PUBLIC(void *) cJSON_malloc(size_t size);
+CJSON_PUBLIC(void) cJSON_free(void *object);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/test-tools/host-tool/external/cJSON/cjson.cmake b/test-tools/host-tool/external/cJSON/cjson.cmake
new file mode 100644
index 0000000000..af1a9d8a16
--- /dev/null
+++ b/test-tools/host-tool/external/cJSON/cjson.cmake
@@ -0,0 +1,10 @@
+
+set (CJSON_DIR ${CMAKE_CURRENT_LIST_DIR})
+
+include_directories(${CJSON_DIR})
+
+
+file (GLOB_RECURSE source_all ${CJSON_DIR}/*.c)
+
+set (CJSON_SOURCE ${source_all})
+
diff --git a/test-tools/host-tool/src/host_tool_utils.c b/test-tools/host-tool/src/host_tool_utils.c
new file mode 100644
index 0000000000..564bc087f4
--- /dev/null
+++ b/test-tools/host-tool/src/host_tool_utils.c
@@ -0,0 +1,311 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include "host_tool_utils.h"
+#include "shared_utils.h"
+
+#include
+#include
+#include
+#include
+#include
+
+typedef union jvalue {
+ bool z;
+ int8_t b;
+ uint16_t c;
+ int16_t s;
+ int32_t i;
+ int64_t j;
+ float f;
+ double d;
+} jvalue;
+
+#define bh_memcpy_s(dest, dlen, src, slen) do { \
+ int _ret = slen == 0 ? 0 : b_memcpy_s (dest, dlen, src, slen); \
+ (void)_ret; \
+ } while (0)
+
+static inline int16_t get_int16(const char *buf)
+{
+ int16_t ret;
+ bh_memcpy_s(&ret, sizeof(int16_t), buf, sizeof(int16_t));
+ return ret;
+}
+
+static inline uint16_t get_uint16(const char *buf)
+{
+ return get_int16(buf);
+}
+
+static inline int32_t get_int32(const char *buf)
+{
+ int32_t ret;
+ bh_memcpy_s(&ret, sizeof(int32_t), buf, sizeof(int32_t));
+ return ret;
+}
+
+static inline uint32_t get_uint32(const char *buf)
+{
+ return get_int32(buf);
+}
+
+char* attr_container_get_attr_begin(const attr_container_t *attr_cont,
+ uint32_t *p_total_length,
+ uint16_t *p_attr_num);
+
+cJSON *attr2json(const attr_container_t *attr_cont)
+{
+ uint32_t total_length;
+ uint16_t attr_num, i, j, type;
+ const char *p, *tag, *key;
+ jvalue value;
+ cJSON *root;
+
+ if (!attr_cont)
+ return NULL;
+
+ root = cJSON_CreateObject();
+ if (!root)
+ return NULL;
+
+ /* TODO: how to convert the tag? */
+ tag = attr_container_get_tag(attr_cont);
+ if (!tag)
+ goto fail;
+
+ p = attr_container_get_attr_begin(attr_cont, &total_length, &attr_num);
+ if (!p)
+ goto fail;
+
+ for (i = 0; i < attr_num; i++) {
+ cJSON *obj;
+
+ key = p + 2;
+ /* Skip key len and key */
+ p += 2 + get_uint16(p);
+ type = *p++;
+
+ switch (type) {
+ case ATTR_TYPE_SHORT:
+ bh_memcpy_s(&value.s, sizeof(int16_t), p, sizeof(int16_t));
+ if (NULL == (obj = cJSON_CreateNumber(value.s)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ /* another approach: cJSON_AddNumberToObject(root, key, value.s) */
+ p += 2;
+ break;
+ case ATTR_TYPE_INT:
+ bh_memcpy_s(&value.i, sizeof(int32_t), p, sizeof(int32_t));
+ if (NULL == (obj = cJSON_CreateNumber(value.i)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p += 4;
+ break;
+ case ATTR_TYPE_INT64:
+ bh_memcpy_s(&value.j, sizeof(uint64_t), p, sizeof(uint64_t));
+ if (NULL == (obj = cJSON_CreateNumber(value.j)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p += 8;
+ break;
+ case ATTR_TYPE_BYTE:
+ bh_memcpy_s(&value.b, 1, p, 1);
+ if (NULL == (obj = cJSON_CreateNumber(value.b)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p++;
+ break;
+ case ATTR_TYPE_UINT16:
+ bh_memcpy_s(&value.c, sizeof(uint16_t), p, sizeof(uint16_t));
+ if (NULL == (obj = cJSON_CreateNumber(value.c)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p += 2;
+ break;
+ case ATTR_TYPE_FLOAT:
+ bh_memcpy_s(&value.f, sizeof(float), p, sizeof(float));
+ if (NULL == (obj = cJSON_CreateNumber(value.f)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p += 4;
+ break;
+ case ATTR_TYPE_DOUBLE:
+ bh_memcpy_s(&value.d, sizeof(double), p, sizeof(double));
+ if (NULL == (obj = cJSON_CreateNumber(value.d)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p += 8;
+ break;
+ case ATTR_TYPE_BOOLEAN:
+ bh_memcpy_s(&value.z, 1, p, 1);
+ if (NULL == (obj = cJSON_CreateBool(value.z)))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p++;
+ break;
+ case ATTR_TYPE_STRING:
+ if (NULL == (obj = cJSON_CreateString(p + sizeof(uint16_t))))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ p += sizeof(uint16_t) + get_uint16(p);
+ break;
+ case ATTR_TYPE_BYTEARRAY:
+ if (NULL == (obj = cJSON_CreateArray()))
+ goto fail;
+ cJSON_AddItemToObject(root, key, obj);
+ for (j = 0; j < get_uint32(p); j++) {
+ cJSON *item = cJSON_CreateNumber(*(p + sizeof(uint32_t) + j));
+ if (item == NULL)
+ goto fail;
+ cJSON_AddItemToArray(obj, item);
+ }
+ p += sizeof(uint32_t) + get_uint32(p);
+ break;
+ }
+ }
+
+ return root;
+
+ fail: cJSON_Delete(root);
+ return NULL;
+}
+
+attr_container_t *json2attr(const cJSON *json_obj)
+{
+ attr_container_t *attr_cont;
+ cJSON *item;
+
+ if (NULL == (attr_cont = attr_container_create("")))
+ return NULL;
+
+ if (!cJSON_IsObject(json_obj))
+ goto fail;
+
+ cJSON_ArrayForEach(item, json_obj)
+ {
+
+ if (cJSON_IsNumber(item)) {
+ attr_container_set_double(&attr_cont, item->string,
+ item->valuedouble);
+ } else if (cJSON_IsTrue(item)) {
+ attr_container_set_bool(&attr_cont, item->string, true);
+ } else if (cJSON_IsFalse(item)) {
+ attr_container_set_bool(&attr_cont, item->string, false);
+ } else if (cJSON_IsString(item)) {
+ attr_container_set_string(&attr_cont, item->string,
+ item->valuestring);
+ } else if (cJSON_IsArray(item)) {
+ int8_t *array;
+ int i = 0, len = sizeof(int8_t) * cJSON_GetArraySize(item);
+ cJSON *array_item;
+
+ if (0 == len || NULL == (array = (int8_t *) malloc(len)))
+ goto fail;
+ memset(array, 0, len);
+
+ cJSON_ArrayForEach(array_item, item)
+ {
+ /* must be number array */
+ if (!cJSON_IsNumber(array_item))
+ break;
+ /* TODO: if array_item->valuedouble > 127 or < -128 */
+ array[i++] = (int8_t) array_item->valuedouble;
+ }
+ if (i > 0)
+ attr_container_set_bytearray(&attr_cont, item->string, array,
+ i);
+ free(array);
+ }
+ }
+
+ return attr_cont;
+
+ fail: attr_container_destroy(attr_cont);
+ return NULL;
+}
+
+int g_mid = 0;
+
+int gen_random_id()
+{
+ static bool init = false;
+ int r;
+
+ if (!init) {
+ srand(time(NULL));
+ init = true;
+ }
+
+ r = rand();
+ g_mid = r;
+
+ return r;
+}
+
+char *
+read_file_to_buffer(const char *filename, int *ret_size)
+{
+ char *buffer;
+ int file;
+ int file_size, read_size;
+ struct stat stat_buf;
+
+ if (!filename || !ret_size) {
+ return NULL;
+ }
+
+ if ((file = open(filename, O_RDONLY, 0)) == -1) {
+ return NULL;
+ }
+
+ if (fstat(file, &stat_buf) != 0) {
+ close(file);
+ return NULL;
+ }
+
+ file_size = stat_buf.st_size;
+
+ if (!(buffer = malloc(file_size))) {
+ close(file);
+ return NULL;
+ }
+
+ read_size = read(file, buffer, file_size);
+ close(file);
+
+ if (read_size < file_size) {
+ free(buffer);
+ return NULL;
+ }
+
+ *ret_size = file_size;
+ return buffer;
+}
+
+int wirte_buffer_to_file(const char *filename, const char *buffer, int size)
+{
+ int file, ret;
+
+ if ((file = open(filename, O_RDWR | O_CREAT | O_APPEND, 0644)) == -1)
+ return -1;
+
+ ret = write(file, buffer, size);
+
+ close(file);
+
+ return ret;
+}
diff --git a/test-tools/host-tool/src/host_tool_utils.h b/test-tools/host-tool/src/host_tool_utils.h
new file mode 100644
index 0000000000..33dafb6fd8
--- /dev/null
+++ b/test-tools/host-tool/src/host_tool_utils.h
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef _HOST_TOOL_UTILS_H_
+#define _HOST_TOOL_UTILS_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#include "attr_container.h"
+#include "cJSON.h"
+
+/**
+ * @brief Convert attribute container object to cJSON object.
+ *
+ * @param attr the attribute container object to be converted
+ *
+ * @return the created cJSON object if not NULL, NULL means fail
+ *
+ * @warning the return object should be deleted with cJSON_Delete by caller
+ */
+cJSON *attr2json(const attr_container_t *attr);
+
+/**
+ * @brief Convert cJSON object to attribute container object.
+ *
+ * @param json the cJSON object to be converted
+ *
+ * @return the created attribute container object if not NULL, NULL means fail
+ *
+ * @warning the return object should be deleted with attr_container_destroy
+ */
+attr_container_t *json2attr(const cJSON *json);
+
+/**
+ * @brief Generate a random 32 bit integer.
+ *
+ * @return the generated random integer
+ */
+int gen_random_id();
+
+/**
+ * @brief Read file content to buffer.
+ *
+ * @param filename the file name to read
+ * @param ret_size pointer of integer to save file size once return success
+ *
+ * @return the created buffer which contains file content if not NULL, NULL means fail
+ *
+ * @warning the return buffer should be deleted with free by caller
+ */
+char *read_file_to_buffer(const char *filename, int *ret_size);
+
+/**
+ * @brief Write buffer content to file.
+ *
+ * @param filename name the file name to be written
+ * @param buffer the buffer
+ * @param size size of the buffer to be written
+ *
+ * @return < 0 means fail, > 0 means the number of bytes actually written
+ */
+int wirte_buffer_to_file(const char *filename, const char *buffer, int size);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif
diff --git a/test-tools/host-tool/src/main.c b/test-tools/host-tool/src/main.c
new file mode 100644
index 0000000000..87b170ea0f
--- /dev/null
+++ b/test-tools/host-tool/src/main.c
@@ -0,0 +1,930 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "host_tool_utils.h"
+#include "shared_utils.h"
+#include "attr_container.h"
+#include "coap_ext.h"
+#include "cJSON.h"
+#include "app_manager_export.h" /* for Module_WASM_App */
+#include "host_link.h" /* for REQUEST_PACKET */
+#include "transport.h"
+#include "iagent_bsp.h" /* for bh_get_elpased_ms */
+
+#define BUF_SIZE 1024
+#define TIMEOUT_EXIT_CODE 2
+#define URL_MAX_LEN 256
+#define DEFAULT_TIMEOUT_MS 5000
+#define DEFAULT_ALIVE_TIME_MS 0
+
+#define CONNECTION_MODE_TCP 1
+#define CONNECTION_MODE_UART 2
+
+typedef enum {
+ INSTALL, UNINSTALL, QUERY, REQUEST, REGISTER, UNREGISTER
+} op_type;
+
+typedef struct {
+ const char *file;
+ const char *name;
+ const char *module_type;
+ int heap_size;
+ /* max timers number */
+ int timers;
+ int watchdog_interval;
+} inst_info;
+
+typedef struct {
+ const char *name;
+ const char *module_type;
+} uninst_info;
+
+typedef struct {
+ const char *name;
+} query_info;
+
+typedef struct {
+ const char *url;
+ int action;
+ const char *json_payload_file;
+} req_info;
+
+typedef struct {
+ const char *urls;
+} reg_info;
+
+typedef struct {
+ const char *urls;
+} unreg_info;
+
+typedef union operation_info {
+ inst_info inst;
+ uninst_info uinst;
+ query_info query;
+ req_info req;
+ reg_info reg;
+ unreg_info unreg;
+} operation_info;
+
+typedef struct {
+ op_type type;
+ operation_info info;
+} operation;
+
+typedef enum REPLY_PACKET_TYPE {
+ REPLY_TYPE_EVENT = 0, REPLY_TYPE_RESPONSE = 1
+} REPLY_PACKET_TYPE;
+
+/* Package Type */
+typedef enum {
+ Wasm_Module_Bytecode = 0, Wasm_Module_AoT, Package_Type_Unknown = 0xFFFF
+} PackageType;
+
+static uint32_t g_timeout_ms = DEFAULT_TIMEOUT_MS;
+static uint32_t g_alive_time_ms = DEFAULT_ALIVE_TIME_MS;
+static char *g_redirect_file_name = NULL;
+static int g_redirect_udp_port = -1;
+static int g_conn_fd; /* may be tcp or uart */
+static char *g_server_addr = "127.0.0.1";
+static int g_server_port = 8888;
+static char *g_uart_dev = "/dev/ttyS2";
+static int g_baudrate = B115200;
+static int g_connection_mode = CONNECTION_MODE_TCP;
+
+extern int g_mid;
+extern unsigned char leading[2];
+
+/* -1 fail, 0 success */
+static int send_request(request_t *request, bool is_install_wasm_bytecode_app)
+{
+ char *req_p;
+ int req_size, req_size_n, ret = -1;
+ uint16_t msg_type = REQUEST_PACKET;
+
+ if (is_install_wasm_bytecode_app)
+ msg_type = INSTALL_WASM_BYTECODE_APP;
+
+ if ((req_p = pack_request(request, &req_size)) == NULL)
+ return -1;
+
+ /* leanding bytes */
+ if (!host_tool_send_data(g_conn_fd, leading, sizeof(leading)))
+ goto ret;
+
+ /* message type */
+ msg_type = htons(msg_type);
+ if (!host_tool_send_data(g_conn_fd, (char *) &msg_type, sizeof(msg_type)))
+ goto ret;
+
+ /* payload length */
+ req_size_n = htonl(req_size);
+ if (!host_tool_send_data(g_conn_fd, (char *) &req_size_n,
+ sizeof(req_size_n)))
+ goto ret;
+
+ /* payload */
+ if (!host_tool_send_data(g_conn_fd, req_p, req_size))
+ goto ret;
+
+ ret = 0;
+
+ ret: free_req_resp_packet(req_p);
+
+ return ret;
+}
+
+static PackageType get_package_type(const char *buf, int size)
+{
+ if (buf && size > 4) {
+ if (buf[0] == '\0' && buf[1] == 'a' && buf[2] == 's' && buf[3] == 'm')
+ return Wasm_Module_Bytecode;
+ if (buf[0] == '\0' && buf[1] == 'a' && buf[2] == 'o' && buf[3] == 't')
+ return Wasm_Module_AoT;
+ }
+ return Package_Type_Unknown;
+}
+
+#define url_remain_space (sizeof(url) - strlen(url))
+
+/*return:
+ 0: success
+ others: fail*/
+static int install(inst_info *info)
+{
+ request_t request[1] = { 0 };
+ char *app_file_buf;
+ char url[URL_MAX_LEN] = { 0 };
+ int ret = -1, app_size;
+ bool is_wasm_bytecode_app;
+
+ snprintf(url, sizeof(url) - 1, "/applet?name=%s", info->name);
+
+ if (info->module_type != NULL && url_remain_space > 0)
+ snprintf(url + strlen(url), url_remain_space, "&type=%s",
+ info->module_type);
+
+ if (info->heap_size > 0 && url_remain_space > 0)
+ snprintf(url + strlen(url), url_remain_space, "&heap=%d",
+ info->heap_size);
+
+ if (info->timers > 0 && url_remain_space > 0)
+ snprintf(url + strlen(url), url_remain_space, "&timers=%d",
+ info->timers);
+
+ if (info->watchdog_interval > 0 && url_remain_space > 0)
+ snprintf(url + strlen(url), url_remain_space, "&wd=%d",
+ info->watchdog_interval);
+
+ /*TODO: permissions to access JLF resource: AUDIO LOCATION SENSOR VISION platform.SERVICE */
+
+ if ((app_file_buf = read_file_to_buffer(info->file, &app_size)) == NULL)
+ return -1;
+
+ init_request(request, url, COAP_PUT,
+ FMT_APP_RAW_BINARY, app_file_buf, app_size);
+ request->mid = gen_random_id();
+
+ if ((info->module_type == NULL || strcmp(info->module_type, "wasm") == 0)
+ && get_package_type(app_file_buf, app_size) == Wasm_Module_Bytecode)
+ is_wasm_bytecode_app = true;
+ else
+ is_wasm_bytecode_app = false;
+
+ ret = send_request(request, is_wasm_bytecode_app);
+
+ free(app_file_buf);
+
+ return ret;
+}
+
+static int uninstall(uninst_info *info)
+{
+ request_t request[1] = { 0 };
+ char url[URL_MAX_LEN] = { 0 };
+
+ snprintf(url, sizeof(url) - 1, "/applet?name=%s", info->name);
+
+ if (info->module_type != NULL && url_remain_space > 0)
+ snprintf(url + strlen(url), url_remain_space, "&type=%s",
+ info->module_type);
+
+ init_request(request, url, COAP_DELETE,
+ FMT_ATTR_CONTAINER,
+ NULL, 0);
+ request->mid = gen_random_id();
+
+ return send_request(request, false);
+}
+
+static int query(query_info *info)
+{
+ request_t request[1] = { 0 };
+ int ret = -1;
+ char url[URL_MAX_LEN] = { 0 };
+
+ if (info->name != NULL)
+ snprintf(url, sizeof(url) - 1, "/applet?name=%s", info->name);
+ else
+ snprintf(url, sizeof(url) - 1, "/applet");
+
+ init_request(request, url, COAP_GET,
+ FMT_ATTR_CONTAINER,
+ NULL, 0);
+ request->mid = gen_random_id();
+
+ ret = send_request(request, false);
+
+ return ret;
+}
+
+static int request(req_info *info)
+{
+ request_t request[1] = { 0 };
+ attr_container_t *payload = NULL;
+ int ret = -1, payload_len = 0;
+
+ if (info->json_payload_file != NULL) {
+ char *payload_file;
+ cJSON *json;
+ int payload_file_size;
+
+ if ((payload_file = read_file_to_buffer(info->json_payload_file,
+ &payload_file_size)) == NULL)
+ return -1;
+
+ if (NULL == (json = cJSON_Parse(payload_file))) {
+ free(payload_file);
+ goto fail;
+ }
+
+ if (NULL == (payload = json2attr(json))) {
+ cJSON_Delete(json);
+ free(payload_file);
+ goto fail;
+ }
+ payload_len = attr_container_get_serialize_length(payload);
+
+ cJSON_Delete(json);
+ free(payload_file);
+ }
+
+ init_request(request, (char *)info->url, info->action,
+ FMT_ATTR_CONTAINER, payload, payload_len);
+ request->mid = gen_random_id();
+
+ ret = send_request(request, false);
+
+ if (info->json_payload_file != NULL && payload != NULL)
+ attr_container_destroy(payload);
+
+ fail: return ret;
+}
+
+/*
+ TODO: currently only support 1 url.
+ how to handle multiple responses and set process's exit code?
+ */
+static int subscribe(reg_info *info)
+{
+ request_t request[1] = { 0 };
+ int ret = -1;
+#if 0
+ char *p;
+
+ p = strtok(info->urls, ",");
+ while(p != NULL) {
+ char url[URL_MAX_LEN] = {0};
+ sprintf(url, "%s%s", "/event/", p);
+ init_request(request,
+ url,
+ COAP_PUT,
+ FMT_ATTR_CONTAINER,
+ NULL,
+ 0);
+ request->mid = gen_random_id();
+ ret = send_request(request, false);
+ p = strtok (NULL, ",");
+ }
+#else
+ char url[URL_MAX_LEN] = { 0 };
+ char *prefix = info->urls[0] == '/' ? "/event" : "/event/";
+ sprintf(url, "%s%s", prefix, info->urls);
+ init_request(request, url, COAP_PUT,
+ FMT_ATTR_CONTAINER,
+ NULL, 0);
+ request->mid = gen_random_id();
+ ret = send_request(request, false);
+#endif
+ return ret;
+}
+
+static int unsubscribe(unreg_info *info)
+{
+ request_t request[1] = { 0 };
+ int ret = -1;
+#if 0
+ char *p;
+
+ p = strtok(info->urls, ",");
+ while(p != NULL) {
+ char url[URL_MAX_LEN] = {0};
+ sprintf(url, "%s%s", "/event/", p);
+ init_request(request,
+ url,
+ COAP_DELETE,
+ FMT_ATTR_CONTAINER,
+ NULL,
+ 0);
+ request->mid = gen_random_id();
+ ret = send_request(request, false);
+ p = strtok (NULL, ",");
+ }
+#else
+ char url[URL_MAX_LEN] = { 0 };
+ sprintf(url, "%s%s", "/event/", info->urls);
+ init_request(request, url, COAP_DELETE,
+ FMT_ATTR_CONTAINER,
+ NULL, 0);
+ request->mid = gen_random_id();
+ ret = send_request(request, false);
+#endif
+ return ret;
+}
+
+static int init()
+{
+ if (g_connection_mode == CONNECTION_MODE_TCP) {
+ int fd;
+ if (!tcp_init(g_server_addr, g_server_port, &fd))
+ return -1;
+ g_conn_fd = fd;
+ return 0;
+ } else if (g_connection_mode == CONNECTION_MODE_UART) {
+ int fd;
+ if (!uart_init(g_uart_dev, g_baudrate, &fd))
+ return -1;
+ g_conn_fd = fd;
+ return 0;
+ }
+
+ return -1;
+}
+
+static void deinit()
+{
+ close(g_conn_fd);
+}
+
+static int parse_action(const char *str)
+{
+ if (strcasecmp(str, "PUT") == 0)
+ return COAP_PUT;
+ if (strcasecmp(str, "GET") == 0)
+ return COAP_GET;
+ if (strcasecmp(str, "DELETE") == 0)
+ return COAP_DELETE;
+ if (strcasecmp(str, "POST") == 0)
+ return COAP_POST;
+ return -1;
+}
+
+static void showUsage()
+{
+ printf("\n");
+ /*printf("Usage: host_tool [-i|--install]|[-u|--uninstall]|[-q|--query]|[-r|--request]|[-s|--register]|[-d|--deregister] ...\n");*/
+ printf("Usage:\n\thost_tool -i|-u|-q|-r|-s|-d ...\n\n");
+
+ printf("\thost_tool -i -f \n"
+ "\t\t [--type=]\n"
+ "\t\t [--heap=]\n"
+ "\t\t [--timers=]\n"
+ "\t\t [--watchdog=]\n"
+ "\t\t [ ...] \n");
+ printf("\thost_tool -u [ ...]\n");
+ printf("\thost_tool -q[][ ...]\n");
+ printf(
+ "\thost_tool -r -A [-p ] [ ...]\n");
+ printf("\thost_tool -s [ ...]\n");
+ printf("\thost_tool -d [ ...]\n\n");
+
+ printf(
+ "\t-i, --install Install an application\n");
+ printf(
+ "\t-u, --uninstall Uninstall an application\n");
+ printf(
+ "\t-q, --query Query all applications\n");
+ printf("\t-r, --request Send a request\n");
+ printf("\t-s, --register Register event(s)\n");
+ printf("\t-d, --deregister De-register event(s)\n");
+ printf(
+ "\t-f, --file Specify app binary file path\n");
+ printf(
+ "\t-A, --action Specify action of the request\n");
+ printf(
+ "\t-p, --payload Specify payload of the request\n");
+ printf("\n");
+
+ printf("\n\tControl Options:\n");
+ printf(" \t-S |--address= Set server address, default to 127.0.0.1\n");
+ printf(" \t-P |--port= Set server port, default to 8888\n");
+ printf(" \t-D |--uart= Set uart device, default to /dev/ttyS2\n");
+ printf(" \t-B |--baudrate= Set uart device baudrate, default to 115200\n");
+
+ printf(
+ "\t-t |--timeout= Operation timeout in ms, default to 5000\n");
+ printf(
+ "\t-a |--alive= Alive time in ms after last operation done, default to 0\n");
+ printf(
+ "\t-o |--output= Redirect the output to output a file\n");
+ printf(
+ "\t-U |--udp= Redirect the output to an UDP port in local machine\n");
+
+ printf("\nNotes:\n");
+ printf("\t=name of the application\n");
+ printf("\t=path of the application binary file in wasm format\n");
+ printf(
+ "\t=resource descriptor, such as /app//res1 or /res1\n");
+ printf(
+ "\t=event url list separated by ',', such as /event1,/event2,/event3\n");
+ printf(
+ "\t=action of the request, can be PUT, GET, DELETE or POST (case insensitive)\n");
+ printf("\t=path of the payload file in json format\n");
+ printf("\t=Type of app. Can be 'wasm'(default) or 'jeff'\n");
+ printf("\t=Heap size of app.\n");
+ printf("\t=Max timers number app can use.\n");
+ printf("\t=Watchdog interval in ms.\n");
+}
+
+#define CHECK_DUPLICATE_OPERATION do{ \
+ if (operation_parsed) \
+ { \
+ showUsage(); \
+ return false; \
+ } \
+}while(0)
+
+#define ERROR_RETURN do{ \
+ showUsage(); \
+ return false; \
+}while(0)
+
+#define CHECK_ARGS_UNMATCH_OPERATION(op_type) do{ \
+ if (!operation_parsed || op->type != op_type) \
+ { \
+ showUsage(); \
+ return false; \
+ } \
+}while(0)
+
+static bool parse_args(int argc, char *argv[], operation *op)
+{
+ int c;
+ bool operation_parsed = false;
+ bool conn_mode_parsed = false;
+
+ while (1) {
+ int optIndex = 0;
+ static struct option longOpts[] = {
+ { "install", required_argument, NULL, 'i' },
+ { "uninstall", required_argument, NULL, 'u' },
+ { "query", optional_argument, NULL, 'q' },
+ { "request", required_argument, NULL, 'r' },
+ { "register", required_argument, NULL, 's' },
+ { "deregister", required_argument, NULL, 'd' },
+ { "timeout", required_argument, NULL, 't' },
+ { "alive", required_argument, NULL, 'a' },
+ { "output", required_argument, NULL, 'o' },
+ { "udp", required_argument, NULL, 'U' },
+ { "action", required_argument, NULL, 'A' },
+ { "file", required_argument, NULL, 'f' },
+ { "payload", required_argument, NULL, 'p' },
+ { "type", required_argument, NULL, 0 },
+ { "heap", required_argument, NULL, 1 },
+ { "timers", required_argument, NULL, 2 },
+ { "watchdog", required_argument, NULL, 3 },
+ { "address", required_argument, NULL, 'S' },
+ { "port", required_argument, NULL, 'P' },
+ { "uart_device",required_argument, NULL, 'D' },
+ { "baudrate", required_argument, NULL, 'B' },
+ { "help", required_argument, NULL, 'h' },
+ { 0, 0, 0, 0 }
+ };
+
+ c = getopt_long(argc, argv, "i:u:q::r:s:d:t:a:o:U:A:f:p:S:P:D:B:h",
+ longOpts, &optIndex);
+ if (c == -1)
+ break;
+
+ switch (c) {
+ case 'i':
+ CHECK_DUPLICATE_OPERATION;
+ op->type = INSTALL;
+ op->info.inst.name = optarg;
+ operation_parsed = true;
+ break;
+ case 'u':
+ CHECK_DUPLICATE_OPERATION;
+ op->type = UNINSTALL;
+ op->info.uinst.name = optarg;
+ operation_parsed = true;
+ break;
+ case 'q':
+ CHECK_DUPLICATE_OPERATION;
+ op->type = QUERY;
+ op->info.query.name = optarg;
+ break;
+ case 'r':
+ CHECK_DUPLICATE_OPERATION;
+ op->type = REQUEST;
+ op->info.req.url = optarg;
+ operation_parsed = true;
+ break;
+ case 's':
+ CHECK_DUPLICATE_OPERATION;
+ op->type = REGISTER;
+ op->info.reg.urls = optarg;
+ operation_parsed = true;
+ break;
+ case 'd':
+ CHECK_DUPLICATE_OPERATION;
+ op->type = UNREGISTER;
+ op->info.unreg.urls = optarg;
+ operation_parsed = true;
+ break;
+ case 't':
+ g_timeout_ms = atoi(optarg);
+ break;
+ case 'a':
+ g_alive_time_ms = atoi(optarg);
+ break;
+ case 'o':
+ g_redirect_file_name = optarg;
+ break;
+ case 'U':
+ g_redirect_udp_port = atoi(optarg);
+ break;
+ case 'A':
+ CHECK_ARGS_UNMATCH_OPERATION(REQUEST);
+ op->info.req.action = parse_action(optarg);
+ break;
+ case 'f':
+ CHECK_ARGS_UNMATCH_OPERATION(INSTALL);
+ op->info.inst.file = optarg;
+ break;
+ case 'p':
+ CHECK_ARGS_UNMATCH_OPERATION(REQUEST);
+ op->info.req.json_payload_file = optarg;
+ break;
+ /* module type */
+ case 0:
+ /* TODO: use bit mask */
+ /* CHECK_ARGS_UNMATCH_OPERATION(INSTALL | UNINSTALL); */
+ if (op->type == INSTALL)
+ op->info.inst.module_type = optarg;
+ else if (op->type == UNINSTALL)
+ op->info.uinst.module_type = optarg;
+ break;
+ /* heap */
+ case 1:
+ CHECK_ARGS_UNMATCH_OPERATION(INSTALL);
+ op->info.inst.heap_size = atoi(optarg);
+ break;
+ /* timers */
+ case 2:
+ CHECK_ARGS_UNMATCH_OPERATION(INSTALL);
+ op->info.inst.timers = atoi(optarg);
+ break;
+ /* watchdog */
+ case 3:
+ CHECK_ARGS_UNMATCH_OPERATION(INSTALL);
+ op->info.inst.watchdog_interval = atoi(optarg);
+ break;
+ case 'S':
+ if (conn_mode_parsed) {
+ showUsage();
+ return false;
+ }
+ g_connection_mode = CONNECTION_MODE_TCP;
+ g_server_addr = optarg;
+ conn_mode_parsed = true;
+ break;
+ case 'P':
+ g_server_port = atoi(optarg);
+ break;
+ case 'D':
+ if (conn_mode_parsed) {
+ showUsage();
+ return false;
+ }
+ g_connection_mode = CONNECTION_MODE_UART;
+ g_uart_dev = optarg;
+ conn_mode_parsed = true;
+ break;
+ case 'B':
+ g_baudrate = parse_baudrate(atoi(optarg));
+ break;
+ case 'h':
+ showUsage();
+ return false;
+ default:
+ showUsage();
+ return false;
+ }
+ }
+
+ /* check mandatory options for the operation */
+ switch (op->type) {
+ case INSTALL:
+ if (NULL == op->info.inst.file || NULL == op->info.inst.name)
+ ERROR_RETURN;
+ break;
+ case UNINSTALL:
+ if (NULL == op->info.uinst.name)
+ ERROR_RETURN;
+ break;
+ case QUERY:
+ break;
+ case REQUEST:
+ if (NULL == op->info.req.url || op->info.req.action <= 0)
+ ERROR_RETURN;
+ break;
+ case REGISTER:
+ if (NULL == op->info.reg.urls)
+ ERROR_RETURN;
+ break;
+ case UNREGISTER:
+ if (NULL == op->info.unreg.urls)
+ ERROR_RETURN;
+ break;
+ default:
+ return false;
+ }
+
+ return true;
+}
+
+/*
+ return value:
+ < 0: not complete message
+ REPLY_TYPE_EVENT: event(request)
+ REPLY_TYPE_RESPONSE: response
+ */
+static int preocess_reply_data(const char *buf, int len,
+ imrt_link_recv_context_t *ctx)
+{
+ int result = -1;
+ const char *pos = buf;
+
+#if DEBUG
+ int i = 0;
+ for (; i < len; i++) {
+ printf(" 0x%02x", buf[i]);
+ }
+ printf("\n");
+#endif
+
+ while (len-- > 0) {
+ result = on_imrt_link_byte_arrive((unsigned char) *pos++, ctx);
+ switch (result) {
+ case 0: {
+ imrt_link_message_t *message = &ctx->message;
+ if (message->message_type == RESPONSE_PACKET)
+ return REPLY_TYPE_RESPONSE;
+ if (message->message_type == REQUEST_PACKET)
+ return REPLY_TYPE_EVENT;
+ break;
+ }
+ default:
+ break;
+ }
+ }
+ return -1;
+}
+
+static response_t *
+parse_response_from_imrtlink(imrt_link_message_t *message, response_t *response)
+{
+ if (!unpack_response(message->payload, message->payload_size, response))
+ return NULL;
+
+ return response;
+}
+
+static request_t *
+parse_event_from_imrtlink(imrt_link_message_t *message, request_t *request)
+{
+ if (!unpack_request(message->payload, message->payload_size, request))
+ return NULL;
+
+ return request;
+}
+
+static void output(const char *header, attr_container_t *payload, int foramt,
+ int payload_len)
+{
+ cJSON *json = NULL;
+ char *json_str = NULL;
+
+ /* output the header */
+ printf("%s", header);
+ if (g_redirect_file_name != NULL)
+ wirte_buffer_to_file(g_redirect_file_name, header, strlen(header));
+ if (g_redirect_udp_port > 0 && g_redirect_udp_port < 65535)
+ udp_send("127.0.0.1", g_redirect_udp_port, header, strlen(header));
+
+ if (foramt != FMT_ATTR_CONTAINER || payload == NULL || payload_len <= 0)
+ return;
+
+ if ((json = attr2json(payload)) == NULL)
+ return;
+
+ if ((json_str = cJSON_Print(json)) == NULL) {
+ cJSON_Delete(json);
+ return;
+ }
+
+ /* output the payload as json format */
+ printf("%s", json_str);
+ if (g_redirect_file_name != NULL)
+ wirte_buffer_to_file(g_redirect_file_name, json_str, strlen(json_str));
+ if (g_redirect_udp_port > 0 && g_redirect_udp_port < 65535)
+ udp_send("127.0.0.1", g_redirect_udp_port, json_str, strlen(json_str));
+
+ free(json_str);
+ cJSON_Delete(json);
+}
+
+static void output_response(response_t *obj)
+{
+ char header[32] = { 0 };
+ snprintf(header, sizeof(header), "\nresponse status %d\n", obj->status);
+ output(header, obj->payload, obj->fmt, obj->payload_len);
+}
+
+static void output_event(request_t *obj)
+{
+ char header[256] = { 0 };
+ snprintf(header, sizeof(header), "\nreceived an event %s\n", obj->url);
+ output(header, obj->payload, obj->fmt, obj->payload_len);
+}
+
+int main(int argc, char *argv[])
+{
+ int ret;
+ imrt_link_recv_context_t recv_ctx = { 0 };
+ char buffer[BUF_SIZE] = { 0 };
+ uint32_t last_check, total_elpased_ms = 0;
+ bool is_responsed = false;
+ operation op;
+
+ memset(&op, 0, sizeof(op));
+
+ if (!parse_args(argc, argv, &op))
+ return -1;
+
+ //TODO: reconnect 3 times
+ if (init() != 0)
+ return -1;
+
+ switch (op.type) {
+ case INSTALL:
+ ret = install((inst_info *) &op.info.inst);
+ break;
+ case UNINSTALL:
+ ret = uninstall((uninst_info *) &op.info.uinst);
+ break;
+ case QUERY:
+ ret = query((query_info *) &op.info.query);
+ break;
+ case REQUEST:
+ ret = request((req_info *) &op.info.req);
+ break;
+ case REGISTER:
+ ret = subscribe((reg_info *) &op.info.reg);
+ break;
+ case UNREGISTER:
+ ret = unsubscribe((unreg_info *) &op.info.unreg);
+ break;
+ default:
+ goto ret;
+ }
+
+ if (ret != 0)
+ goto ret;
+
+ bh_get_elpased_ms(&last_check);
+
+ while (1) {
+ int result = 0;
+ fd_set readfds;
+ struct timeval tv;
+
+ total_elpased_ms += bh_get_elpased_ms(&last_check);
+
+ if (!is_responsed) {
+ if (total_elpased_ms >= g_timeout_ms) {
+ output("operation timeout\n", NULL, 0, 0);
+ ret = TIMEOUT_EXIT_CODE;
+ goto ret;
+ }
+ } else {
+ if (total_elpased_ms >= g_alive_time_ms) {
+ /*ret = 0;*/
+ goto ret;
+ }
+ }
+
+ if (g_conn_fd == -1) {
+ if (init() != 0) {
+ sleep(1);
+ continue;
+ }
+ }
+
+ FD_ZERO(&readfds);
+ FD_SET(g_conn_fd, &readfds);
+
+ tv.tv_sec = 1;
+ tv.tv_usec = 0;
+
+ result = select(FD_SETSIZE, &readfds, NULL, NULL, &tv);
+
+ if (result < 0) {
+ if (errno != EINTR) {
+ printf("Error in select, errno: 0x%x\n", errno);
+ ret = -1;
+ goto ret;
+ }
+ } else if (result == 0) { /* select timeout */
+ } else if (result > 0) {
+ int n;
+ if (FD_ISSET(g_conn_fd, &readfds)) {
+ int reply_type = -1;
+
+ n = read(g_conn_fd, buffer, BUF_SIZE);
+ if (n <= 0) {
+ g_conn_fd = -1;
+ continue;
+ }
+
+ reply_type = preocess_reply_data((char *) buffer, n, &recv_ctx);
+
+ if (reply_type == REPLY_TYPE_RESPONSE) {
+ response_t response[1] = { 0 };
+
+ parse_response_from_imrtlink(&recv_ctx.message, response);
+
+ if (response->mid != g_mid) {
+ /* ignore invalid response */
+ continue;
+ }
+
+ is_responsed = true;
+ ret = response->status;
+ output_response(response);
+
+ if (op.type == REGISTER || op.type == UNREGISTER) {
+ /* alive time start */
+ total_elpased_ms = 0;
+ bh_get_elpased_ms(&last_check);
+ }
+ } else if (reply_type == REPLY_TYPE_EVENT) {
+ request_t event[1] = { 0 };
+
+ parse_event_from_imrtlink(&recv_ctx.message, event);
+
+ if (op.type == REGISTER || op.type == UNREGISTER) {
+ output_event(event);
+ }
+ }
+ }
+ }
+ } /* end of while(1) */
+
+ ret: if (recv_ctx.message.payload != NULL)
+ free(recv_ctx.message.payload);
+
+ deinit();
+
+ return ret;
+}
diff --git a/test-tools/host-tool/src/transport.c b/test-tools/host-tool/src/transport.c
new file mode 100644
index 0000000000..0ccb62763d
--- /dev/null
+++ b/test-tools/host-tool/src/transport.c
@@ -0,0 +1,261 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "transport.h"
+
+#define SA struct sockaddr
+
+unsigned char leading[2] = { 0x12, 0x34 };
+
+bool tcp_init(const char *address, uint16_t port, int *fd)
+{
+ int sock;
+ struct sockaddr_in servaddr;
+
+ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
+ return false;
+
+ bzero(&servaddr, sizeof(servaddr));
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_addr.s_addr = inet_addr(address);
+ servaddr.sin_port = htons(port);
+
+ if (connect(sock, (SA*) &servaddr, sizeof(servaddr)) != 0)
+ return false;
+
+ *fd = sock;
+ return true;
+}
+
+int parse_baudrate(int baud)
+{
+ switch (baud) {
+ case 9600:
+ return B9600;
+ case 19200:
+ return B19200;
+ case 38400:
+ return B38400;
+ case 57600:
+ return B57600;
+ case 115200:
+ return B115200;
+ case 230400:
+ return B230400;
+ case 460800:
+ return B460800;
+ case 500000:
+ return B500000;
+ case 576000:
+ return B576000;
+ case 921600:
+ return B921600;
+ case 1000000:
+ return B1000000;
+ case 1152000:
+ return B1152000;
+ case 1500000:
+ return B1500000;
+ case 2000000:
+ return B2000000;
+ case 2500000:
+ return B2500000;
+ case 3000000:
+ return B3000000;
+ case 3500000:
+ return B3500000;
+ case 4000000:
+ return B4000000;
+ default:
+ return -1;
+ }
+}
+
+bool uart_init(const char *device, int baudrate, int *fd)
+{
+ int uart_fd;
+ struct termios uart_term;
+
+ uart_fd = open(device, O_RDWR | O_NOCTTY);
+
+ if (uart_fd <= 0)
+ return false;
+
+ memset(&uart_term, 0, sizeof(uart_term));
+ uart_term.c_cflag = baudrate | CS8 | CLOCAL | CREAD;
+ uart_term.c_iflag = IGNPAR;
+ uart_term.c_oflag = 0;
+
+ /* set noncanonical mode */
+ uart_term.c_lflag = 0;
+ uart_term.c_cc[VTIME] = 30;
+ uart_term.c_cc[VMIN] = 1;
+ tcflush(uart_fd, TCIFLUSH);
+
+ if (tcsetattr(uart_fd, TCSANOW, &uart_term) != 0) {
+ close(uart_fd);
+ return false;
+ }
+
+ *fd = uart_fd;
+
+ return true;
+}
+
+bool udp_send(const char *address, int port, const char *buf, int len)
+{
+ int sockfd;
+ struct sockaddr_in servaddr;
+
+ if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 )
+ return false;
+
+ memset(&servaddr, 0, sizeof(servaddr));
+
+ servaddr.sin_family = AF_INET;
+ servaddr.sin_port = htons(port);
+ servaddr.sin_addr.s_addr = INADDR_ANY;
+
+ sendto(sockfd, buf, len, MSG_CONFIRM, (const struct sockaddr *) &servaddr,
+ sizeof(servaddr));
+
+ close(sockfd);
+
+ return true;
+}
+
+bool host_tool_send_data(int fd, const char *buf, unsigned int len)
+{
+ int cnt = 0;
+ ssize_t ret;
+
+ if (fd == -1 || buf == NULL || len <= 0) {
+ return false;
+ }
+
+ resend: ret = write(fd, buf, len);
+
+ if (ret == -1) {
+ if (errno == ECONNRESET) {
+ close(fd);
+ }
+
+ // repeat sending if the outbuffer is full
+ if (errno == EAGAIN || errno == EWOULDBLOCK) {
+ if (++cnt > 10) {
+ close(fd);
+ return false;
+ }
+ sleep(1);
+ goto resend;
+ }
+ }
+
+ return (ret == len);
+}
+
+#define SET_RECV_PHASE(ctx, new_phase) {ctx->phase = new_phase; ctx->size_in_phase = 0;}
+
+/*
+ * input: 1 byte from remote
+ * output: parse result
+ * return: -1 invalid sync byte
+ * 1 byte added to buffer, waiting more for complete packet
+ * 0 completed packet
+ * 2 in receiving payload
+ */
+int on_imrt_link_byte_arrive(unsigned char ch, imrt_link_recv_context_t *ctx)
+{
+ if (ctx->phase == Phase_Non_Start) {
+ if (ctx->message.payload) {
+ free(ctx->message.payload);
+ ctx->message.payload = NULL;
+ ctx->message.payload_size = 0;
+ }
+
+ if (leading[0] == ch) {
+ ctx->phase = Phase_Leading;
+ } else {
+ return -1;
+ }
+ } else if (ctx->phase == Phase_Leading) {
+ if (leading[1] == ch) {
+ SET_RECV_PHASE(ctx, Phase_Type);
+ } else {
+ ctx->phase = Phase_Non_Start;
+ return -1;
+ }
+ } else if (ctx->phase == Phase_Type) {
+ unsigned char *p = (unsigned char *) &ctx->message.message_type;
+ p[ctx->size_in_phase++] = ch;
+
+ if (ctx->size_in_phase == sizeof(ctx->message.message_type)) {
+ ctx->message.message_type = ntohs(ctx->message.message_type);
+ SET_RECV_PHASE(ctx, Phase_Size);
+ }
+ } else if (ctx->phase == Phase_Size) {
+ unsigned char * p = (unsigned char *) &ctx->message.payload_size;
+ p[ctx->size_in_phase++] = ch;
+
+ if (ctx->size_in_phase == sizeof(ctx->message.payload_size)) {
+ ctx->message.payload_size = ntohl(ctx->message.payload_size);
+ SET_RECV_PHASE(ctx, Phase_Payload);
+
+ if (ctx->message.payload) {
+ free(ctx->message.payload);
+ ctx->message.payload = NULL;
+ }
+
+ /* no payload */
+ if (ctx->message.payload_size == 0) {
+ SET_RECV_PHASE(ctx, Phase_Non_Start);
+ return 0;
+ }
+
+ if (ctx->message.payload_size > 1024 * 1024) {
+ SET_RECV_PHASE(ctx, Phase_Non_Start);
+ return -1;
+ }
+
+ ctx->message.payload = (char *) malloc(ctx->message.payload_size);
+ SET_RECV_PHASE(ctx, Phase_Payload);
+ }
+ } else if (ctx->phase == Phase_Payload) {
+ ctx->message.payload[ctx->size_in_phase++] = ch;
+
+ if (ctx->size_in_phase == ctx->message.payload_size) {
+ SET_RECV_PHASE(ctx, Phase_Non_Start);
+ return 0;
+ }
+
+ return 2;
+ }
+
+ return 1;
+}
diff --git a/test-tools/host-tool/src/transport.h b/test-tools/host-tool/src/transport.h
new file mode 100644
index 0000000000..6d978d792a
--- /dev/null
+++ b/test-tools/host-tool/src/transport.h
@@ -0,0 +1,122 @@
+/*
+ * Copyright (C) 2019 Intel Corporation. All rights reserved.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#ifndef DEPS_APP_MGR_HOST_TOOL_SRC_TRANSPORT_H_
+#define DEPS_APP_MGR_HOST_TOOL_SRC_TRANSPORT_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* IMRT link message between host and WAMR */
+typedef struct {
+ unsigned short message_type;
+ unsigned long payload_size;
+ char *payload;
+} imrt_link_message_t;
+
+/* The receive phase of IMRT link message */
+typedef enum {
+ Phase_Non_Start, Phase_Leading, Phase_Type, Phase_Size, Phase_Payload
+} recv_phase_t;
+
+/* The receive context of IMRT link message */
+typedef struct {
+ recv_phase_t phase;
+ int size_in_phase;
+ imrt_link_message_t message;
+} imrt_link_recv_context_t;
+
+/**
+ * @brief Send data to WAMR.
+ *
+ * @param fd the connection fd to WAMR
+ * @param buf the buffer that contains content to be sent
+ * @param len size of the buffer to be sent
+ *
+ * @return true if success, false if fail
+ */
+bool host_tool_send_data(int fd, const char *buf, unsigned int len);
+
+/**
+ * @brief Handle one byte of IMRT link message
+ *
+ * @param ch the one byte from WAMR to be handled
+ * @param ctx the receive context
+ *
+ * @return -1 invalid sync byte
+ * 1 byte added to buffer, waiting more for complete packet
+ * 0 completed packet
+ * 2 in receiving payload
+ */
+int on_imrt_link_byte_arrive(unsigned char ch, imrt_link_recv_context_t *ctx);
+
+/**
+ * @brief Initialize TCP connection with remote server.
+ *
+ * @param address the network address of peer
+ * @param port the network port of peer
+ * @param fd pointer of integer to save the socket fd once return success
+ *
+ * @return true if success, false if fail
+ */
+bool tcp_init(const char *address, uint16_t port, int *fd);
+
+/**
+ * @brief Initialize UART connection with remote.
+ *
+ * @param device name of the UART device
+ * @param baudrate baudrate of the device
+ * @param fd pointer of integer to save the uart fd once return success
+ *
+ * @return true if success, false if fail
+ */
+bool uart_init(const char *device, int baudrate, int *fd);
+
+/**
+ * @brief Parse UART baudrate from an integer
+ *
+ * @param the baudrate interger to be parsed
+ *
+ * @return true if success, false if fail
+ *
+ * @par
+ * @code
+ * int baudrate = parse_baudrate(9600);
+ * ...
+ * uart_term.c_cflag = baudrate;
+ * ...
+ * @endcode
+ */
+int parse_baudrate(int baud);
+
+/**
+ * @brief Send data over UDP.
+ *
+ * @param address network address of the remote
+ * @param port network port of the remote
+ * @param buf the buffer that contains content to be sent
+ * @param len size of the buffer to be sent
+ *
+ * @return true if success, false if fail
+ */
+bool udp_send(const char *address, int port, const char *buf, int len);
+
+#ifdef __cplusplus
+} /* end of extern "C" */
+#endif
+
+#endif /* DEPS_APP_MGR_HOST_TOOL_SRC_TRANSPORT_H_ */