From 722cba49b9d8628f2407d73b7b0c231bef357ac7 Mon Sep 17 00:00:00 2001 From: Pranav Mahesh Phansalkar Date: Tue, 30 Dec 2025 01:14:45 +0530 Subject: [PATCH] qmi-framework: Enable level-based QCCI and QCSI logging This change introduces configurable, level-based logging for the QMI Common Client Interface (QCCI) and QMI Common Service Interface (QCSI) components. Signed-off-by: Pranav Mahesh Phansalkar --- build_script.sh | 236 ++++++++++++++++++++++++++++++----------- configure.ac | 14 ++- qcci/Makefile.am | 6 +- qcci/qcci_os.c | 121 ++++++++++++++++----- qcci/qcci_os.h | 72 +++---------- qcci/qcci_xport_qrtr.c | 15 +-- qcsi/Makefile.am | 6 +- qcsi/qcsi_common.c | 5 +- qcsi/qcsi_os.c | 120 +++++++++++++++++---- qcsi/qcsi_os.h | 80 ++++---------- qcsi/qcsi_xport_qrtr.c | 51 ++++----- tests/qcsi_test.c | 7 +- 12 files changed, 455 insertions(+), 278 deletions(-) diff --git a/build_script.sh b/build_script.sh index f9ddd83..44e313e 100755 --- a/build_script.sh +++ b/build_script.sh @@ -1,80 +1,190 @@ -# Copyright (c) 2024, Qualcomm Innovation Center, Inc. All rights reserved. +#!/usr/bin/env bash +# Copyright (c) 2024, Qualcomm Innovation Center, Inc. +# All rights reserved. # SPDX-License-Identifier: BSD-3-Clause +set -euo pipefail + +# Default host (native build) HOST_ARCH="x86_64-linux-gnu" +PREFIX_DIR="$(pwd)/install" # base install prefix +BUILD_BASE="$(pwd)/build" # out-of-tree build root + +usage() { + cat <] [--prefix ] + +Examples: + # Native build on x86_64 + $0 + + # Cross build for aarch64 glibc + $0 --host aarch64-linux-gnu + + # Cross build for Android aarch64 (needs NDK_PATH and optional ANDROID_API) + NDK_PATH=\$HOME/android-ndk-r26d ANDROID_API=21 $0 --host aarch64-linux-android + + # Custom prefix + $0 --host aarch64-linux-gnu --prefix /tmp/qmi-install +EOF +} while [[ "$#" -gt 0 ]]; do - case $1 in + case "$1" in --host) HOST_ARCH="$2" shift 2 ;; + --prefix) + PREFIX_DIR="$2" + shift 2 + ;; + -h|--help) + usage + exit 0 + ;; *) - echo "Warning: Unknown parameter passed: $1." + echo "Warning: Unknown parameter passed: $1" >&2 shift 1 ;; esac done - -echo "Cleaning up previous build.." -make clean -rm -rf install - - -echo "Running autoreconf.." -autoreconf --install || { echo "Autoreconf failed"; exit 1; } - -echo "Running configure.." -./configure --host=$HOST_ARCH --prefix=$(pwd)/install || { echo "configure failed"; exit 1; } - -echo "Running make.." -make || { echo "make failed"; exit 1; } - -make install || { echo "make install failed"; exit 1; } - - -FILES_TO_CLEAN=( - aclocal.m4 configure ar-lib config.h config.h.in config.log config.status libtool - Makefile Makefile.in compile config.guess install-sh missing mkinstalldirs depcomp - ltmain.sh stamp-h1 config.sub *subs.sh -) -DIRECTORIES_TO_CLEAN=( - autom4te.cache - m4 +echo "=======================================" +echo " Host triplet : ${HOST_ARCH}" +echo " Install prefix: ${PREFIX_DIR}" +echo " Build base : ${BUILD_BASE}" +echo "=======================================" + +SRC_DIR="$(pwd)" +BUILD_DIR="${BUILD_BASE}/${HOST_ARCH}" +INSTALL_DIR="${PREFIX_DIR}/${HOST_ARCH}" + +mkdir -p "${BUILD_DIR}" "${INSTALL_DIR}" + +echo "Using build dir : ${BUILD_DIR}" +echo "Using install dir : ${INSTALL_DIR}" +echo + +# Optional: set toolchain based on host triplet. +CC_FOR_HOST="" +CXX_FOR_HOST="" + +case "${HOST_ARCH}" in + aarch64-linux-android) + # For Android builds you must provide (or accept defaults): + # NDK_PATH -> path to Android NDK root + # ANDROID_API -> Android API level (e.g. 21, 28, 30) + : "${NDK_PATH:=$HOME/android-ndk-r26d}" + : "${ANDROID_API:=21}" + + TOOLCHAIN="${NDK_PATH}/toolchains/llvm/prebuilt/linux-x86_64/bin" + CC_FOR_HOST="${TOOLCHAIN}/aarch64-linux-android${ANDROID_API}-clang" + CXX_FOR_HOST="${TOOLCHAIN}/aarch64-linux-android${ANDROID_API}-clang++" + ;; + + aarch64-linux-gnu|arm64-linux-gnu) + CC_FOR_HOST="aarch64-linux-gnu-gcc" + CXX_FOR_HOST="aarch64-linux-gnu-g++" + ;; + + arm-linux-gnueabihf|arm-linux-gnueabi) + CC_FOR_HOST="arm-linux-gnueabihf-gcc" + CXX_FOR_HOST="arm-linux-gnueabihf-g++" + ;; + + x86_64-linux-gnu) + CC_FOR_HOST="gcc" + CXX_FOR_HOST="g++" + ;; + + *) + echo "Note: No specific toolchain mapping for host='${HOST_ARCH}'." + echo " Relying on environment CC/CXX (if set) or system defaults." + ;; +esac + +# Environment args for configure/make; passed via 'env' +env_args=() +[[ -n "${CC_FOR_HOST}" ]] && env_args+=(CC="${CC_FOR_HOST}") +[[ -n "${CXX_FOR_HOST}" ]] && env_args+=(CXX="${CXX_FOR_HOST}") + +echo "Toolchain env (for this build only):" +if [[ ${#env_args[@]} -eq 0 ]]; then + echo " (none, using system/default CC/CXX)" +else + for v in "${env_args[@]}"; do + echo " $v" + done +fi +echo + +echo "Cleaning build directory for this host..." +rm -rf "${BUILD_DIR:?}"/* +cd "${BUILD_DIR}" + +echo "Running autoreconf in source tree..." +( + cd "${SRC_DIR}" + autoreconf --install ) -for file in "${FILES_TO_CLEAN[@]}"; do - if [ -f "$file" ]; then - rm -f "$file" - fi -done - -for dir in "${DIRECTORIES_TO_CLEAN[@]}"; do - if [ -d "$dir" ]; then - rm -rf "$dir" - fi -done - -make clean - -# Clean up bin executables in subdirectories, excluding the install directory -find . -type f -name 'qcci_test' ! -path './install/*' -exec rm -f {} + -find . -type f -name 'qcsi_test' ! -path './install/*' -exec rm -f {} + - -# Clean up bin executables in subdirectories -find . -type f -name 'bin' -exec rm -f {} + - -# Additional cleanup for .la files and other generated files -find . -name '*.la' -delete -find . -name '*.o' -delete -find . -name '*.lo' -delete -find . -name '*.libs' -type d -exec rm -rf {} + -find . -name '.deps' -type d -exec rm -rf {} + -find . -name '.dir' -type d -exec rm -rf {} + - -# Remove Makefile and Makefile.in from subdirectories -find . -name 'Makefile' -exec rm -f {} + -find . -name 'Makefile.in' -exec rm -f {} + - -echo "Build completed successfully." +echo "Running configure..." +env "${env_args[@]}" "${SRC_DIR}/configure" \ + --host="${HOST_ARCH}" \ + --prefix="${INSTALL_DIR}" + +echo "Running make..." +env "${env_args[@]}" make -j"$(nproc)" + +echo "Running make install..." +env "${env_args[@]}" make install + +echo "Per-host build done." +echo "Artifacts:" +echo " Build : ${BUILD_DIR}" +echo " Install : ${INSTALL_DIR}" +echo + +# Optional deep clean of *generated* autotools files in the source tree. +# Enable via: DEEP_CLEAN=1 ./build_script.sh ... +if [[ "${DEEP_CLEAN:-0}" == "1" ]]; then + echo "Performing deep clean of autotools artifacts in source tree..." + cd "${SRC_DIR}" + + FILES_TO_CLEAN=( + aclocal.m4 configure ar-lib config.h config.h.in config.log config.status libtool + Makefile Makefile.in compile config.guess install-sh missing mkinstalldirs depcomp + ltmain.sh stamp-h1 config.sub *subs.sh + ) + DIRECTORIES_TO_CLEAN=( + autom4te.cache + m4 + ) + + for file in "${FILES_TO_CLEAN[@]}"; do + if [[ -f "$file" ]]; then + rm -f "$file" + fi + done + + for dir in "${DIRECTORIES_TO_CLEAN[@]}"; do + if [[ -d "$dir" ]]; then + rm -rf "$dir" + fi + done + + # Aggressive find-based clean; only under DEEP_CLEAN + find . -name '*.la' -delete + find . -name '*.o' -delete + find . -name '*.lo' -delete + find . -name '*.libs' -type d -exec rm -rf {} + + find . -name '.deps' -type d -exec rm -rf {} + + find . -name '.dir' -type d -exec rm -rf {} + + find . -name 'Makefile' -exec rm -f {} + + find . -name 'Makefile.in' -exec rm -f {} + + + echo "Deep clean completed." +fi + +echo "Build completed successfully for host='${HOST_ARCH}' " \ No newline at end of file diff --git a/configure.ac b/configure.ac index c672236..034eee4 100644 --- a/configure.ac +++ b/configure.ac @@ -30,8 +30,18 @@ AS_CASE([$host], AM_CONDITIONAL([GNU_CC], [test "$compile_for_gnu" = yes]) -#Enable QMI FW logging -AM_CONDITIONAL(ENABLE_QMI_LOG, test "x${with_qmilog}" = "xyes") +dnl Enable Android-specific logging (uses -llog etc.) +AS_CASE([$host], + [*-linux-android*], [ + enable_android_logging=yes + ], [ + enable_android_logging=no + ] +) + +AM_CONDITIONAL([ENABLE_ANDROID_LOGGING], + [test "x$enable_android_logging" = "xyes"]) + QCCI_DEBUG_LEVEL=3 QCSI_DEBUG_LEVEL=3 diff --git a/qcci/Makefile.am b/qcci/Makefile.am index 8133d40..52f68f4 100644 --- a/qcci/Makefile.am +++ b/qcci/Makefile.am @@ -18,16 +18,12 @@ AM_CPPFLAGS = \ $(QMI_CFLAGS) \ $(QMIFV_CFLAGS) -if ENABLE_QMI_LOG -AM_CFLAGS += -DQMI_ANDROID_LOGGING_LE -endif - h_sources = \ qcci_os.h requiredlibs = ../qencdec/libqencdec.la -if ENABLE_QMI_LOG +if ENABLE_ANDROID_LOGGING requiredlibs += -llog endif diff --git a/qcci/qcci_os.c b/qcci/qcci_os.c index 3eb0f7b..6648314 100644 --- a/qcci/qcci_os.c +++ b/qcci/qcci_os.c @@ -7,46 +7,119 @@ #include #include #include +#include #include "qmi_cci.h" #include "qcci_os.h" #include "qcci_common.h" #include "config.h" -#ifdef QMI_FW_SYSLOG - #define QCCI_DEFAULT_DBG_LEVEL 4 -#else - #define QCCI_DEFAULT_DBG_LEVEL 5 -#endif - -#ifdef QMI_CCI_SYSTEM - #define QMI_FW_CONF_FILE "/etc/qmi_fw.conf" -#else - #define QMI_FW_CONF_FILE "/vendor/etc/qmi_fw.conf" -#endif +#define QMI_FW_CONF_FILE "/etc/qmi_fw.conf" #define MAX_LINE_LENGTH 80 -#define QCCI_DBG_CONF_STR "QMI_CCI_DEBUG_LEVEL=" extern qcci_xport_ops_type qcci_qrtr_ops; extern void qcci_xport_qrtr_deinit(void); -unsigned int qcci_debug_level; +#ifdef __ANDROID__ +#include +#else +#include +#endif -/** - * @brief Debug level init. - * - */ -#if defined(QMI_FW_ANDROID) || defined(QMI_FW_SYSLOG) || defined(QMI_ANDROID_LOGGING_LE) -static void qcci_debug_init(void) +int qcci_loglevel = QCCI_LOG_ERR; + +static void qcci_set_loglevel(const char *val) { - qcci_debug_level = QCCI_DEBUG_LEVEL; + if (!val || !*val) + return; + + if (!strcasecmp(val, "NONE")) + qcci_loglevel = QCCI_LOG_NONE; + else if (!strcasecmp(val, "ERR")) + qcci_loglevel = QCCI_LOG_ERR; + else if (!strcasecmp(val, "WARN")) + qcci_loglevel = QCCI_LOG_WARN; + else if (!strcasecmp(val, "INFO")) + qcci_loglevel = QCCI_LOG_INFO; + else if (!strcasecmp(val, "DBG")) + qcci_loglevel = QCCI_LOG_DBG; + else if (!strcasecmp(val, "TRACE")) + qcci_loglevel = QCCI_LOG_TRACE; } -#else -static void qcci_debug_init(void) + +static void qcci_log_init_once(void) +{ + static int init; + if (init) + return; + + + FILE *f = fopen(QMI_FW_CONF_FILE, "r"); + if (f) { + char line[MAX_LINE_LENGTH]; + + while (fgets(line, sizeof(line), f)) { + char *p = line; + while (*p && isspace((unsigned char)*p)) + p++; + + const char *key = "QMI_LOG_LEVEL="; + size_t key_len = strlen(key); + + if (!strncmp(p, key, key_len)) { + char *val = p + key_len; + + char *end = val + strlen(val); + while (end > val && isspace((unsigned char)end[-1])) + *--end = '\0'; + + qcci_set_loglevel(val); + break; + } + } + + fclose(f); + } + + const char *env = getenv("QMI_LOG_LEVEL"); + if (env) { + qcci_set_loglevel(env); + } + +#ifndef __ANDROID__ + openlog("qcci", LOG_PID, LOG_USER); +#endif + init = 1; +} + +void qcci_log_write(qcci_log_level_t lvl, const char *fmt, ...) { + + if (lvl > qcci_loglevel) + return; + + char buf[512]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + +#ifdef __ANDROID__ + int pr = ANDROID_LOG_DEBUG; + if (lvl == QCCI_LOG_ERR) pr = ANDROID_LOG_ERROR; + else if (lvl == QCCI_LOG_WARN) pr = ANDROID_LOG_WARN; + else if (lvl == QCCI_LOG_INFO) pr = ANDROID_LOG_INFO; + __android_log_print(pr, "QMI_OS", "%s", buf); +#else + int pr = LOG_DEBUG; + if (lvl == QCCI_LOG_ERR) pr = LOG_ERR; + else if (lvl == QCCI_LOG_WARN) pr = LOG_WARNING; + else if (lvl == QCCI_LOG_INFO) pr = LOG_INFO; + syslog(pr, "QMI_OS: %s", buf); +#endif } -#endif /* QMI_FW_ANDROID) || QMI_FW_SYSLOG */ + /** * @brief Initialize the QCCI library. @@ -62,7 +135,7 @@ static void qcci_debug_init(void) #ifdef __GNUC__ void __attribute__ ((constructor)) qcci_fw_init(void) { - qcci_debug_init(); + qcci_log_init_once(); qcci_init(&qcci_qrtr_ops, NULL); } #endif diff --git a/qcci/qcci_os.h b/qcci/qcci_os.h index 224ee85..1132053 100644 --- a/qcci/qcci_os.h +++ b/qcci/qcci_os.h @@ -15,6 +15,7 @@ #include #include #include +#include #if defined(__GLIBC__) #include @@ -55,66 +56,27 @@ typedef pthread_mutex_t qcci_os_lock_type; param = param; \ } while(0) -/** - * @brief Macros for logging. - */ -#if defined(QMI_FW_ADB_LOG) || defined(QMI_ANDROID_LOGGING_LE) -#define LOG_TAG "QMI_FW" - -#ifdef QMI_ANDROID_LOGGING_LE -#include -#else -#include -#endif - -#ifdef QMI_CCI_ANDROID -extern unsigned int qcci_debug_level; -#define QCCI_LOG_INFO(x...) do { \ - if (qcci_debug_level <= ANDROID_LOG_INFO) \ - SLOGI("QCCI: "x); \ - } while(0) -#define QCCI_LOG_DBG(x...) do { \ - if (qcci_debug_level <= ANDROID_LOG_DEBUG) \ - SLOGD("QCCI: "x); \ - } while(0) -#else -#define QCCI_LOG_INFO(x...) -#define QCCI_LOG_DBG(x...) -#endif -#define QCCI_LOG_ERR(x...) ALOGE(x); -#elif defined(QMI_FW_SYSLOG) -#include +typedef enum { + QCCI_LOG_NONE = 0, + QCCI_LOG_ERR, + QCCI_LOG_WARN, + QCCI_LOG_INFO, + QCCI_LOG_DBG, + QCCI_LOG_TRACE, +} qcci_log_level_t; -extern unsigned int qcci_debug_level; -#define QCCI_LOG_INFO(x...) do { \ - if (qcci_debug_level >= LOG_INFO) \ - syslog(LOG_INFO, "QMI_FW: QCCI: "x); \ - } while(0) -#define QCCI_LOG_DBG(x...) do { \ - if (qcci_debug_level >= LOG_DEBUG) \ - syslog(LOG_DEBUG, "QMI_FW: QCCI: "x); \ - } while(0) - -#define QCCI_LOG_ERR(x...) syslog(LOG_ERR, x) - -#else -#define QCCI_LOG_INFO(x...) do { \ - fprintf(stdout, "%s(%d) ", __FUNCTION__, __LINE__); \ - fprintf(stdout, ##x); \ - } while(0) +extern int qcci_loglevel; -#define QCCI_LOG_DBG(x...) do { \ - fprintf(stdout, "%s(%d) ", __FUNCTION__, __LINE__); \ - fprintf(stdout, ##x); \ - } while(0) +void qcci_log_write(qcci_log_level_t lvl, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); -#define QCCI_LOG_ERR(x...) do { \ - fprintf(stderr, "%s(%d) ", __FUNCTION__, __LINE__); \ - fprintf(stderr, ##x); \ - } while(0) -#endif +#define QCCI_LOG_ERR(fmt, ...) qcci_log_write(QCCI_LOG_ERR, "QCCI: " fmt, ##__VA_ARGS__) +#define QCCI_LOG_WARN(fmt, ...) qcci_log_write(QCCI_LOG_WARN, "QCCI: " fmt, ##__VA_ARGS__) +#define QCCI_LOG_INFO(fmt, ...) qcci_log_write(QCCI_LOG_INFO, "QCCI: " fmt, ##__VA_ARGS__) +#define QCCI_LOG_DBG(fmt, ...) qcci_log_write(QCCI_LOG_DBG, "QCCI: " fmt, ##__VA_ARGS__) +#define QCCI_LOG_TRACE(fmt, ...) qcci_log_write(QCCI_LOG_TRACE, "QCCI: " fmt, ##__VA_ARGS__) /** * @brief Macro for logging transmitted messages. diff --git a/qcci/qcci_xport_qrtr.c b/qcci/qcci_xport_qrtr.c index 63df751..5c52686 100644 --- a/qcci/qcci_xport_qrtr.c +++ b/qcci/qcci_xport_qrtr.c @@ -401,8 +401,8 @@ static void *data_msg_reader_thread(void *arg) break; } else if (rx_len == 0) { if (addr_size == sizeof(struct sockaddr_qrtr)) { - QCCI_LOG_DBG("%s: QCCI Received Resume_Tx on FD %d from port %08x:%08x\n", - __func__, xp->fd, addr.sq_node, addr.sq_port); + QCCI_LOG_DBG("QCCI Received Resume_Tx on FD %d from port %08x:%08x\n", + xp->fd, addr.sq_node, addr.sq_port); qcci_xport_resume(xp->clnt); } else { QCCI_LOG_ERR("%s: No data read from %d\n", __func__, xp->fd); @@ -414,7 +414,8 @@ static void *data_msg_reader_thread(void *arg) continue; } - QCCI_LOG_DBG("%s: Received %d bytes from %d\n", __func__, (int)rx_len, xp->fd); + QCCI_LOG_DBG("XP[%d] Received %d bytes from svc 0x%x at 0x%X:0x%x\n", xp->fd, + (int)rx_len, xp->srv_name.service, addr.sq_node,addr.sq_port); src_addr.service = 0; src_addr.instance = 0; src_addr.node_id = addr.sq_node; @@ -430,7 +431,7 @@ static void *data_msg_reader_thread(void *arg) if(ch == 'd') { close(xp->rdr_tdata.wakeup_pipe[0]); close(xp->rdr_tdata.wakeup_pipe[1]); - QCCI_LOG_DBG("Close[%d]\n", xp->fd); + QCCI_LOG_DBG("Close[%d] for service:[%d]\n", xp->fd, xp->srv_name.service); close(xp->fd); pthread_attr_destroy(&xp->rdr_tdata.reader_tattr); release_xp(xp); @@ -634,7 +635,7 @@ static void *xport_open fcntl(xp->fd, F_SETFL, flags | O_NONBLOCK); if(write(xp->rdr_tdata.wakeup_pipe[1], "a", 1) < 0) QCCI_LOG_ERR("%s: Error writing to pipe\n", __func__); - QCCI_LOG_DBG("xport_open[%d]: max_rx_len=%d\n", xp->fd, max_rx_len); + QCCI_LOG_DBG("xport_open[%d]: max_rx_len=%d for service:[0x%x]\n", xp->fd, max_rx_len, service_id); xport_open_success: pthread_mutex_lock(&ctrl_port->xport_list_lock); @@ -694,8 +695,8 @@ static qmi_cci_error_type xport_send ntohs(s_addr->port_id), errno); return QMI_CLIENT_TRANSPORT_ERR; } - QCCI_LOG_DBG("Sent[%d]: %d bytes to port %d\n", xp->fd, len, - ntohs(s_addr->port_id)); + QCCI_LOG_DBG("Sent[%d]: %d bytes to service:[0x%x] at [0x%x:0x%x] \n", xp->fd, len, + xp->srv_name.service, s_addr->node_id, s_addr->port_id); return QMI_NO_ERR; } diff --git a/qcsi/Makefile.am b/qcsi/Makefile.am index 2718a34..c23c789 100644 --- a/qcsi/Makefile.am +++ b/qcsi/Makefile.am @@ -18,16 +18,12 @@ AM_CPPFLAGS = \ $(QMI_CFLAGS) \ $(QMIFV_CFLAGS) -if ENABLE_QMI_LOG -AM_CFLAGS += -DQMI_ANDROID_LOGGING_LE -endif - h_sources = \ qcsi_os.h requiredlibs = ../qencdec/libqencdec.la -if ENABLE_QMI_LOG +if ENABLE_ANDROID_LOGGING requiredlibs += -llog endif diff --git a/qcsi/qcsi_common.c b/qcsi/qcsi_common.c index 8864a50..dbe842d 100644 --- a/qcsi/qcsi_common.c +++ b/qcsi/qcsi_common.c @@ -661,6 +661,7 @@ qmi_csi_error_type qcsi_xport_connect /* invoke service_connect without lock held */ if(connect_cb) { + QCSI_LOG_ERR("Invoking service_connect cb for client handle %u\n", client_handle); cb_rc = connect_cb((qmi_client_handle)(uintptr_t)client_handle, service_cookie, &connection_handle); @@ -728,7 +729,7 @@ qmi_csi_error_type qcsi_xport_recv decode_header(buf, &cntl_flag, &txn_id, &msg_id, &msg_len); - QCSI_LOG_TX_PKT(svc->service_obj, cntl_flag, txn_id, msg_id, msg_len, + QCSI_LOG_RX_PKT(svc->service_obj, cntl_flag, txn_id, msg_id, msg_len, addr, xport->addr_len); /* got a client struct, handle only request */ @@ -1211,6 +1212,7 @@ qmi_csi_error_type qmi_csi_register ( os_params, NULL, service_provider); + } /** @@ -1307,7 +1309,6 @@ qmi_csi_error_type qcsi_send_resp_internal( send_resp_bail: UNLOCK(&txn_list_lock); - QCSI_LOG_ERR("%s Internal send: rc: %d \n", __func__,rc); return rc; } diff --git a/qcsi/qcsi_os.c b/qcsi/qcsi_os.c index 2636814..13228a2 100644 --- a/qcsi/qcsi_os.c +++ b/qcsi/qcsi_os.c @@ -8,36 +8,114 @@ #include #include #include +#include #include "qcsi_common.h" #include "config.h" +#include "qcsi_os.h" -#ifdef QMI_CCI_SYSTEM - #define QMI_FW_CONF_FILE "/etc/qmi_fw.conf" +#ifdef __ANDROID__ +#include #else - #define QMI_FW_CONF_FILE "/vendor/etc/qmi_fw.conf" +#include #endif +#define QMI_FW_CONF_FILE "/etc/qmi_fw.conf" + #define MAX_LINE_LENGTH 80 -#define qcsi_DBG_CONF_STR "qcsi_DEBUG_LEVEL=" -#ifdef QMI_FW_SYSLOG - #define DEFAULT_DBG_LEVEL 4 -#else - #define DEFAULT_DBG_LEVEL 5 +extern qcsi_xport_ops_type qcsi_qrtr_ops; + +int qcsi_loglevel = QCSI_LOG_ERR; + +static void qcsi_set_loglevel(const char *val) +{ + if (!val || !*val) + return; + + if (!strcasecmp(val, "NONE")) + qcsi_loglevel = QCSI_LOG_NONE; + else if (!strcasecmp(val, "ERR")) + qcsi_loglevel = QCSI_LOG_ERR; + else if (!strcasecmp(val, "WARN")) + qcsi_loglevel = QCSI_LOG_WARN; + else if (!strcasecmp(val, "INFO")) + qcsi_loglevel = QCSI_LOG_INFO; + else if (!strcasecmp(val, "DBG")) + qcsi_loglevel = QCSI_LOG_DBG; + else if (!strcasecmp(val, "TRACE")) + qcsi_loglevel = QCSI_LOG_TRACE; +} + +static void qcsi_log_init_once(void) +{ + static int init; + if (init) + return; + + + FILE *f = fopen(QMI_FW_CONF_FILE, "r"); + if (f) { + char line[MAX_LINE_LENGTH]; + + while (fgets(line, sizeof(line), f)) { + char *p = line; + while (*p && isspace((unsigned char)*p)) + p++; + + const char *key = "QMI_LOG_LEVEL="; + size_t key_len = strlen(key); + + if (!strncmp(p, key, key_len)) { + char *val = p + key_len; + + char *end = val + strlen(val); + while (end > val && isspace((unsigned char)end[-1])) + *--end = '\0'; + + qcsi_set_loglevel(val); + break; + } + } + + fclose(f); + } + + const char *env = getenv("QMI_LOG_LEVEL"); + if (env) { + qcsi_set_loglevel(env); + } + +#ifndef __ANDROID__ + openlog("qcsi", LOG_PID, LOG_USER); #endif + init = 1; +} -unsigned int qcsi_debug_level; /*= DEFAULT_DBG_LEVEL;*/ -extern qcsi_xport_ops_type qcsi_qrtr_ops; -/** - * @brief Initialize the QMI CSI debug level. - * - * This function initializes the QMI CSI debug level by reading the configuration - * file specified by QMI_FW_CONF_FILE. If the configuration file contains a valid - * debug level, it sets qcsi_debug_level to that value. - */ -void qcsi_debug_init(void) +void qcsi_log_write(qcsi_log_level_t lvl, const char *fmt, ...) { - qcsi_debug_level = QCSI_DEBUG_LEVEL; + + if (lvl > qcsi_loglevel) + return; + + char buf[512]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + +#ifdef __ANDROID__ + int pr = ANDROID_LOG_DEBUG; + if (lvl == QCSI_LOG_ERR) pr = ANDROID_LOG_ERROR; + else if (lvl == QCSI_LOG_WARN) pr = ANDROID_LOG_WARN; + else if (lvl == QCSI_LOG_INFO) pr = ANDROID_LOG_INFO; + __android_log_print(pr, "QMI_OS", "%s", buf); +#else + int pr = LOG_DEBUG; + if (lvl == QCSI_LOG_ERR) pr = LOG_ERR; + else if (lvl == QCSI_LOG_WARN) pr = LOG_WARNING; + else if (lvl == QCSI_LOG_INFO) pr = LOG_INFO; + syslog(pr, "QMI_OS: %s", buf); +#endif } @@ -55,13 +133,13 @@ void qcsi_debug_init(void) #ifdef __GNUC__ void __attribute__ ((constructor)) qcsi_fw_init(void) { - qcsi_debug_init(); + qcsi_log_init_once(); qcsi_init(&qcsi_qrtr_ops, NULL); } #endif /** - * @brief Cleans up the QCCI library. + * @brief Cleans up the QCSI library. * * This function is called after exit() or after the application's main() * completes. diff --git a/qcsi/qcsi_os.h b/qcsi/qcsi_os.h index 6ac17f5..ae6d31d 100644 --- a/qcsi/qcsi_os.h +++ b/qcsi/qcsi_os.h @@ -9,6 +9,7 @@ * @brief QMI CSI OS-specific utilities. */ #include +#include #include #include #include @@ -53,66 +54,25 @@ typedef pthread_mutex_t qcsi_lock_type; /** Free allocated memory */ #define FREE free -/** - * @brief Macros for logging. - */ -#if defined(QMI_FW_ADB_LOG) || defined(QMI_ANDROID_LOGGING_LE) -#define LOG_TAG "QMI_OS_FW" - -#ifdef QMI_ANDROID_LOGGING_LE -#include -#else -#include -#endif - -#ifdef QMI_CSI_ANDROID -extern unsigned int qcsi_debug_level; -#define QCSI_LOG_INFO(x...) do { \ - if (qcsi_debug_level <= ANDROID_LOG_INFO) \ - SLOGI("QCSI: "x); \ - } while(0) -#define QCSI_LOG_DBG(x...) do { \ - if (qcsi_debug_level <= ANDROID_LOG_DEBUG) \ - SLOGD("QCSI: "x); \ - } while(0) -#else -#define QCSI_LOG_INFO(x...) -#define QCSI_LOG_DBG(x...) -#endif - -#define QCSI_LOG_ERR(x...) ALOGE(x); - -#elif defined(QMI_FW_SYSLOG) -#include - -extern unsigned int qcsi_debug_level; -#define QCSI_LOG_INFO(x...) do { \ - if (qcsi_debug_level >= LOG_INFO) \ - syslog(LOG_INFO, "QMI_OS_FW: QCSI: "x); \ - } while(0) -#define QCSI_LOG_DBG(x...) do { \ - if (qcsi_debug_level >= LOG_DEBUG) \ - syslog(LOG_DEBUG, "QMI_OS_FW: QCSI: "x); \ - } while(0) - -#define QCSI_LOG_ERR(x...) syslog(LOG_ERR, x) - -#else -#define QCSI_LOG_INFO(x...) do { \ - fprintf(stdout, "%s(%d) ", __FUNCTION__, __LINE__); \ - fprintf(stdout, ##x); \ - } while(0) - -#define QCSI_LOG_DBG(x...) do { \ - fprintf(stdout, "%s(%d) ", __FUNCTION__, __LINE__); \ - fprintf(stdout, ##x); \ - } while(0) - -#define QCSI_LOG_ERR(x...) do { \ - fprintf(stderr, "%s(%d) ", __FUNCTION__, __LINE__); \ - fprintf(stderr, ##x); \ - } while(0) -#endif +typedef enum { + QCSI_LOG_NONE = 0, + QCSI_LOG_ERR, + QCSI_LOG_WARN, + QCSI_LOG_INFO, + QCSI_LOG_DBG, + QCSI_LOG_TRACE, +} qcsi_log_level_t; + +extern int qcsi_loglevel; + +void qcsi_log_write(qcsi_log_level_t lvl, const char *fmt, ...) + __attribute__((format(printf, 2, 3))); + +#define QCSI_LOG_ERR(fmt, ...) qcsi_log_write(QCSI_LOG_ERR, "QCSI: " fmt, ##__VA_ARGS__) +#define QCSI_LOG_WARN(fmt, ...) qcsi_log_write(QCSI_LOG_WARN, "QCSI: " fmt, ##__VA_ARGS__) +#define QCSI_LOG_INFO(fmt, ...) qcsi_log_write(QCSI_LOG_INFO, "QCSI: " fmt, ##__VA_ARGS__) +#define QCSI_LOG_DBG(fmt, ...) qcsi_log_write(QCSI_LOG_DBG, "QCSI: " fmt, ##__VA_ARGS__) +#define QCSI_LOG_TRACE(fmt, ...) qcsi_log_write(QCSI_LOG_TRACE, "QCSI: " fmt, ##__VA_ARGS__) /** * @brief Macro for logging transmitted messages. diff --git a/qcsi/qcsi_xport_qrtr.c b/qcsi/qcsi_xport_qrtr.c index 2d759f7..a4857e9 100644 --- a/qcsi/qcsi_xport_qrtr.c +++ b/qcsi/qcsi_xport_qrtr.c @@ -260,7 +260,7 @@ static void handle_resume_tx break; } else if(sendto_rc >= 0) { - QCSI_LOG_ERR("%s Sent [%d]: %d queued bytes for port %08x:%08x\n", __func__, + QCSI_LOG_DBG("%s Sent [%d]: %d queued bytes for port %08x:%08x\n", __func__, xp->fd, q_buf->len, dest->dest_addr->node_id, dest->dest_addr->port_id); } @@ -329,7 +329,6 @@ static void *xport_open pthread_mutexattr_init(&mta); int align_size = 0; - QCSI_LOG_ERR("xport_open[%d]: Enter\n", xp->fd); if (!xp) { QCSI_LOG_ERR("%s: xp calloc failed\n", __func__); return NULL; @@ -357,7 +356,7 @@ static void *xport_open if (init_socket(xp, os_params) != QCSI_NO_ERR) goto xport_open_free_xp; - QCSI_LOG_ERR("xport_open[%d]: max_rx_len=%d\n", xp->fd, max_rx_len); + QCSI_LOG_DBG("xport_open[%d]: max_rx_len=%d\n", xp->fd, max_rx_len); return xp; xport_open_free_xp: @@ -379,17 +378,17 @@ static qmi_csi_error_type xport_reg int rc; if (service_id == (uint32_t)-1 || version == (uint32_t)-1) { - QCSI_LOG_ERR("%s Invalid svc:%d ins:%d\n", __func__, service_id, version); + QCSI_LOG_ERR("Invalid svc:%d ins:%d\n", service_id, version); return QCSI_INTERNAL_ERR; } if(getsockname(xp->fd, (void *)&sq, &sl)) { - QCSI_LOG_ERR("%s Failed to getsockname %d\n", __func__, errno); + QCSI_LOG_ERR("Failed to getsockname %d\n", errno); return QCSI_INTERNAL_ERR; } if(sq.sq_family != AF_QIPCRTR || sl != sizeof(sq)) { - QCSI_LOG_ERR("%s Invalid socket family\n", __func__); + QCSI_LOG_ERR("Invalid socket family\n"); return QCSI_INTERNAL_ERR; } @@ -405,7 +404,7 @@ static qmi_csi_error_type xport_reg rc = sendto(xp->fd, &pkt, sizeof(pkt), 0, (void *)&sq, sizeof(sq)); if(rc < 0) { - QCSI_LOG_ERR("%s Failed for service_id=0x%x version=0x%x on %d error %d\n", __func__, + QCSI_LOG_ERR("Failed for service_id=0x%x version=0x%x on %d error %d\n", service_id, version, xp->fd, errno); return QCSI_INTERNAL_ERR; } @@ -413,7 +412,7 @@ static qmi_csi_error_type xport_reg xp->svc.service = service_id; xp->svc.instance = version; - QCSI_LOG_ERR("xport_reg[%d]: service_id=0x%x version=0x%x\n", xp->fd, service_id, version); + QCSI_LOG_DBG("xport_reg[%d]: service_id=0x%x version=0x%x\n", xp->fd, service_id, version); return QCSI_NO_ERR; } @@ -426,7 +425,7 @@ static qmi_csi_error_type xport_unreg { struct xport_handle *xp; xp = (struct xport_handle *)handle; - QCSI_LOG_ERR("xport_unreg[%d]: type=0x%x version=0x%x\n", xp->fd, service_id, version); + QCSI_LOG_DBG("xport_unreg[%d]: type=0x%x version=0x%x\n", xp->fd, service_id, version); return QCSI_NO_ERR; } @@ -467,15 +466,9 @@ static qmi_csi_error_type xport_send if( dest && LIST_CNT(dest->bufs)) { /* Queue the message so that it doesn't go out of order */ rc = put_tx_q(xp, s_addr, msg, msg_len, max_q_len); - if(rc == QCSI_CONN_BUSY) - QCSI_LOG_ERR("%s Queue exceeded, Retry sending for port %08x:%08x\n", + if(rc != QCSI_NO_ERR) + QCSI_LOG_ERR("%s Error queuing packet for port %08x:%08x\n", __func__, s_addr->node_id, s_addr->port_id); - else if(rc == QCSI_NO_ERR) - QCSI_LOG_ERR("%s Packet queued for port %08x:%08x\n", __func__, - s_addr->node_id, s_addr->port_id); - else - QCSI_LOG_ERR("%s Error queuing packet for port %08x:%08x\n", __func__, - s_addr->node_id, s_addr->port_id); pthread_mutex_unlock(&xp->tx_q_lock); return rc; } @@ -484,25 +477,19 @@ static qmi_csi_error_type xport_send if ((sendto_rc < 0) && (errno == EAGAIN)) { /* queue to tx queue */ rc = put_tx_q(xp, addr, msg, msg_len, max_q_len); - if(rc == QCSI_CONN_BUSY) - QCSI_LOG_ERR("%s Queue exceeded, Retry sending for port %08x:%08x\n", + if(rc != QCSI_NO_ERR) + QCSI_LOG_ERR("%s Error queuing packet for port %08x:%08x\n", __func__, s_addr->node_id, s_addr->port_id); - else if(rc == QCSI_NO_ERR) - QCSI_LOG_ERR("%s Packet queued for port %08x:%08x\n", __func__, - s_addr->node_id, s_addr->port_id); - else - QCSI_LOG_ERR("%s Error queuing packet for port %08x:%08x\n", __func__, - s_addr->node_id, s_addr->port_id); } else if (sendto_rc >= 0) { - QCSI_LOG_ERR("Sent[%d]: %d bytes to port %08x:%08x\n", xp->fd, msg_len, + QCSI_LOG_TRACE("Sent[%d]: %d bytes to port %08x:%08x\n", xp->fd, msg_len, s_addr->node_id, s_addr->port_id); pthread_mutex_unlock(&xp->tx_q_lock); return QCSI_NO_ERR; } else { /* Err on all other cases */ rc = QCSI_INTERNAL_ERR; - QCSI_LOG_ERR("%s QCSI Sendto failed for port %08x:%08x err[%d]\n", __func__, s_addr->node_id, s_addr->port_id, errno); + QCSI_LOG_ERR("QCSI Sendto failed for port %08x:%08x err[%d]\n", s_addr->node_id, s_addr->port_id, errno); } pthread_mutex_unlock(&xp->tx_q_lock); @@ -562,12 +549,12 @@ static void xport_handle_event memcpy(&rx_ctl_msg, buf, sizeof(rx_ctl_msg)); addr.node_id = rx_ctl_msg.client.node; addr.port_id = rx_ctl_msg.client.port; - QCSI_LOG_ERR("%s: CONTROL PKT cmd %d node %d port %d\n", __func__, rx_ctl_msg.cmd, + QCSI_LOG_DBG("%s: CONTROL PKT cmd %d node %d port %d\n", __func__, rx_ctl_msg.cmd, rx_ctl_msg.client.node, rx_ctl_msg.client.port); if (rx_ctl_msg.cmd == QRTR_TYPE_DEL_CLIENT) { struct conn_cli *client; - QCSI_LOG_ERR("Received REMOVE_CLIENT cmd for %08x:%08x\n", + QCSI_LOG_DBG("Received REMOVE_CLIENT cmd for %08x:%08x\n", rx_ctl_msg.client.node, rx_ctl_msg.client.port); /* Purge the Tx queue */ pthread_mutex_lock(&xp->tx_q_lock); @@ -605,7 +592,7 @@ static void xport_handle_event } else if ((src_addr_size == sizeof(struct sockaddr_qrtr)) && (rx_len == 0x0)) { - QCSI_LOG_ERR("%s: QCSI Received Resume_Tx from %08x:%08x on FD- %d\n", + QCSI_LOG_TRACE("%s: QCSI Received Resume_Tx from %08x:%08x on FD- %d\n", __func__, addr.node_id, addr.port_id, xp->fd); handle_resume_tx(xp, &addr); } @@ -616,7 +603,7 @@ static void xport_handle_event else break; } while(rx_len >= 0); - QCSI_LOG_ERR("xport_handle_event[%d]\n", xp->fd); + QCSI_LOG_TRACE("xport_handle_event[%d]\n", xp->fd); free(buf); } } @@ -632,7 +619,7 @@ static void xport_close purge_dest_s(xp); purge_conn_cli(xp); - QCSI_LOG_ERR("xport_close[%d]\n", xp->fd); + QCSI_LOG_DBG("xport_close[%d]\n", xp->fd); close(xp->fd); qcsi_xport_closed(xp->xport); free(xp); diff --git a/tests/qcsi_test.c b/tests/qcsi_test.c index 54d8ba9..26d1c1f 100644 --- a/tests/qcsi_test.c +++ b/tests/qcsi_test.c @@ -59,6 +59,9 @@ void qmi_test_service_start_service(uint32_t serv_inst) char buf[10]; void *sp; + memset(&os_params, 0, sizeof(os_params)); + memset(&os_params_in, 0, sizeof(os_params_in)); + printf("Starting QMI Test Ping Service with instance ID: %d\n", serv_inst); sp = qmi_test_service_register_service(&os_params, serv_inst); if(!sp) @@ -79,14 +82,14 @@ void qmi_test_service_start_service(uint32_t serv_inst) { if(read(STDIN_FILENO, buf, sizeof(buf)) <= 0) { - break; + break; } } os_params_in.fds = fds; qmi_csi_handle_event(sp, &os_params_in); } qmi_csi_unregister(sp); - printf("Server Terminated....\n"); + printf("Terminated QMI Test Ping Service\n"); } /*=============================================================================