Initial snapshot of stm-log

Preliminary changes for the stm-log userspace library for
logging via STM.

Change-Id: Ief82b6c8c7847b26ebbbe0d9f6512c7d97cd48f5
diff --git a/Android.mk b/Android.mk
new file mode 100644
index 0000000..a18167c
--- /dev/null
+++ b/Android.mk
@@ -0,0 +1,28 @@
+ifeq ($(call is-vendor-board-platform,QCOM),true)
+
+LOCAL_PATH := $(call my-dir)
+
+include $(CLEAR_VARS)
+
+LOCAL_SRC_FILES := \
+	stm-log.c
+
+LOCAL_C_INCLUDES += \
+	$(LOCAL_PATH) \
+	system/core/include \
+	$(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr/include
+
+LOCAL_ADDITIONAL_DEPENDENCIES += $(TARGET_OUT_INTERMEDIATES)/KERNEL_OBJ/usr
+
+LOCAL_CFLAGS += \
+	-Wall
+
+# Debug
+# LOCAL_CFLAGS += -DDEBUG
+# LOCAL_SHARED_LIBRARIES += liblog
+
+LOCAL_MODULE := libstm-log
+LOCAL_MODULE_TAGS := optional
+
+include $(BUILD_SHARED_LIBRARY)
+endif
diff --git a/stm-log.c b/stm-log.c
new file mode 100644
index 0000000..90e93ea
--- /dev/null
+++ b/stm-log.c
@@ -0,0 +1,183 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <stdint.h>
+#include <stdarg.h>
+#include <stdio.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <linux/coresight-stm.h>
+#include <stm-log.h>
+#include <string.h>
+
+#ifdef DEBUG
+#define LOG_TAG "STM-LOG"
+#include <cutils/log.h>
+#endif
+
+#define STM_LOG_DEV     "/dev/coresight-stm"
+#define STM_LOG_MAGIC_0 0xf0
+#define STM_LOG_MAGIC_1 0xf1
+
+static uint8_t dflt_stm_entity_id = OST_ENTITY_NONE;
+static uint8_t dflt_stm_proto_id  = 0;
+static uint32_t dflt_stm_options  = STM_OPTION_TIMESTAMPED;
+
+typedef struct
+{
+    uint8_t  magic[2];
+    uint8_t  entity;
+    uint8_t  proto;
+    uint32_t options;
+} stmlog_t;
+
+void stm_log_initdefaults(uint32_t init_mask,
+                          uint8_t  entity_id,
+                          uint8_t  proto_id,
+                          uint32_t options)
+{
+    if ((init_mask & STM_DFLT_ENTITY) != 0) {
+        dflt_stm_entity_id = entity_id;
+    }
+    if ((init_mask & STM_DFLT_PROTOCOL) != 0) {
+        dflt_stm_proto_id = proto_id;
+    }
+    if ((init_mask & STM_DFLT_OPTIONS) != 0) {
+        dflt_stm_options = options;
+    }
+#ifdef DEBUG
+    if ((init_mask & ~(STM_DFLT_ENTITY
+                       | STM_DFLT_PROTOCOL
+                       | STM_DFLT_OPTIONS)) != 0) {
+        ALOGE("Invalid init mask 0x%08x", init_mask);
+    }
+#endif
+}
+
+int STMLOG_WRITE(int len, void *data) {
+    int fd;
+    int rc = -1;
+    fd = open(STM_LOG_DEV, O_WRONLY);
+    if (fd >= 0) {
+        do {
+            rc = write(fd, data, len);
+            if (rc == -1)
+                break;
+            len -= rc;
+        } while (len > 0);
+        close(fd);
+    }
+#ifdef DEBUG
+    ALOGE("Failed to write to stm log");
+#endif
+    return rc;
+}
+
+void stm_log(const char *format, ...)
+{
+    va_list ap;
+    va_start(ap, format);
+    stm_log_ex(dflt_stm_entity_id,
+               dflt_stm_proto_id,
+               dflt_stm_options,
+               format,
+               ap);
+    va_end(ap);
+}
+
+void stm_logbin(int length, void *data)
+{
+    stm_logbin_ex(dflt_stm_entity_id,
+                  dflt_stm_proto_id,
+                  dflt_stm_options,
+                  length,
+                  data);
+}
+
+void stm_log_ex(uint8_t     entity_id,
+                uint8_t     proto_id,
+                uint32_t    options,
+                const char *format, ...)
+{
+    int length;
+    char *buf;
+    stmlog_t *log;
+    va_list ap;
+
+    va_start(ap, format);
+    length = vsnprintf(NULL, 0, format, ap);
+    if (length >= 0) {
+        length++;
+        buf = (char *)malloc(sizeof(stmlog_t) + length);
+        if (buf) {
+            log = (stmlog_t *)buf;
+            log->magic[0] = STM_LOG_MAGIC_0;
+            log->magic[1] = STM_LOG_MAGIC_1;
+            log->entity   = entity_id;
+            log->proto    = proto_id;
+            log->options  = options;
+            vsnprintf(buf + sizeof(stmlog_t), length, format, ap);
+            STMLOG_WRITE(sizeof(stmlog_t) + length, buf);
+            free(buf);
+        }
+#ifdef DEBUG
+        else {
+            ALOGE("Out of memory allocating temp buffer");
+        }
+#endif
+    }
+    va_end(ap);
+}
+
+void stm_logbin_ex(uint8_t     entity_id,
+                   uint8_t     proto_id,
+                   uint32_t    options,
+                   int         length,
+                   void        *data)
+{
+    uint8_t  *buf;
+    stmlog_t *stm;
+    buf = (uint8_t *)malloc(sizeof(stmlog_t) + length);
+    if (buf) {
+        stm = (stmlog_t *)buf;
+        stm->magic[0] = STM_LOG_MAGIC_0;
+        stm->magic[1] = STM_LOG_MAGIC_1;
+        stm->entity   = entity_id;
+        stm->proto    = proto_id;
+        stm->options  = options;
+        memcpy(buf + sizeof(stmlog_t), data, length);
+        STMLOG_WRITE(sizeof(stmlog_t) + length, buf);
+        free(buf);
+    }
+#ifdef DEBUG
+    else {
+        ALOGE("Out of memory allocating temp buffer");
+    }
+#endif
+}
diff --git a/stm-log.h b/stm-log.h
new file mode 100644
index 0000000..c88d5a6
--- /dev/null
+++ b/stm-log.h
@@ -0,0 +1,57 @@
+/* Copyright (c) 2012, The Linux Foundation. All rights reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions are
+ * met:
+ *     * Redistributions of source code must retain the above copyright
+ *       notice, this list of conditions and the following disclaimer.
+ *     * Redistributions in binary form must reproduce the above
+ *       copyright notice, this list of conditions and the following
+ *       disclaimer in the documentation and/or other materials provided
+ *       with the distribution.
+ *     * Neither the name of The Linux Foundation nor the names of its
+ *       contributors may be used to endorse or promote products derived
+ *       from this software without specific prior written permission.
+ *
+ * THIS SOFTWARE IS PROVIDED "AS IS" AND ANY EXPRESS OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
+ * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NON-INFRINGEMENT
+ * ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR
+ * BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY,
+ * WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE
+ * OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN
+ * IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#ifndef __STM_LOG__
+#define __STM_LOG__
+
+#include <stdint.h>
+#include <linux/coresight-stm.h>
+
+enum {
+    STM_DFLT_ENTITY   = 0x01,
+    STM_DFLT_PROTOCOL = 0x02,
+    STM_DFLT_OPTIONS  = 0x04,
+};
+
+void stm_log_initdefaults(uint32_t init_mask,
+                          uint8_t  entity_id,
+                          uint8_t  proto_id,
+                          uint32_t options);
+
+void stm_log(const char *format, ...);
+void stm_logbin(int length, void *data);
+void stm_log_ex(uint8_t     entity_id,
+                uint8_t     proto_id,
+                uint32_t    options,
+                const char *format, ...);
+void stm_logbin_ex(uint8_t     entity_id,
+                   uint8_t     proto_id,
+                   uint32_t    options,
+                   int         length,
+                   void        *data);
+#endif /* __STM_LOG__ */
diff --git a/stm-log.txt b/stm-log.txt
new file mode 100644
index 0000000..78a51f4
--- /dev/null
+++ b/stm-log.txt
@@ -0,0 +1,104 @@
+STM Logging
+===========
+
+This library provides an interface for userspace application to log via STM.
+Note that the task must already have write permission to the stm device node.
+
+This file describes the STM logging API's and associate definitions.
+
+
+1) Definitions:
+~~~~~~~~~~~~~~~
+1.1) Header file includes:
+  #include <stdint.h>
+  #include <linux/coresight-stm.h>
+  #include <stm_log.h>  // stmlog.h resides in /vendor/qcom/opensource/stmlog/inc
+                        // and must be part of the compiler include search path
+
+1.2) Linking:
+  The STM logging library is available in dynamic library form.
+
+1.3) Entity ID:
+  Description:
+    Entity ID is an unsigned byte value (range 0-255) and are pre-allocated
+    for each individual clients.  The entity ID allocation is defined in the
+    kernel file /usr/include/linux/coresight-stm.h.  Refer to the kernel
+    header file for instructions on allocating a new entity ID.
+
+    Note that entity ID's are not verified at runtime for clients, so it is
+    possible for a different client to (incorrectly) use the wrong ID.
+
+
+2) Initialization functions:
+~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+
+2.1) stm_log_initdefaults(uint32_t init_mask,
+                          uint8_t  entity_id,
+                          uint8_t  proto_id,
+                          uint32_t options)
+  Description:
+    Optional initialization function to specify the default entity ID, protocol
+    ID and/or options for stm logging.  Takes effect on all subsequent calls
+    to the STM logging API.
+
+    If this function is not called then a compile-time default is used with
+    entity ID of zero (OST_ENTITY_NONE).
+
+  Parameters:
+    init_mask: Indicate which default parameter(s) is being set (bitmask).
+                 STM_DFLT_ENTITY
+                 STM_DFLT_PROTOCOL
+                 STM_DFLT_OPTIONS
+    entity_id: Specify the default entity ID
+    proto_id:  Specify the default protocol ID
+    options:   Specify the default options; refer to kernel's coresight-stm.h
+               Currently available options are:
+                 STM_OPTION_NONE
+                 STM_OPTION_TIMESTAMPED
+                 STM_OPTION_GUARANTEED
+
+  Example:
+    // Set default entity id to 5 and enable log timestamps
+    stmlog_initdefaults(STM_DFLT_ENTITY | STM_DFLT_OPTIONS,
+                        5, 0, STM_OPTION_TIMESTAMPED);
+
+
+3) Logging functions:
+~~~~~~~~~~~~~~~~~~~~~
+
+3.1) stm_log(const char *format, ...)
+  Description:
+    Generate a log via STM using the default entity/protocol ID and options.
+    The parameters are passed to vsprintf() for parsing and so %d/%s/etc.
+    parameters are valid.
+
+  Parameters:
+    Refer to man pages for printf() for details.
+
+  Examples:
+    stm_log("event X");
+    stm_log("event Y, data %d", varY);
+
+3.2) stm_logbin(int length, void *data)
+  Description:
+    Generate a binary via STM using the default entity/protocol ID and options.
+
+3.3) stm_log_ex(uint8_t     entity_id,
+                uint8_t     proto_id,
+                uint32_t    options,
+                const char *format, ...)
+  Description:
+    An extended form of stmlog() to explicitly specify all options for logging
+    (e.g. override the entity/protocol ID's or options).
+
+  Parameters:
+    entity_id: Specify the default entity ID
+    proto_id:  Specify the default protocol ID
+    options:   Specify the default options
+    ...:       Same as stmlog()
+
+3.4) stm_logbin_ex(uint8_t     entity_id,
+                   uint8_t     proto_id,
+                   uint32_t    options,
+                   int         length,
+                   void        *data)