diff options
39 files changed, 2969 insertions, 1243 deletions
@@ -1,3 +1,42 @@ +# Tests +/samsung-ipc/tests/libsamsung-ipc-test +/samsung-ipc/tests/libsamsung-ipc-test.log +/samsung-ipc/tests/libsamsung-ipc-test.trs +/samsung-ipc/tests/test-suite.log +/test-driver +/tools/ipc-modem.log +/tools/ipc-modem/tests/ipc-modem.log +/tools/ipc-modem/tests/ipc-modem.trs +/tools/ipc-modem/test-suite.log +/tools/ipc-modem.trs +/tools/nv_data-imei.log +/tools/nv_data-imei.trs +/tools/nv_data-md5.log +/tools/nv_data-md5.trs +/tools/tests/nv_data-imei.log +/tools/tests/nv_data-imei.trs +/tools/tests/nv_data-md5.log +/tools/tests/nv_data-md5.trs +/tools/test-suite.log +valgrind.*.log + +# scripts/PKGBUILD +/scripts/libsamsung-ipc-git-*.pkg.tar.xz +/scripts/libsamsung-ipc-git-debug-*.pkg.tar.xz +/scripts/pkg/** +/scripts/src/** + +# Tools +/tools/https-send-sms +/tools/ipc-modem/ipc-modem +/tools/ipc-test +/tools/nv_data-imei +/tools/nv_data-md5 + +# Text editors +\#*\# +*~ + Makefile.in Makefile *.o @@ -29,6 +68,3 @@ INSTALL *.pc build core -ipc-modem -ipc-test -nv_data-md5 @@ -58,6 +58,7 @@ libsamsung_ipc_local_src_files := \ samsung-ipc/gen.c \ samsung-ipc/gprs.c \ samsung-ipc/ipc.c \ + samsung-ipc/ipc_strings.c \ samsung-ipc/ipc_utils.c \ samsung-ipc/misc.c \ samsung-ipc/net.c \ @@ -112,9 +113,11 @@ libsamsung_ipc_local_c_includes := \ $(LOCAL_PATH)/samsung-ipc \ external/openssl/include -libsamsung_local_cflags := \ - -DIPC_DEVICE_NAME=\"$(ipc_device_name)\" \ - -DDEBUG +libsamsung_local_cflags := -DDEBUG + +ifneq ($(TARGET_DEVICE),) +libsamsung_local_cflags += -DIPC_DEVICE_NAME=\"$(ipc_device_name)\" +endif # ifneq ($(TARGET_DEVICE),) libsamsung_ipc_local_shared_libraries := \ libutils \ @@ -158,6 +161,22 @@ LOCAL_EXPORT_C_INCLUDE_DIRS := $(local_export_c_include_dirs) include $(BUILD_SHARED_LIBRARY) +####################### +# https-send-sms tool # +####################### +include $(CLEAR_VARS) +include $(LOCAL_PATH)/android_versions.mk + +LOCAL_MODULE := https-send-sms +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := tools/https-send-sms.c + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/tools/include/glibc +LOCAL_SHARED_LIBRARIES := libcurl + +include $(BUILD_EXECUTABLE) + ################## # ipc-modem tool # ################## @@ -167,13 +186,34 @@ include $(LOCAL_PATH)/android_versions.mk LOCAL_MODULE := ipc-modem LOCAL_MODULE_TAGS := optional -LOCAL_SRC_FILES := tools/ipc-modem.c +LOCAL_SRC_FILES := \ + tools/ipc-modem/ipc-modem.c \ + tools/ipc-modem/ipc-modem-log.c -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/tools/include/glibc LOCAL_SHARED_LIBRARIES := libsamsung-ipc include $(BUILD_EXECUTABLE) +######################### +# ipc-modem-static tool # +######################### +include $(CLEAR_VARS) +include $(LOCAL_PATH)/android_versions.mk + +LOCAL_MODULE := ipc-modem-static +LOCAL_MODULE_TAGS := optional + +LOCAL_SRC_FILES := \ + tools/ipc-modem/ipc-modem.c \ + tools/ipc-modem/ipc-modem-log.c + +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/tools/include/glibc +LOCAL_STATIC_LIBRARIES := libsamsung-ipc +LOCAL_SHARED_LIBRARIES := $(libsamsung_ipc_local_shared_libraries) + +include $(BUILD_EXECUTABLE) + ################# # ipc-test tool # ################# @@ -219,7 +259,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_SRC_FILES := tools/nv_data-md5.c -LOCAL_C_INCLUDES := $(LOCAL_PATH)/include +LOCAL_C_INCLUDES := $(LOCAL_PATH)/include $(LOCAL_PATH)/tools/include/glibc LOCAL_SHARED_LIBRARIES := libsamsung-ipc diff --git a/CONTRIBUTING b/CONTRIBUTING index f032039..8f9e7a1 100644 --- a/CONTRIBUTING +++ b/CONTRIBUTING @@ -7,7 +7,7 @@ https://git.replicant.us/replicant/hardware_replicant_libsamsung-ipc Policies -------- While at the time of writing, Replicant is the main user of libsamsung-ipc, and -maintain it, libsamsung-ipc usage is not limited to Replicant nor Android. +maintains it, libsamsung-ipc usage is not limited to Replicant nor Android. In the past, libsamsung-ipc was used in the SHR GNU/Linux distribution as well, with the freesmartphone.org middleware. diff --git a/Makefile.am b/Makefile.am index 45669d8..376f52e 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,18 +1,27 @@ NULL = +EXTRA_DIST = $(NULL) + SUBDIRS = \ samsung-ipc \ samsung-ipc/tests \ include \ tools \ + tools/ipc-modem \ $(NULL) pkgconfigdir = $(libdir)/pkgconfig pkgconfig_DATA = samsung-ipc.pc -EXTRA_DIST = \ +EXTRA_DIST += \ + Android.mk \ + android_versions.mk \ + CONTRIBUTING \ + INSTALL \ MAINTAINERS \ samsung-ipc.pc \ + strict-cflags.sh \ + tools/include/glibc/sysexits.h \ $(NULL) MAINTAINERCLEANFILES = \ @@ -21,3 +30,75 @@ MAINTAINERCLEANFILES = \ Makefile.in missing config.h.in \ mkinstalldirs *~ \ $(NULL) + +################################################################################ +# Extra checks # +################################################################################ + +if WANT_CODE_COVERAGE +check-local: build-code-coverage check-tarball-builds +install-data-local: install-code-coverage +clean-local: clean-code-coverage +else # WANT_CODE_COVERAGE +check-local: check-tarball-builds +endif # WANT_CODE_COVERAGE + +# With the next release of libsamsung-ipc, we will also release +# tarballs. +# +# Until now, no automatic testing was done with the libsamsung-ipc +# tarballs (all tests were done with the libsamsung-ipc git +# repository). +# +# We also need to verify that everything also builds and that the +# tests also work with tarballs. This can spot mistakes where people +# add new files that are not automatically picked up by automake and +# forget to add these files to EXTRA_DIST. +# +# This test runs only from git because it is not necessary with a +# tarball build. If we wanted to run it anyway we would end up in an +# infinite recursion as a given test from a tarball would then spawn +# another build and test from a tarball which would then spawn again +# another build and test. +check-tarball-builds: dist + if [ -d $(srcdir)/.git ] ; then \ + BUILD_TMPDIR=`mktemp -d` && \ + echo $$BUILD_TMPDIR && \ + mkdir $$BUILD_TMPDIR/build $$BUILD_TMPDIR/destdir && \ + tar xf $(srcdir)/libsamsung-ipc-$(VERSION).tar.xz \ + -C $$BUILD_TMPDIR && \ + cd $$BUILD_TMPDIR/build && \ + ../libsamsung-ipc-$(VERSION)/configure \ + $(CONFIGURE_ARGUMENTS) && \ + make check && \ + make install DESTDIR=`realpath $$BUILD_TMPDIR/destdir` && \ + rm -rf $$BUILD_TMPDIR ; \ + fi + +################# +# Code coverage # +################# +if WANT_CODE_COVERAGE + +CODE_COVERAGE_DIR = lcov + +EXTRA_DIST += $(CODE_COVERAGE_DIR) + +build-code-coverage: + lcov \ + --capture \ + --compat-libtool \ + --directory . \ + --output-file libsamsung-ipc.info + genhtml -o $(CODE_COVERAGE_DIR) libsamsung-ipc.info + +install-code-coverage: check + install -d $(DESTDIR)/$(datadir)/libsamsung-ipc/$(CODE_COVERAGE_DIR)/ + find $(srcdir)/$(CODE_COVERAGE_DIR) -type f | \ + xargs -I src install -D src \ + $(DESTDIR)/$(datadir)/libsamsung-ipc/$(CODE_COVERAGE_DIR)/ + +clean-code-coverage: + rm -rf $(CODE_COVERAGE_DIR) + +endif # WANT_CODE_COVERAGE @@ -7,10 +7,11 @@ found in many Samsung devices. Compilation and installation ============================ -In orderto compile the source code you need the following software packages +In order to compile the source code you need the following software packages - GCC compiler - GNC C library - OpenSSL >= 1.0.0e +- curl >= 7.62.0 To configure run ./configure --prefix=/usr diff --git a/configure.ac b/configure.ac index d59ef0f..501a386 100644 --- a/configure.ac +++ b/configure.ac @@ -1,21 +1,16 @@ -AC_INIT([libsamsung-ipc], [0.6.0], [replicant@osuosl.org], [libsamsung-ipc]) +AC_INIT([libsamsung-ipc], [0.7.0], [replicant@osuosl.org], [libsamsung-ipc]) + +AC_SUBST(CONFIGURE_ARGUMENTS) +: ${CONFIGURE_ARGUMENTS="$@"} + AC_CONFIG_SRCDIR([Makefile.am]) AC_CONFIG_HEADERS(config.h) AM_INIT_AUTOMAKE([dist-bzip2 dist-xz subdir-objects]) XZ_OPT=-v9e m4_ifdef([AM_SILENT_RULES], [AM_SILENT_RULES([yes])]) -AC_PROG_CC -AM_PROG_CC_C_O -AC_GNU_SOURCE -AC_DISABLE_STATIC -AC_PROG_LIBTOOL - -AC_SUBST(CFLAGS) -AC_SUBST(CPPFLAGS) -AC_SUBST(LDFLAGS) - OPENSSL_REQUIRED=1.0.0e +LIBCURL_REQUIRED=7.62.0 #------------------------------------------------------------------------------ # pkg-config @@ -30,15 +25,113 @@ AC_SUBST(OPENSSL_CFLAGS) AC_SUBST(OPENSSL_LIBS) #------------------------------------------------------------------------------ +# strict cflags +AC_SUBST(STRICT_CFLAGS) + +#------------------------------------------------------------------------------ +# Static build of test utilities +AC_SUBST(ALL_STATIC_LDFLAGS) + +#------------------------------------------------------------------------------ +# python +AC_SUBST(PYTHON3) +AC_CHECK_PROG([PYTHON3], [python3], [python3]) +#------------------------------------------------------------------------------ +# code coverage +AC_SUBST(CODE_COVERAGE) +#------------------------------------------------------------------------------ +# valgrind +AC_SUBST(VALGRIND) + +#------------------------------------------------------------------------------ +# ipc device name +AC_SUBST([IPC_DEVICE_NAME], [all]) + +#------------------------------------------------------------------------------ +# libcurl +PKG_CHECK_MODULES(LIBCURL, libcurl >= $LIBCURL_REQUIRED) +AC_SUBST(LIBCURL_CFLAGS) +AC_SUBST(LIBCURL_LIBS) + +#------------------------------------------------------------------------------ # check for debugging AC_ARG_ENABLE(debug, - [ --enable-debug Enable debug build (default=disabled)], + [AS_HELP_STRING([--enable-debug], [Enable debug build (default=disabled)])], [debug=$enableval], [debug="no"]) AM_CONDITIONAL( [WANT_DEBUG], [test x"$debug" = x"yes"]) #------------------------------------------------------------------------------ +AC_ARG_ENABLE(static-progs, + [AS_HELP_STRING([--enable-static-progs], + [Build static (test) tools (default=disabled)])], + [static_progs=$enableval], + [static_progs="no"]) + +#------------------------------------------------------------------------------ +AC_ARG_ENABLE(strict-cflags, + [AS_HELP_STRING([--enable-strict-cflags], + [Build with strict cflags (default=disabled)])], + [strict_cflags=$enableval], + [strict_cflags="no"]) +AM_CONDITIONAL( [WANT_STRICT_CFLAGS], [test x"$strict_cflags" = x"yes"]) + +#------------------------------------------------------------------------------ +# TODO: GCC has --enable-checking= for extensive runtime checks and one of the +# available values is valgrind, so it would be a good idea to convert to +# it for consistency across free software projects. +AC_ARG_ENABLE( + [code-coverage-tests], + [AS_HELP_STRING([--enable-code-coverage-tests], + [Build with --coverage, -O0 and use lcov from PATH during + tests (default=disabled)])], + [code_coverage_tests=$enableval], + [code_coverage="no"]) + +AM_CONDITIONAL( [WANT_CODE_COVERAGE], [test x"$code_coverage_tests" = x"yes"]) + +AS_IF([test x"$code_coverage_tests" = x"yes"], + [AC_CHECK_PROG([CODE_COVERAGE], [lcov], [lcov]) + AS_IF( + [test x"$CODE_COVERAGE" = x""], + [AC_MSG_ERROR( + [code coverage tests are enabled but lcov was not found in PATH ($PATH)])])]) + +#------------------------------------------------------------------------------ +# TODO: GCC has --enable-checking= for extensive runtime checks and one of the +# available values is valgrind, so it would be a good idea to convert to +# it for consistency across free software projects. +AC_ARG_ENABLE( + [valgrind-tests], + [AS_HELP_STRING([--enable-valgrind-tests], + [Build with -ggdb3, -O0 and use valgrind from PATH during + tests (default=disabled)])], + [valgrind_tests=$enableval], + [valgrind_tests="no"]) + +AM_CONDITIONAL( [WANT_VALGRIND_CHECKING], [test x"$valgrind_tests" = x"yes"]) + +AS_IF([test x"$valgrind_tests" = x"yes"], + [AC_CHECK_PROG([VALGRIND], [valgrind], [valgrind]) + AS_IF( + [test x"$VALGRIND" = x""], + [AC_MSG_ERROR( + [valgrind tests are enabled but valgrind was not found in PATH ($PATH)])])]) +#------------------------------------------------------------------------------ +AC_ARG_ENABLE(samsung-ipc-device, + [ --enable-samsung-ipc-device=[DEVICE] + make libsamsung-ipc assumes that it runs on DEVICE + DEVICE={all,aries,crespo,galaxys2,herolte,i9300,maguro,n5100,n7100,piranha} (default=all)], + [AS_CASE([$enableval], + [aries|crespo|galaxys2|herolte|i9300|maguro|n5100|n7100|piranha], + [IPC_DEVICE_NAME=$enableval], + [AC_MSG_ERROR([Unknown device $enableval])])], + [IPC_DEVICE_NAME="all"]) + +AM_CONDITIONAL( [WANT_IPC_DEVICE_NAME], [test x"$IPC_DEVICE_NAME" != x"all"]) +#------------------------------------------------------------------------------ + AC_CONFIG_FILES([ Makefile samsung-ipc.pc @@ -46,23 +139,67 @@ AC_CONFIG_FILES([ samsung-ipc/Makefile samsung-ipc/tests/Makefile tools/Makefile + tools/ipc-modem/Makefile ]) -AC_OUTPUT + #------------------------------------------------------------------------------ +AS_IF([test x"$static_progs" = x"yes"], + [ALL_STATIC_LDFLAGS=-all-static], []) + +AS_IF([test x"$strict_cflags" = x"yes"], + [STRICT_CFLAGS=`$srcdir/strict-cflags.sh`], []) + +AS_IF([test x"$valgrind_tests" = x"yes"], [: ${CFLAGS="-ggdb3 -O0"}], + [test x"$debug" = x"yes"], [: ${CFLAGS="-ggdb -O0"}], []) + +AS_IF([test x"$code_coverage_tests" = x"yes"], + [: ${LDFLAGS=" --coverage"}], []) + +AS_IF([test x"$code_coverage_tests" = x"yes"], + [ CFLAGS+=" --coverage"], []) + +AC_PROG_CC +AM_PROG_CC_C_O +AC_GNU_SOURCE +AC_DISABLE_STATIC +AC_PROG_LIBTOOL + +AC_SUBST(CFLAGS) +AC_SUBST(CPPFLAGS) +AC_SUBST(LDFLAGS) +AC_SUBST(ALL_STATIC_LDFLAGS) + +AC_OUTPUT +#------------------------------------------------------------------------------ # info echo "------------------------------------------------------------------------" echo "$PACKAGE_NAME $PACKAGE_VERSION" echo "------------------------------------------------------------------------" echo +echo "Compiler flags:" +echo +echo " CFLAGS..................: $CFLAGS $STRICT_CFLAGS" +echo " LDFLAGS.................: $LDFLAGS $ALL_STATIC_LDFLAGS" +echo +echo +echo "Interpreters paths:" +echo +echo " PYTHON3..................: $PYTHON3" +echo +echo echo "Configuration Options:" echo echo " debug build.............: $debug" echo +echo " device(s)...............: $IPC_DEVICE_NAME" +echo echo " prefix..................: $prefix" echo +echo " valgrind tests..........: $valgrind_tests" +echo +echo " code coverage tests.....: $code_coverage_tests" echo "------------------------------------------------------------------------" echo echo "Now type 'make' to compile and 'make install' to install this package." - diff --git a/include/samsung-ipc.h b/include/samsung-ipc.h index 53f1f72..d9aa7c7 100644 --- a/include/samsung-ipc.h +++ b/include/samsung-ipc.h @@ -138,6 +138,7 @@ const char *ipc_request_type_string(unsigned char type); const char *ipc_response_type_string(unsigned char type); const char *ipc_command_string(unsigned short command); const char *ipc_group_string(unsigned char group); +const char *ipc_client_type_string(unsigned char client_type); int ipc_data_dump(struct ipc_client *client, const void *data, size_t size); void ipc_client_log_send(struct ipc_client *client, struct ipc_message *message, diff --git a/samsung-ipc/Makefile.am b/samsung-ipc/Makefile.am index ed6331f..47484e5 100644 --- a/samsung-ipc/Makefile.am +++ b/samsung-ipc/Makefile.am @@ -6,8 +6,16 @@ AM_CFLAGS = \ $(OPENSSL_CFLAGS) \ $(NULL) +if WANT_STRICT_CFLAGS +AM_CFLAGS += $(STRICT_CFLAGS) +endif + if WANT_DEBUG -AM_CFLAGS += -ggdb -O0 -DDEBUG +AM_CFLAGS += -DDEBUG +endif + +if WANT_IPC_DEVICE_NAME +AM_CFLAGS += -DIPC_DEVICE_NAME=\"$(IPC_DEVICE_NAME)\" endif lib_LTLIBRARIES = \ @@ -17,6 +25,7 @@ lib_LTLIBRARIES = \ libsamsung_ipc_la_SOURCES = \ ipc.c \ ipc.h \ + ipc_strings.c \ ipc_utils.c \ utils.c \ call.c \ diff --git a/samsung-ipc/devices/aries/aries.c b/samsung-ipc/devices/aries/aries.c index 93d5d31..9fc905a 100644 --- a/samsung-ipc/devices/aries/aries.c +++ b/samsung-ipc/devices/aries/aries.c @@ -819,11 +819,16 @@ char *aries_gprs_get_iface(__attribute__((unused)) struct ipc_client *client, unsigned int cid) { char *iface = NULL; + int rc; if (cid > ARIES_GPRS_IFACE_COUNT) return NULL; - asprintf(&iface, "%s%d", ARIES_GPRS_IFACE_PREFIX, cid - 1); + rc = asprintf(&iface, "%s%d", ARIES_GPRS_IFACE_PREFIX, cid - 1); + if (rc == -1) { + ipc_client_log(client, "%s: asprintf failed", __func__); + return NULL; + } return iface; } diff --git a/samsung-ipc/devices/crespo/crespo.c b/samsung-ipc/devices/crespo/crespo.c index ebb6075..5399e77 100644 --- a/samsung-ipc/devices/crespo/crespo.c +++ b/samsung-ipc/devices/crespo/crespo.c @@ -553,13 +553,17 @@ int crespo_gprs_deactivate(__attribute__((unused)) struct ipc_client *client, return 0; } -char *crespo_gprs_get_iface_single( - __attribute__((unused)) struct ipc_client *client, - __attribute__((unused)) unsigned int cid) +char *crespo_gprs_get_iface_single(struct ipc_client *client, + __attribute__((unused)) unsigned int cid) { char *iface = NULL; + int rc; - asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, 0); + rc = asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, 0); + if (rc == -1) { + ipc_client_log(client, "%s: asprintf failed", __func__); + return NULL; + } return iface; } @@ -580,11 +584,16 @@ char *crespo_gprs_get_iface(__attribute__((unused)) struct ipc_client *client, unsigned int cid) { char *iface = NULL; + int rc; if (cid > CRESPO_GPRS_IFACE_COUNT) return NULL; - asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, cid - 1); + rc = asprintf(&iface, "%s%d", CRESPO_GPRS_IFACE_PREFIX, cid - 1); + if (rc == -1) { + ipc_client_log(client, "%s: asprintf failed", __func__); + return NULL; + } return iface; } diff --git a/samsung-ipc/gprs.c b/samsung-ipc/gprs.c index 89f06e7..c9722e5 100644 --- a/samsung-ipc/gprs.c +++ b/samsung-ipc/gprs.c @@ -35,7 +35,7 @@ int ipc_gprs_define_pdp_context_setup( data->cid = cid; data->magic = 0x02; - strncpy((char *) data->apn, apn, sizeof(data->apn)); + memcpy(data->apn, apn, sizeof(data->apn)); return 0; } @@ -56,9 +56,9 @@ int ipc_gprs_pdp_context_request_set_setup( data->magic1[2] = 0x13; data->magic2 = 0x01; - strncpy((char *) data->username, username, + memcpy(data->username, username, sizeof(data->username)); - strncpy((char *) data->password, password, + memcpy(data->password, password, sizeof(data->password)); } diff --git a/samsung-ipc/ipc_strings.c b/samsung-ipc/ipc_strings.c new file mode 100644 index 0000000..e7e6e8b --- /dev/null +++ b/samsung-ipc/ipc_strings.c @@ -0,0 +1,409 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2010-2011 Joerie de Gram <j.de.gram@gmail.com> + * Copyright (C) 2013-2014 Paul Kocialkowski <contact@paulk.fr> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +#include <samsung-ipc.h> + +const char *ipc_request_type_string(unsigned char type) +{ + static char type_string[5] = { 0 }; + + switch (type) { + case IPC_TYPE_EXEC: + return "IPC_TYPE_EXEC"; + case IPC_TYPE_GET: + return "IPC_TYPE_GET"; + case IPC_TYPE_SET: + return "IPC_TYPE_SET"; + case IPC_TYPE_CFRM: + return "IPC_TYPE_CFRM"; + case IPC_TYPE_EVENT: + return "IPC_TYPE_EVENT"; + default: + snprintf((char *) &type_string, sizeof(type_string), "0x%02x", + type); + return type_string; + } +} + +const char *ipc_response_type_string(unsigned char type) +{ + static char type_string[5] = { 0 }; + + switch (type) { + case IPC_TYPE_INDI: + return "IPC_TYPE_INDI"; + case IPC_TYPE_RESP: + return "IPC_TYPE_RESP"; + case IPC_TYPE_NOTI: + return "IPC_TYPE_NOTI"; + default: + snprintf((char *) &type_string, sizeof(type_string), "0x%02x", + type); + return type_string; + } +} + +const char *ipc_command_string(unsigned short command) +{ + static char command_string[7] = { 0 }; + + switch (command) { + case IPC_PWR_PHONE_PWR_UP: + return "IPC_PWR_PHONE_PWR_UP"; + case IPC_PWR_PHONE_PWR_OFF: + return "IPC_PWR_PHONE_PWR_OFF"; + case IPC_PWR_PHONE_RESET: + return "IPC_PWR_PHONE_RESET"; + case IPC_PWR_BATT_STATUS: + return "IPC_PWR_BATT_STATUS"; + case IPC_PWR_BATT_TYPE: + return "IPC_PWR_BATT_TYPE"; + case IPC_PWR_BATT_COMP: + return "IPC_PWR_BATT_COMP"; + case IPC_PWR_PHONE_STATE: + return "IPC_PWR_PHONE_STATE"; + case IPC_CALL_OUTGOING: + return "IPC_CALL_OUTGOING"; + case IPC_CALL_INCOMING: + return "IPC_CALL_INCOMING"; + case IPC_CALL_RELEASE: + return "IPC_CALL_RELEASE"; + case IPC_CALL_ANSWER: + return "IPC_CALL_ANSWER"; + case IPC_CALL_STATUS: + return "IPC_CALL_STATUS"; + case IPC_CALL_LIST: + return "IPC_CALL_LIST"; + case IPC_CALL_BURST_DTMF: + return "IPC_CALL_BURST_DTMF"; + case IPC_CALL_CONT_DTMF: + return "IPC_CALL_CONT_DTMF"; + case IPC_CALL_WAITING: + return "IPC_CALL_WAITING"; + case IPC_CALL_LINE_ID: + return "IPC_CALL_LINE_ID"; + case IPC_SMS_SEND_MSG: + return "IPC_SMS_SEND_MSG"; + case IPC_SMS_INCOMING_MSG: + return "IPC_SMS_INCOMING_MSG"; + case IPC_SMS_READ_MSG: + return "IPC_SMS_READ_MSG"; + case IPC_SMS_SAVE_MSG: + return "IPC_SMS_SAVE_MSG"; + case IPC_SMS_DEL_MSG: + return "IPC_SMS_DEL_MSG"; + case IPC_SMS_DELIVER_REPORT: + return "IPC_SMS_DELIVER_REPORT"; + case IPC_SMS_DEVICE_READY: + return "IPC_SMS_DEVICE_READY"; + case IPC_SMS_SEL_MEM: + return "IPC_SMS_SEL_MEM"; + case IPC_SMS_STORED_MSG_COUNT: + return "IPC_SMS_STORED_MSG_COUNT"; + case IPC_SMS_SVC_CENTER_ADDR: + return "IPC_SMS_SVC_CENTER_ADDR"; + case IPC_SMS_SVC_OPTION: + return "IPC_SMS_SVC_OPTION"; + case IPC_SMS_MEM_STATUS: + return "IPC_SMS_MEM_STATUS"; + case IPC_SMS_CBS_MSG: + return "IPC_SMS_CBS_MSG"; + case IPC_SMS_CBS_CFG: + return "IPC_SMS_CBS_CFG"; + case IPC_SMS_STORED_MSG_STATUS: + return "IPC_SMS_STORED_MSG_STATUS"; + case IPC_SMS_PARAM_COUNT: + return "IPC_SMS_PARAM_COUNT"; + case IPC_SMS_PARAM: + return "IPC_SMS_PARAM"; + case IPC_SEC_PIN_STATUS: + return "IPC_SEC_PIN_STATUS"; + case IPC_SEC_PHONE_LOCK: + return "IPC_SEC_PHONE_LOCK"; + case IPC_SEC_CHANGE_LOCKING_PW: + return "IPC_SEC_CHANGE_LOCKING_PW"; + case IPC_SEC_SIM_LANG: + return "IPC_SEC_SIM_LANG"; + case IPC_SEC_RSIM_ACCESS: + return "IPC_SEC_RSIM_ACCESS"; + case IPC_SEC_GSIM_ACCESS: + return "IPC_SEC_GSIM_ACCESS"; + case IPC_SEC_SIM_ICC_TYPE: + return "IPC_SEC_SIM_ICC_TYPE"; + case IPC_SEC_LOCK_INFORMATION: + return "IPC_SEC_LOCK_INFORMATION"; + case IPC_SEC_IMS_AUTH: + return "IPC_SEC_IMS_AUTH"; + case IPC_PB_ACCESS: + return "IPC_PB_ACCESS"; + case IPC_PB_STORAGE: + return "IPC_PB_STORAGE"; + case IPC_PB_STORAGE_LIST: + return "IPC_PB_STORAGE_LIST"; + case IPC_PB_ENTRY_INFO: + return "IPC_PB_ENTRY_INFO"; + case IPC_PB_3GPB_CAPA: + return "IPC_PB_3GPB_CAPA"; + case IPC_DISP_ICON_INFO: + return "IPC_DISP_ICON_INFO"; + case IPC_DISP_HOMEZONE_INFO: + return "IPC_DISP_HOMEZONE_INFO"; + case IPC_DISP_RSSI_INFO: + return "IPC_DISP_RSSI_INFO"; + case IPC_NET_PREF_PLMN: + return "IPC_NET_PREF_PLMN"; + case IPC_NET_PLMN_SEL: + return "IPC_NET_PLMN_SEL"; + case IPC_NET_SERVING_NETWORK: + return "IPC_NET_SERVING_NETWORK"; + case IPC_NET_PLMN_LIST: + return "IPC_NET_PLMN_LIST"; + case IPC_NET_REGIST: + return "IPC_NET_REGIST"; + case IPC_NET_SUBSCRIBER_NUM: + return "IPC_NET_SUBSCRIBER_NUM"; + case IPC_NET_BAND_SEL: + return "IPC_NET_BAND_SEL"; + case IPC_NET_SERVICE_DOMAIN_CONFIG: + return "IPC_NET_SERVICE_DOMAIN_CONFIG"; + case IPC_NET_POWERON_ATTACH: + return "IPC_NET_POWERON_ATTACH"; + case IPC_NET_MODE_SEL: + return "IPC_NET_MODE_SEL"; + case IPC_NET_ACQ_ORDER: + return "IPC_NET_ACQ_ORDER"; + case IPC_NET_IDENTITY: + return "IPC_NET_IDENTITY"; + case IPC_NET_PREFERRED_NETWORK_INFO: + return "IPC_NET_PREFERRED_NETWORK_INFO"; + case IPC_SND_SPKR_VOLUME_CTRL: + return "IPC_SND_SPKR_VOLUME_CTRL"; + case IPC_SND_MIC_MUTE_CTRL: + return "IPC_SND_MIC_MUTE_CTRL"; + case IPC_SND_AUDIO_PATH_CTRL: + return "IPC_SND_AUDIO_PATH_CTRL"; + case IPC_SND_AUDIO_SOURCE_CTRL: + return "IPC_SND_AUDIO_SOURCE_CTRL"; + case IPC_SND_LOOPBACK_CTRL: + return "IPC_SND_LOOPBACK_CTRL"; + case IPC_SND_VOICE_RECORDING_CTRL: + return "IPC_SND_VOICE_RECORDING_CTRL"; + case IPC_SND_VIDEO_CALL_CTRL: + return "IPC_SND_VIDEO_CALL_CTRL"; + case IPC_SND_RINGBACK_TONE_CTRL: + return "IPC_SND_RINGBACK_TONE_CTRL"; + case IPC_SND_CLOCK_CTRL: + return "IPC_SND_CLOCK_CTRL"; + case IPC_SND_WB_AMR_STATUS: + return "IPC_SND_WB_AMR_STATUS"; + case IPC_MISC_ME_VERSION: + return "IPC_MISC_ME_VERSION"; + case IPC_MISC_ME_IMSI: + return "IPC_MISC_ME_IMSI"; + case IPC_MISC_ME_SN: + return "IPC_MISC_ME_SN"; + case IPC_MISC_TIME_INFO: + return "IPC_MISC_TIME_INFO"; + case IPC_MISC_DEBUG_LEVEL: + return "IPC_MISC_DEBUG_LEVEL"; + case IPC_SVC_ENTER: + return "IPC_SVC_ENTER"; + case IPC_SVC_END: + return "IPC_SVC_END"; + case IPC_SVC_PRO_KEYCODE: + return "IPC_SVC_PRO_KEYCODE"; + case IPC_SVC_SCREEN_CFG: + return "IPC_SVC_SCREEN_CFG"; + case IPC_SVC_DISPLAY_SCREEN: + return "IPC_SVC_DISPLAY_SCREEN"; + case IPC_SVC_CHANGE_SVC_MODE: + return "IPC_SVC_CHANGE_SVC_MODE"; + case IPC_SVC_DEVICE_TEST: + return "IPC_SVC_DEVICE_TEST"; + case IPC_SVC_DEBUG_DUMP: + return "IPC_SVC_DEBUG_DUMP"; + case IPC_SVC_DEBUG_STRING: + return "IPC_SVC_DEBUG_STRING"; + case IPC_SS_WAITING: + return "IPC_SS_WAITING"; + case IPC_SS_CLI: + return "IPC_SS_CLI"; + case IPC_SS_BARRING: + return "IPC_SS_BARRING"; + case IPC_SS_BARRING_PW: + return "IPC_SS_BARRING_PW"; + case IPC_SS_FORWARDING: + return "IPC_SS_FORWARDING"; + case IPC_SS_INFO: + return "IPC_SS_INFO"; + case IPC_SS_MANAGE_CALL: + return "IPC_SS_MANAGE_CALL"; + case IPC_SS_USSD: + return "IPC_SS_USSD"; + case IPC_SS_AOC: + return "IPC_SS_AOC"; + case IPC_SS_RELEASE_COMPLETE: + return "IPC_SS_RELEASE_COMPLETE"; + case IPC_GPRS_DEFINE_PDP_CONTEXT: + return "IPC_GPRS_DEFINE_PDP_CONTEXT"; + case IPC_GPRS_QOS: + return "IPC_GPRS_QOS"; + case IPC_GPRS_PS: + return "IPC_GPRS_PS"; + case IPC_GPRS_PDP_CONTEXT: + return "IPC_GPRS_PDP_CONTEXT"; + case IPC_GPRS_ENTER_DATA: + return "IPC_GPRS_ENTER_DATA"; + case IPC_GPRS_SHOW_PDP_ADDR: + return "IPC_GPRS_SHOW_PDP_ADDR"; + case IPC_GPRS_MS_CLASS: + return "IPC_GPRS_MS_CLASS"; + case IPC_GPRS_3G_QUAL_SRVC_PROFILE: + return "IPC_GPRS_3G_QUAL_SRVC_PROFILE"; + case IPC_GPRS_IP_CONFIGURATION: + return "IPC_GPRS_IP_CONFIGURATION"; + case IPC_GPRS_DEFINE_SEC_PDP_CONTEXT: + return "IPC_GPRS_DEFINE_SEC_PDP_CONTEXT"; + case IPC_GPRS_TFT: + return "IPC_GPRS_TFT"; + case IPC_GPRS_HSDPA_STATUS: + return "IPC_GPRS_HSDPA_STATUS"; + case IPC_GPRS_CURRENT_SESSION_DATA_COUNTER: + return "IPC_GPRS_CURRENT_SESSION_DATA_COUNTER"; + case IPC_GPRS_DATA_DORMANT: + return "IPC_GPRS_DATA_DORMANT"; + case IPC_GPRS_PIN_CTRL: + return "IPC_GPRS_PIN_CTRL"; + case IPC_GPRS_CALL_STATUS: + return "IPC_GPRS_CALL_STATUS"; + case IPC_GPRS_PORT_LIST: + return "IPC_GPRS_PORT_LIST"; + case IPC_SAT_PROFILE_DOWNLOAD: + return "IPC_SAT_PROFILE_DOWNLOAD"; + case IPC_SAT_ENVELOPE_CMD: + return "IPC_SAT_ENVELOPE_CMD"; + case IPC_SAT_PROACTIVE_CMD: + return "IPC_SAT_PROACTIVE_CMD"; + case IPC_SAT_TERMINATE_USAT_SESSION: + return "IPC_SAT_TERMINATE_USAT_SESSION"; + case IPC_SAT_EVENT_DOWNLOAD: + return "IPC_SAT_EVENT_DOWNLOAD"; + case IPC_SAT_PROVIDE_LOCAL_INFO: + return "IPC_SAT_PROVIDE_LOCAL_INFO"; + case IPC_SAT_POLLING: + return "IPC_SAT_POLLING"; + case IPC_SAT_REFRESH: + return "IPC_SAT_REFRESH"; + case IPC_SAT_SETUP_EVENT_LIST: + return "IPC_SAT_SETUP_EVENT_LIST"; + case IPC_SAT_CALL_CONTROL_RESULT: + return "IPC_SAT_CALL_CONTROL_RESULT"; + case IPC_SAT_IMAGE_CLUT: + return "IPC_SAT_IMAGE_CLUT"; + case IPC_SAT_SETUP_CALL_PROCESSING: + return "IPC_SAT_SETUP_CALL_PROCESSING"; + case IPC_IMEI_START: + return "IPC_IMEI_START"; + case IPC_IMEI_CHECK_DEVICE_INFO: + return "IPC_IMEI_CHECK_DEVICE_INFO"; + case IPC_RFS_NV_READ_ITEM: + return "IPC_RFS_NV_READ_ITEM"; + case IPC_RFS_NV_WRITE_ITEM: + return "IPC_RFS_NV_WRITE_ITEM"; + case IPC_GEN_PHONE_RES: + return "IPC_GEN_PHONE_RES"; + default: + snprintf((char *) &command_string, sizeof(command_string), + "0x%04x", command); + return command_string; + } +} + +const char *ipc_group_string(unsigned char group) +{ + static char group_string[5] = { 0 }; + + switch (group) { + case IPC_GROUP_PWR: + return "IPC_GROUP_PWR"; + case IPC_GROUP_CALL: + return "IPC_GROUP_CALL"; + case IPC_GROUP_SMS: + return "IPC_GROUP_SMS"; + case IPC_GROUP_SEC: + return "IPC_GROUP_SEC"; + case IPC_GROUP_PB: + return "IPC_GROUP_PB"; + case IPC_GROUP_DISP: + return "IPC_GROUP_DISP"; + case IPC_GROUP_NET: + return "IPC_GROUP_NET"; + case IPC_GROUP_SND: + return "IPC_GROUP_SND"; + case IPC_GROUP_MISC: + return "IPC_GROUP_MISC"; + case IPC_GROUP_SVC: + return "IPC_GROUP_SVC"; + case IPC_GROUP_SS: + return "IPC_GROUP_SS"; + case IPC_GROUP_GPRS: + return "IPC_GROUP_GPRS"; + case IPC_GROUP_SAT: + return "IPC_GROUP_SAT"; + case IPC_GROUP_CFG: + return "IPC_GROUP_CFG"; + case IPC_GROUP_IMEI: + return "IPC_GROUP_IMEI"; + case IPC_GROUP_GPS: + return "IPC_GROUP_GPS"; + case IPC_GROUP_SAP: + return "IPC_GROUP_SAP"; + case IPC_GROUP_RFS: + return "IPC_GROUP_RFS"; + case IPC_GROUP_GEN: + return "IPC_GROUP_GEN"; + default: + snprintf((char *) &group_string, sizeof(group_string), "0x%02x", + (unsigned int)group); + return group_string; + } +} + +const char *ipc_client_type_string(unsigned char client_type) +{ + static char client_type_string[5] = { 0 }; + + switch (client_type) { + case IPC_CLIENT_TYPE_FMT: + return "FMT"; + case IPC_CLIENT_TYPE_RFS: + return "RFS"; + case IPC_CLIENT_TYPE_DUMMY: + return "DUMMY"; + default: + snprintf((char *) &client_type_string, + sizeof(client_type_string), + "0x%02x", + client_type); + return client_type_string; + } +} diff --git a/samsung-ipc/ipc_utils.c b/samsung-ipc/ipc_utils.c index 9c4ccb8..3518475 100644 --- a/samsung-ipc/ipc_utils.c +++ b/samsung-ipc/ipc_utils.c @@ -41,372 +41,6 @@ int ipc_seq_valid(unsigned char seq) return 1; } -const char *ipc_request_type_string(unsigned char type) -{ - static char type_string[5] = { 0 }; - - switch (type) { - case IPC_TYPE_EXEC: - return "IPC_TYPE_EXEC"; - case IPC_TYPE_GET: - return "IPC_TYPE_GET"; - case IPC_TYPE_SET: - return "IPC_TYPE_SET"; - case IPC_TYPE_CFRM: - return "IPC_TYPE_CFRM"; - case IPC_TYPE_EVENT: - return "IPC_TYPE_EVENT"; - default: - snprintf((char *) &type_string, sizeof(type_string), "0x%02x", - type); - return type_string; - } -} - -const char *ipc_response_type_string(unsigned char type) -{ - static char type_string[5] = { 0 }; - - switch (type) { - case IPC_TYPE_INDI: - return "IPC_TYPE_INDI"; - case IPC_TYPE_RESP: - return "IPC_TYPE_RESP"; - case IPC_TYPE_NOTI: - return "IPC_TYPE_NOTI"; - default: - snprintf((char *) &type_string, sizeof(type_string), "0x%02x", - type); - return type_string; - } -} - -const char *ipc_command_string(unsigned short command) -{ - static char command_string[7] = { 0 }; - - switch (command) { - case IPC_PWR_PHONE_PWR_UP: - return "IPC_PWR_PHONE_PWR_UP"; - case IPC_PWR_PHONE_PWR_OFF: - return "IPC_PWR_PHONE_PWR_OFF"; - case IPC_PWR_PHONE_RESET: - return "IPC_PWR_PHONE_RESET"; - case IPC_PWR_BATT_STATUS: - return "IPC_PWR_BATT_STATUS"; - case IPC_PWR_BATT_TYPE: - return "IPC_PWR_BATT_TYPE"; - case IPC_PWR_BATT_COMP: - return "IPC_PWR_BATT_COMP"; - case IPC_PWR_PHONE_STATE: - return "IPC_PWR_PHONE_STATE"; - case IPC_CALL_OUTGOING: - return "IPC_CALL_OUTGOING"; - case IPC_CALL_INCOMING: - return "IPC_CALL_INCOMING"; - case IPC_CALL_RELEASE: - return "IPC_CALL_RELEASE"; - case IPC_CALL_ANSWER: - return "IPC_CALL_ANSWER"; - case IPC_CALL_STATUS: - return "IPC_CALL_STATUS"; - case IPC_CALL_LIST: - return "IPC_CALL_LIST"; - case IPC_CALL_BURST_DTMF: - return "IPC_CALL_BURST_DTMF"; - case IPC_CALL_CONT_DTMF: - return "IPC_CALL_CONT_DTMF"; - case IPC_CALL_WAITING: - return "IPC_CALL_WAITING"; - case IPC_CALL_LINE_ID: - return "IPC_CALL_LINE_ID"; - case IPC_SMS_SEND_MSG: - return "IPC_SMS_SEND_MSG"; - case IPC_SMS_INCOMING_MSG: - return "IPC_SMS_INCOMING_MSG"; - case IPC_SMS_READ_MSG: - return "IPC_SMS_READ_MSG"; - case IPC_SMS_SAVE_MSG: - return "IPC_SMS_SAVE_MSG"; - case IPC_SMS_DEL_MSG: - return "IPC_SMS_DEL_MSG"; - case IPC_SMS_DELIVER_REPORT: - return "IPC_SMS_DELIVER_REPORT"; - case IPC_SMS_DEVICE_READY: - return "IPC_SMS_DEVICE_READY"; - case IPC_SMS_SEL_MEM: - return "IPC_SMS_SEL_MEM"; - case IPC_SMS_STORED_MSG_COUNT: - return "IPC_SMS_STORED_MSG_COUNT"; - case IPC_SMS_SVC_CENTER_ADDR: - return "IPC_SMS_SVC_CENTER_ADDR"; - case IPC_SMS_SVC_OPTION: - return "IPC_SMS_SVC_OPTION"; - case IPC_SMS_MEM_STATUS: - return "IPC_SMS_MEM_STATUS"; - case IPC_SMS_CBS_MSG: - return "IPC_SMS_CBS_MSG"; - case IPC_SMS_CBS_CFG: - return "IPC_SMS_CBS_CFG"; - case IPC_SMS_STORED_MSG_STATUS: - return "IPC_SMS_STORED_MSG_STATUS"; - case IPC_SMS_PARAM_COUNT: - return "IPC_SMS_PARAM_COUNT"; - case IPC_SMS_PARAM: - return "IPC_SMS_PARAM"; - case IPC_SEC_PIN_STATUS: - return "IPC_SEC_PIN_STATUS"; - case IPC_SEC_PHONE_LOCK: - return "IPC_SEC_PHONE_LOCK"; - case IPC_SEC_CHANGE_LOCKING_PW: - return "IPC_SEC_CHANGE_LOCKING_PW"; - case IPC_SEC_SIM_LANG: - return "IPC_SEC_SIM_LANG"; - case IPC_SEC_RSIM_ACCESS: - return "IPC_SEC_RSIM_ACCESS"; - case IPC_SEC_GSIM_ACCESS: - return "IPC_SEC_GSIM_ACCESS"; - case IPC_SEC_SIM_ICC_TYPE: - return "IPC_SEC_SIM_ICC_TYPE"; - case IPC_SEC_LOCK_INFORMATION: - return "IPC_SEC_LOCK_INFORMATION"; - case IPC_SEC_IMS_AUTH: - return "IPC_SEC_IMS_AUTH"; - case IPC_PB_ACCESS: - return "IPC_PB_ACCESS"; - case IPC_PB_STORAGE: - return "IPC_PB_STORAGE"; - case IPC_PB_STORAGE_LIST: - return "IPC_PB_STORAGE_LIST"; - case IPC_PB_ENTRY_INFO: - return "IPC_PB_ENTRY_INFO"; - case IPC_PB_3GPB_CAPA: - return "IPC_PB_3GPB_CAPA"; - case IPC_DISP_ICON_INFO: - return "IPC_DISP_ICON_INFO"; - case IPC_DISP_HOMEZONE_INFO: - return "IPC_DISP_HOMEZONE_INFO"; - case IPC_DISP_RSSI_INFO: - return "IPC_DISP_RSSI_INFO"; - case IPC_NET_PREF_PLMN: - return "IPC_NET_PREF_PLMN"; - case IPC_NET_PLMN_SEL: - return "IPC_NET_PLMN_SEL"; - case IPC_NET_SERVING_NETWORK: - return "IPC_NET_SERVING_NETWORK"; - case IPC_NET_PLMN_LIST: - return "IPC_NET_PLMN_LIST"; - case IPC_NET_REGIST: - return "IPC_NET_REGIST"; - case IPC_NET_SUBSCRIBER_NUM: - return "IPC_NET_SUBSCRIBER_NUM"; - case IPC_NET_BAND_SEL: - return "IPC_NET_BAND_SEL"; - case IPC_NET_SERVICE_DOMAIN_CONFIG: - return "IPC_NET_SERVICE_DOMAIN_CONFIG"; - case IPC_NET_POWERON_ATTACH: - return "IPC_NET_POWERON_ATTACH"; - case IPC_NET_MODE_SEL: - return "IPC_NET_MODE_SEL"; - case IPC_NET_ACQ_ORDER: - return "IPC_NET_ACQ_ORDER"; - case IPC_NET_IDENTITY: - return "IPC_NET_IDENTITY"; - case IPC_NET_PREFERRED_NETWORK_INFO: - return "IPC_NET_PREFERRED_NETWORK_INFO"; - case IPC_SND_SPKR_VOLUME_CTRL: - return "IPC_SND_SPKR_VOLUME_CTRL"; - case IPC_SND_MIC_MUTE_CTRL: - return "IPC_SND_MIC_MUTE_CTRL"; - case IPC_SND_AUDIO_PATH_CTRL: - return "IPC_SND_AUDIO_PATH_CTRL"; - case IPC_SND_AUDIO_SOURCE_CTRL: - return "IPC_SND_AUDIO_SOURCE_CTRL"; - case IPC_SND_LOOPBACK_CTRL: - return "IPC_SND_LOOPBACK_CTRL"; - case IPC_SND_VOICE_RECORDING_CTRL: - return "IPC_SND_VOICE_RECORDING_CTRL"; - case IPC_SND_VIDEO_CALL_CTRL: - return "IPC_SND_VIDEO_CALL_CTRL"; - case IPC_SND_RINGBACK_TONE_CTRL: - return "IPC_SND_RINGBACK_TONE_CTRL"; - case IPC_SND_CLOCK_CTRL: - return "IPC_SND_CLOCK_CTRL"; - case IPC_SND_WB_AMR_STATUS: - return "IPC_SND_WB_AMR_STATUS"; - case IPC_MISC_ME_VERSION: - return "IPC_MISC_ME_VERSION"; - case IPC_MISC_ME_IMSI: - return "IPC_MISC_ME_IMSI"; - case IPC_MISC_ME_SN: - return "IPC_MISC_ME_SN"; - case IPC_MISC_TIME_INFO: - return "IPC_MISC_TIME_INFO"; - case IPC_MISC_DEBUG_LEVEL: - return "IPC_MISC_DEBUG_LEVEL"; - case IPC_SVC_ENTER: - return "IPC_SVC_ENTER"; - case IPC_SVC_END: - return "IPC_SVC_END"; - case IPC_SVC_PRO_KEYCODE: - return "IPC_SVC_PRO_KEYCODE"; - case IPC_SVC_SCREEN_CFG: - return "IPC_SVC_SCREEN_CFG"; - case IPC_SVC_DISPLAY_SCREEN: - return "IPC_SVC_DISPLAY_SCREEN"; - case IPC_SVC_CHANGE_SVC_MODE: - return "IPC_SVC_CHANGE_SVC_MODE"; - case IPC_SVC_DEVICE_TEST: - return "IPC_SVC_DEVICE_TEST"; - case IPC_SVC_DEBUG_DUMP: - return "IPC_SVC_DEBUG_DUMP"; - case IPC_SVC_DEBUG_STRING: - return "IPC_SVC_DEBUG_STRING"; - case IPC_SS_WAITING: - return "IPC_SS_WAITING"; - case IPC_SS_CLI: - return "IPC_SS_CLI"; - case IPC_SS_BARRING: - return "IPC_SS_BARRING"; - case IPC_SS_BARRING_PW: - return "IPC_SS_BARRING_PW"; - case IPC_SS_FORWARDING: - return "IPC_SS_FORWARDING"; - case IPC_SS_INFO: - return "IPC_SS_INFO"; - case IPC_SS_MANAGE_CALL: - return "IPC_SS_MANAGE_CALL"; - case IPC_SS_USSD: - return "IPC_SS_USSD"; - case IPC_SS_AOC: - return "IPC_SS_AOC"; - case IPC_SS_RELEASE_COMPLETE: - return "IPC_SS_RELEASE_COMPLETE"; - case IPC_GPRS_DEFINE_PDP_CONTEXT: - return "IPC_GPRS_DEFINE_PDP_CONTEXT"; - case IPC_GPRS_QOS: - return "IPC_GPRS_QOS"; - case IPC_GPRS_PS: - return "IPC_GPRS_PS"; - case IPC_GPRS_PDP_CONTEXT: - return "IPC_GPRS_PDP_CONTEXT"; - case IPC_GPRS_ENTER_DATA: - return "IPC_GPRS_ENTER_DATA"; - case IPC_GPRS_SHOW_PDP_ADDR: - return "IPC_GPRS_SHOW_PDP_ADDR"; - case IPC_GPRS_MS_CLASS: - return "IPC_GPRS_MS_CLASS"; - case IPC_GPRS_3G_QUAL_SRVC_PROFILE: - return "IPC_GPRS_3G_QUAL_SRVC_PROFILE"; - case IPC_GPRS_IP_CONFIGURATION: - return "IPC_GPRS_IP_CONFIGURATION"; - case IPC_GPRS_DEFINE_SEC_PDP_CONTEXT: - return "IPC_GPRS_DEFINE_SEC_PDP_CONTEXT"; - case IPC_GPRS_TFT: - return "IPC_GPRS_TFT"; - case IPC_GPRS_HSDPA_STATUS: - return "IPC_GPRS_HSDPA_STATUS"; - case IPC_GPRS_CURRENT_SESSION_DATA_COUNTER: - return "IPC_GPRS_CURRENT_SESSION_DATA_COUNTER"; - case IPC_GPRS_DATA_DORMANT: - return "IPC_GPRS_DATA_DORMANT"; - case IPC_GPRS_PIN_CTRL: - return "IPC_GPRS_PIN_CTRL"; - case IPC_GPRS_CALL_STATUS: - return "IPC_GPRS_CALL_STATUS"; - case IPC_GPRS_PORT_LIST: - return "IPC_GPRS_PORT_LIST"; - case IPC_SAT_PROFILE_DOWNLOAD: - return "IPC_SAT_PROFILE_DOWNLOAD"; - case IPC_SAT_ENVELOPE_CMD: - return "IPC_SAT_ENVELOPE_CMD"; - case IPC_SAT_PROACTIVE_CMD: - return "IPC_SAT_PROACTIVE_CMD"; - case IPC_SAT_TERMINATE_USAT_SESSION: - return "IPC_SAT_TERMINATE_USAT_SESSION"; - case IPC_SAT_EVENT_DOWNLOAD: - return "IPC_SAT_EVENT_DOWNLOAD"; - case IPC_SAT_PROVIDE_LOCAL_INFO: - return "IPC_SAT_PROVIDE_LOCAL_INFO"; - case IPC_SAT_POLLING: - return "IPC_SAT_POLLING"; - case IPC_SAT_REFRESH: - return "IPC_SAT_REFRESH"; - case IPC_SAT_SETUP_EVENT_LIST: - return "IPC_SAT_SETUP_EVENT_LIST"; - case IPC_SAT_CALL_CONTROL_RESULT: - return "IPC_SAT_CALL_CONTROL_RESULT"; - case IPC_SAT_IMAGE_CLUT: - return "IPC_SAT_IMAGE_CLUT"; - case IPC_SAT_SETUP_CALL_PROCESSING: - return "IPC_SAT_SETUP_CALL_PROCESSING"; - case IPC_IMEI_START: - return "IPC_IMEI_START"; - case IPC_IMEI_CHECK_DEVICE_INFO: - return "IPC_IMEI_CHECK_DEVICE_INFO"; - case IPC_RFS_NV_READ_ITEM: - return "IPC_RFS_NV_READ_ITEM"; - case IPC_RFS_NV_WRITE_ITEM: - return "IPC_RFS_NV_WRITE_ITEM"; - case IPC_GEN_PHONE_RES: - return "IPC_GEN_PHONE_RES"; - default: - snprintf((char *) &command_string, sizeof(command_string), - "0x%04x", command); - return command_string; - } -} - -const char *ipc_group_string(unsigned char group) -{ - static char group_string[5] = { 0 }; - - switch (group) { - case IPC_GROUP_PWR: - return "IPC_GROUP_PWR"; - case IPC_GROUP_CALL: - return "IPC_GROUP_CALL"; - case IPC_GROUP_SMS: - return "IPC_GROUP_SMS"; - case IPC_GROUP_SEC: - return "IPC_GROUP_SEC"; - case IPC_GROUP_PB: - return "IPC_GROUP_PB"; - case IPC_GROUP_DISP: - return "IPC_GROUP_DISP"; - case IPC_GROUP_NET: - return "IPC_GROUP_NET"; - case IPC_GROUP_SND: - return "IPC_GROUP_SND"; - case IPC_GROUP_MISC: - return "IPC_GROUP_MISC"; - case IPC_GROUP_SVC: - return "IPC_GROUP_SVC"; - case IPC_GROUP_SS: - return "IPC_GROUP_SS"; - case IPC_GROUP_GPRS: - return "IPC_GROUP_GPRS"; - case IPC_GROUP_SAT: - return "IPC_GROUP_SAT"; - case IPC_GROUP_CFG: - return "IPC_GROUP_CFG"; - case IPC_GROUP_IMEI: - return "IPC_GROUP_IMEI"; - case IPC_GROUP_GPS: - return "IPC_GROUP_GPS"; - case IPC_GROUP_SAP: - return "IPC_GROUP_SAP"; - case IPC_GROUP_RFS: - return "IPC_GROUP_RFS"; - case IPC_GROUP_GEN: - return "IPC_GROUP_GEN"; - default: - snprintf((char *) &group_string, sizeof(group_string), "0x%02x", - (unsigned int)group_string); - return group_string; - } -} - int ipc_data_dump(struct ipc_client *client, const void *data, size_t size) { unsigned int cols = 8; diff --git a/samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c b/samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c index c6b1578..cdac3e4 100644 --- a/samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c +++ b/samsung-ipc/modems/xmm626/xmm626_kernel_smdk4412.c @@ -19,11 +19,13 @@ */ #define _GNU_SOURCE -#include <stdlib.h> + +#include <fcntl.h> #include <stdio.h> -#include <unistd.h> +#include <stdlib.h> #include <string.h> -#include <fcntl.h> +#include <unistd.h> + #include <sys/ioctl.h> #include <sys/select.h> @@ -582,11 +584,17 @@ char *xmm626_kernel_smdk4412_gprs_get_iface( __attribute__((unused)) struct ipc_client *client, unsigned int cid) { char *iface = NULL; + int rc; if (cid > XMM626_SEC_MODEM_GPRS_IFACE_COUNT) return NULL; - asprintf(&iface, "%s%d", XMM626_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1); + rc = asprintf(&iface, "%s%d", + XMM626_SEC_MODEM_GPRS_IFACE_PREFIX, cid - 1); + if (rc == -1) { + ipc_client_log(client, "%s: asprintf failed", __func__); + return NULL; + } return iface; } diff --git a/samsung-ipc/partitions/android/android.c b/samsung-ipc/partitions/android/android.c index 9ec6ed4..9d2322f 100644 --- a/samsung-ipc/partitions/android/android.c +++ b/samsung-ipc/partitions/android/android.c @@ -84,8 +84,7 @@ int open_android_modem_partition_by_name(struct ipc_client *client, return -errno; } - strncpy(path, partitions_dirnames[i], - strlen(partitions_dirnames[i])); + strcpy(path, partitions_dirnames[i]); strcat(path, name); ipc_client_log(client, "%s: Trying to open %s", diff --git a/samsung-ipc/tests/Makefile.am b/samsung-ipc/tests/Makefile.am index d049c74..ad4280e 100644 --- a/samsung-ipc/tests/Makefile.am +++ b/samsung-ipc/tests/Makefile.am @@ -1,13 +1,20 @@ NULL = +EXTRA_DIST = $(NULL) AM_CFLAGS = \ - -I$(top_srcdir)/include \ - -I$(top_srcdir)/samsung-ipc \ - $(OPENSSL_CFLAGS) \ - $(NULL) + -I$(top_srcdir)/include \ + -I$(top_srcdir)/samsung-ipc \ + $(OPENSSL_CFLAGS) \ + $(NULL) + +AM_LDFLAGS = $(ALL_STATIC_LDFLAGS) + +if WANT_STRICT_CFLAGS +AM_CFLAGS += $(STRICT_CFLAGS) +endif if WANT_DEBUG -AM_CFLAGS += -ggdb -O0 -DDEBUG +AM_CFLAGS += -DDEBUG endif bin_PROGRAMS = libsamsung-ipc-test @@ -19,11 +26,14 @@ libsamsung_ipc_test_SOURCES = \ $(NULL) libsamsung_ipc_test_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la -libsamsung_ipc_test_LDFLAGS = # TODO: Find a way to make test more modular and represent each run of # libsamsung-ipc-test in TEST while having it implemented in a single # python file -PY_LOG_COMPILER = $(PYTHON) +if WANT_VALGRIND_CHECKING +AM_TESTS_ENVIRONMENT = VALGRIND='$(VALGRIND)'; export VALGRIND; +endif +PY_LOG_COMPILER = $(PYTHON3) TEST_EXTENSIONS = .py TESTS = libsamsung-ipc-test.py +EXTRA_DIST += $(TESTS) diff --git a/samsung-ipc/tests/libsamsung-ipc-test.py b/samsung-ipc/tests/libsamsung-ipc-test.py index 328f4f0..5435013 100755 --- a/samsung-ipc/tests/libsamsung-ipc-test.py +++ b/samsung-ipc/tests/libsamsung-ipc-test.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # This file is part of libsamsung-ipc. # @@ -26,14 +26,26 @@ class libsamsung_ipc_test(object): def __init__(self): srcdir = os.environ.get('srcdir', None) - # Enable also to test without automake - if not srcdir: - srcdir = os.path.dirname(sys.argv[0]) + command_path = '' + if srcdir: + command_path = '.' + os.sep + 'libsamsung-ipc-test' + # Enable to run tests without automake + else: + command_path = os.path.dirname(sys.argv[0]) \ + + os.sep \ + + 'libsamsung-ipc-test' - self.run = sh.Command(srcdir + os.sep + "libsamsung-ipc-test") + if 'VALGRIND' in os.environ: + self.run = sh.Command(os.environ['VALGRIND']) + self.run = self.run.bake('-v', + '--log-file=valgrind.%p.log', + '--leak-check=full', + command_path) + else: + self.run = sh.Command(command_path) def run_all_tests(self): - output = str(self.run("list-tests")).split(os.linesep) + output = str(self.run('list-tests')).split(os.linesep) # Remove the last line break from the output output.remove('') @@ -44,7 +56,7 @@ class libsamsung_ipc_test(object): output.pop(0) for test_name in output: - self.run("test", test_name.replace(' ', '')) + self.run('test', test_name.replace(' ', '')) def main(): tests = libsamsung_ipc_test() diff --git a/samsung-ipc/tests/partitions/android.c b/samsung-ipc/tests/partitions/android.c index 708480a..7b067e9 100644 --- a/samsung-ipc/tests/partitions/android.c +++ b/samsung-ipc/tests/partitions/android.c @@ -42,17 +42,123 @@ static char const * const dummy_modem_image_paths[] = { NULL }; +int delete_dummy_modem_image(struct ipc_client *client, + __attribute__((unused)) const char * const path) +{ + int rc; + char *endp; + char *dir; + + rc = unlink(path); + if (rc == -1) { + rc = errno; + if (rc != ENOENT) { + ipc_client_log(client, + "%s: unlink %s failed with error %d: %s", + __func__, path, rc, strerror(rc)); + errno = rc; + return -1; + } + } + + endp = strrchr(path, '/'); + + dir = malloc(endp - path + 1); + if (dir == NULL) { + rc = errno; + ipc_client_log(client, + "%s: calloc failed with error %d: %s", + __func__, rc, strerror(rc)); + errno = rc; + return -1; -int create_dummy_modem_image(__attribute__((unused)) struct ipc_client *client, + } + + memcpy(dir, path, endp - path); + dir[endp - path] = '\0'; + + rc = rmdir(dir); + if (rc == -1) { + rc = errno; + if (rc != ENOENT) { + ipc_client_log(client, + "%s: rmdir %s failed with error %d: %s", + __func__, dir, rc, strerror(rc)); + + free(dir); + errno = rc; + return -1; + } + } + + free(dir); + return 0; +} + + +int create_dummy_modem_image(struct ipc_client *client, __attribute__((unused)) const char * const path) { - /* TODO: replace it by C code but make sure that the replacement code - * is as robust as the shell commands - */ - system("mkdir -p /tmp/libsamsung-ipc.55f4731d2e11e85bd889/"); - system("touch /tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img"); + int fd; + int rc; + + rc = mkdir("/tmp/", 0755); + if (rc == -1) { + rc = errno; + if (rc != EEXIST) { + ipc_client_log(client, + "%s: mkdir %s failed with error %d: %s", + __func__, "/tmp/", rc, strerror(rc)); + return -1; + } + } + + rc = mkdir("/tmp/libsamsung-ipc.55f4731d2e11e85bd889/", 0755); + if (rc == -1) { + rc = errno; + if (rc != EEXIST) { + ipc_client_log(client, + "%s: mkdir %s failed with error %d: %s", + __func__, + "/tmp/libsamsung-ipc.55f4731d2e11e85bd889/", + rc, strerror(rc)); + return -1; + } + } + + fd = open("/tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img", + O_CREAT, 0755); + if (fd == -1) { + rc = errno; + ipc_client_log(client, + "%s: open %s failed with error %d: %s", + __func__, + "/tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img", + rc, strerror(rc)); + goto error; + } + + rc = close(fd); + if (rc == -1) { + rc = errno; + ipc_client_log(client, + "%s: close %s failed with error %d: %s", + __func__, + "/tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img", + rc, strerror(rc)); + goto error; + } return 0; + +error: + rc = delete_dummy_modem_image( + client, "/tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img"); + if (rc == -1) + ipc_client_log(client, + "%s: delete_dummy_modem_image %s failed with error -1", + __func__); + return -1; } int test_open_android_modem_partition(struct ipc_client *client) @@ -92,5 +198,15 @@ int test_open_android_modem_partition(struct ipc_client *client) return -1; } + rc = delete_dummy_modem_image( + client, "/tmp/libsamsung-ipc.55f4731d2e11e85bd889/modem.img"); + if (rc == -1) { + rc = errno; + ipc_client_log(client, + "%s: delete_dummy_modem_image() failed with errror %d: %s\n", + __func__, rc, strerror(rc)); + return -1; + } + return 0; } diff --git a/samsung-ipc/utils.c b/samsung-ipc/utils.c index 44cbe2d..18f5d2b 100644 --- a/samsung-ipc/utils.c +++ b/samsung-ipc/utils.c @@ -295,7 +295,7 @@ int network_iface_up(const char *iface, int domain, int type) return -1; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, iface, IFNAMSIZ); + memcpy(ifr.ifr_name, iface, IFNAMSIZ); fd = socket(domain, type, 0); if (fd < 0) @@ -334,7 +334,7 @@ int network_iface_down(const char *iface, int domain, int type) return -1; memset(&ifr, 0, sizeof(ifr)); - strncpy(ifr.ifr_name, iface, IFNAMSIZ); + memcpy(ifr.ifr_name, iface, IFNAMSIZ); fd = socket(domain, type, 0); if (fd < 0) diff --git a/scripts/PKGBUILD b/scripts/PKGBUILD new file mode 100644 index 0000000..155a765 --- /dev/null +++ b/scripts/PKGBUILD @@ -0,0 +1,55 @@ +# Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. + +pkgname=libsamsung-ipc-git +pkgver=0.3.1.r703.7c5e96a +pkgrel=1 +pkgdesc="samsung-ipc modem protocol implementation." +arch=('armv7h' 'i686' 'x86_64') +license=('GPL2') +makedepends=('autoconf' + 'automake' + 'coreutils' + 'ddrescue' + 'gawk' + 'grep' + 'libtool' + 'pkg-config' + 'python' + 'python-sh' + 'sed' + 'valgrind') +depends=('openssl') + +pkgver() { + _base_version="0.3.1" + _base_revision="5cb3e7cb99701cae738693f2d6a6797a4d2df679" + + if [ -d ../../.git ] ; then + printf "%s.r%s.%s" \ + "${_base_version}" \ + "$(git -C ../../ rev-list --count HEAD)" \ + "$(git -C ../../ rev-parse --short HEAD)" + else + date "+%Y%m%d" + fi +} + +build() { + ../../autogen.sh + ../../configure \ + --prefix=/usr \ + --enable-debug --enable-valgrind-tests --enable-strict-cflags + make +} + +check() { + make check +} + +package(){ + make DESTDIR="$pkgdir" install +} diff --git a/scripts/guix.scm b/scripts/guix.scm index a917a82..6343208 100644 --- a/scripts/guix.scm +++ b/scripts/guix.scm @@ -41,56 +41,124 @@ ;;; to all the exported functions, and make a new release when that is ;;; done. -(use-modules - (ice-9 popen) - (ice-9 rdelim) - (sxml ssax input-parse) - ((guix licenses) #:prefix license:) - (guix build-system android-ndk) - (guix build-system gnu) - (guix gexp) - (guix git-download) - (guix packages) - (gnu packages android) - (gnu packages autotools) - (gnu packages disk) - (gnu packages linux) - (gnu packages llvm) - (gnu packages pkg-config) - (gnu packages python) - (gnu packages python-xyz) - (gnu packages tls)) +(use-modules (ice-9 popen) + (ice-9 rdelim) + (ice-9 regex) + (ice-9 textual-ports) + (sxml ssax input-parse) + ((guix licenses) + #:prefix license:) + (guix build-system android-ndk) + (guix build-system gnu) + (guix gexp) + (guix git-download) + (guix packages) + (guix profiles) + (guix transformations) + (gnu packages) + (gnu packages android) + (gnu packages autotools) + (gnu packages base) + (gnu packages curl) + (gnu packages disk) + (gnu packages linux) + (gnu packages llvm) + (gnu packages pkg-config) + (gnu packages python) + (gnu packages python-xyz) + (gnu packages tls) + (gnu packages valgrind)) + +;; We need a more recent version of android-make-stub as it now +;; support passing LOCAL_MODULE= to make to build specific local +;; modules. This is needed because android-make-stub doesn't handle +;; dependencies, so we need to make sure that libsamsung-ipc is built +;; first. In addition we need a fix to make the applications that +;; depend on libsamsung-ipc find libsamsung-ipc's includes directory. +(define with-fixed-android-make-stub + (options->transformation '((with-commit . "android-make-stub=4bc0e068c32fe525741da00af064ddc079de7e4b")))) + +(define (parse-android.mk port modules-list) + (let* ((line (read-line port))) + (if (not (eof-object? line)) + (let* ((line-parts (string-split line #\space))) + (if (string=? (car line-parts) "LOCAL_MODULE") + (if (not (string=? (list-ref line-parts 2) "libsamsung-ipc")) + (if (string=? modules-list "") + (parse-android.mk port + (list-ref line-parts 2)) + (parse-android.mk port + (string-append modules-list " " + (list-ref line-parts 2)))) + (parse-android.mk port modules-list)) + (parse-android.mk port modules-list))) modules-list))) + +(define android-local-modules-list + (let* ((port (open-input-file "./Android.mk")) + (local-modules (parse-android.mk port ""))) + (close-input-port port) + (string-split local-modules #\space))) (define %common-strict-cflags - (string-append - " CFLAGS=" - " -W" - " -Wall" - " -Werror" - " -Werror=address" - " -Werror=return-type" - " -Werror=sequence-point" - " -Winit-self" - " -Wno-unused" - " -Wpointer-arith" - " -Wunused" - " -Wunused-function")) + (let* ((port (open-input-pipe "./strict-cflags.sh")) + (str (read-line port))) + (close-pipe port) + (string-append "CFLAGS=" str))) (define %clang-strict-cflags - (string-append - "-Werror=non-virtual-dtor")) + (string-append "-Werror=non-virtual-dtor")) (define %commit (let* ((port (open-input-pipe "git --no-pager log --oneline HEAD -1 --format='%H'")) - (str (read-line port))) - (close-pipe port) - str)) + (str (read-line port))) + (close-pipe port) str)) (define %local-source - (local-file - (dirname (dirname (current-filename))) - #:recursive? #t)) + (local-file (dirname (dirname (current-filename))) + #:recursive? #t)) + +(define android-make + #~(lambda (target android-local-modules) + (lambda* (#:key inputs make-flags native-inputs outputs + #:allow-other-keys) + (substitute* "Android.mk" + (("BUILD_SHARED_LIBRARY") + "BUILD_HOST_SHARED_LIBRARY") + (("BUILD_EXECUTABLE") + "BUILD_HOST_EXECUTABLE")) + ((assoc-ref %standard-phases target) + #:inputs inputs + #:outputs outputs + #:make-flags (append make-flags + '("LDFLAGS=-lssl -lcrypto" + "LOCAL_MODULE=libsamsung-ipc" + "SO=libsamsung-ipc.so"))) + (map-in-order (lambda (local-module) + ((assoc-ref %standard-phases target) + #:inputs inputs + #:outputs outputs + #:make-flags (append make-flags + (list (string-append + "LDFLAGS=-Wl,-rpath=" + #$output + "/lib -lssl -lcrypto -L .") + (string-append + "LOCAL_MODULE=" + local-module))))) + android-local-modules)))) + +(define android-phases + #~(modify-phases %standard-phases + (delete 'bootstrap) + (replace 'build + (#$android-make + 'build + '#$android-local-modules-list)) + (replace 'install + (#$android-make + 'install + '#$android-local-modules-list)))) (define-public libsamsung-ipc (package @@ -98,116 +166,151 @@ (version (git-version "0.0" "HEAD" %commit)) (source %local-source) (build-system gnu-build-system) - (native-inputs - `(("autoreconf" ,autoconf) - ("aclocal" ,automake) - ("ddrescue", ddrescue) - ("libtool" ,libtool) - ("pkgconfig" ,pkg-config) - ("python" ,python) - ("python-sh" ,python-sh))) - (inputs - `(("openssl" ,openssl))) + (native-inputs (list autoconf + automake + ddrescue + `(,(canonical-package glibc) "debug") + libtool + pkg-config + python + python-sh + valgrind)) + (inputs (list curl libressl)) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'build 'patch-python - (lambda _ - (substitute* (find-files "." ".*\\.py$") - (("/usr/bin/env python") (which "python3"))) - #t))))) - (synopsis "libsamsung-ipc is a free software implementation of the Samsung IPC modem protocol") + (list #:phases #~(modify-phases %standard-phases + (add-before 'build 'fix-valgrind + (lambda _ + (substitute* (find-files "." ".*\\.py$") + (("'--leak-check=full',") + (string-append + "'--leak-check=full', '--extra-debuginfo-path=" + (ungexp (this-package-native-input "glibc") + "debug") "/lib/debug',")))))) + #:configure-flags #~(list "--enable-debug" + "--enable-valgrind-tests"))) + (synopsis + "libsamsung-ipc is a free software implementation of the Samsung IPC modem protocol") (description "libsamsung-ipc is a free software implementation of the Samsung IPC modem protocol, found in many Samsung smartphones and tablets.") (home-page "https://www.replicant.us") (license license:gpl2+))) +(define is-file-static + #~(lambda (readelf path) + ;; str is also eof if the file doesn't exist + (if (not (file-exists? tool)) #f + (let* ((port (open-input-pipe (string-append readelf " --dyn-syms " + path))) + (str (read-line port))) + (close-pipe port) + (eof-object? str))))) + +(define-public libsamsung-ipc-static + (package + (inherit libsamsung-ipc) + (name "libsamsung-ipc-static") + (native-inputs (list autoconf + automake + binutils + ddrescue + libtool + pkg-config + python + python-sh)) + ;; The libressl package contains .a in + ;; /gnu/store/[...]-libressl-[...]/lib/*.a + (inputs (list curl libressl)) + (arguments + (list #:modules '((ice-9 popen) + (ice-9 rdelim) + (guix build utils) + (guix build gnu-build-system)) + #:tests? #f + #:phases #~(modify-phases %standard-phases + ;; https-send-sms depends on curl and Guix doesn't have + ;; a static libcurl. + (add-after 'unpack 'remove-https-send-sms + (lambda _ + (substitute* "tools/Makefile.am" + (("https-send-sms \\\\") + "\\")))) + (add-after 'compress-documentation 'check-static-files + (lambda _ + (display "Checking static files:\n") + (map-in-order (lambda (tool) + (if (#$is-file-static + (string-append #$(this-package-native-input + "binutils") + "/bin/readelf") tool) + (display (string-append + "[ OK ] " + (basename tool) ": " + tool "\n")) + ((lambda _ + (display (string-append + "[ !! ] " + (basename tool) + ": " tool "\n")) + (#f))))) + (list + "samsung-ipc/tests/libsamsung-ipc-test" + "tools/ipc-test" + "tools/nv_data-imei" + "tools/nv_data-md5" + "tools/ipc-modem/ipc-modem"))))) + #:configure-flags #~(list "--enable-debug" "--enable-static=yes" + "--enable-shared=no" + "--enable-static-progs"))))) + (define-public libsamsung-ipc-gcc-android (package - (inherit libsamsung-ipc) + (inherit libsamsung-ipc) (name "libsamsung-ipc-gcc-android") (build-system android-ndk-build-system) - (inputs - `(("android-libutils" ,android-libutils) - ("libcrypto" ,openssl))) + (inputs (list android-libutils curl libressl)) (native-inputs '()) (arguments - `(#:phases - (modify-phases %standard-phases - (delete 'bootstrap) - (add-before 'build 'patch-host - (lambda _ - (substitute* "Android.mk" - (("BUILD_SHARED_LIBRARY") "BUILD_HOST_SHARED_LIBRARY") - (("BUILD_STATIC_LIBRARY") "BUILD_HOST_STATIC_LIBRARY") - (("BUILD_STATIC_EXECUTABLE") "BUILD_HOST_STATIC_EXECUTABLE")) - #t))) - #:make-flags (list ,%common-strict-cflags))))) + (list #:make-flags #~(list #$%common-strict-cflags + #$%clang-strict-cflags) + #:phases android-phases)))) (define-public libsamsung-ipc-gcc-autotools (package - (inherit libsamsung-ipc) - (name "libsamsung-ipc-gcc-autotools") - (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'build 'patch-python - (lambda _ - (substitute* (find-files "." ".*\\.py$") - (("/usr/bin/env python") (which "python3"))) - #t))) - #:make-flags (list ,%common-strict-cflags))))) + (inherit libsamsung-ipc) + (name "libsamsung-ipc-gcc-autotools") + (arguments + (list #:configure-flags #~(list "--enable-debug") + #:make-flags #~(list #$%common-strict-cflags))))) (define-public libsamsung-ipc-clang-autotools (package - (inherit libsamsung-ipc) - (name "libsamsung-ipc-gcc-autotools") - (native-inputs - `(("autoreconf" ,autoconf) - ("aclocal" ,automake) - ("ddrescue", ddrescue) - ("libtool" ,libtool) - ("pkgconfig" ,pkg-config) - ("python" ,python) - ("python-sh" ,python-sh) - ("clang" ,clang))) + (inherit libsamsung-ipc) + (name "libsamsung-ipc-clang-autotools") + (native-inputs (list autoconf + automake + ddrescue + libtool + pkg-config + python + python-sh + clang)) (arguments - `(#:phases - (modify-phases %standard-phases - (add-before 'build 'patch-python - (lambda _ - (substitute* (find-files "." ".*\\.py$") - (("/usr/bin/env python") (which "python3"))) - #t))) - #:make-flags (list ,%common-strict-cflags ,%clang-strict-cflags))))) + (list #:configure-flags #~(list "--enable-debug") + #:make-flags #~(list #$%common-strict-cflags + #$%clang-strict-cflags))))) (define-public libsamsung-ipc-clang-android (package - (inherit libsamsung-ipc) + (inherit libsamsung-ipc) (name "libsamsung-ipc-clang-android") (build-system android-ndk-build-system) - (inputs - `(("android-libutils" ,android-libutils) - ("libcrypto" ,openssl) - ("clang" ,clang))) + (inputs (list android-libutils clang curl libressl)) (native-inputs '()) (arguments - `(#:phases - (modify-phases %standard-phases - (delete 'bootstrap) - (add-before 'build 'patch-host - (lambda _ - (substitute* "Android.mk" - (("BUILD_SHARED_LIBRARY") "BUILD_HOST_SHARED_LIBRARY") - (("BUILD_STATIC_LIBRARY") "BUILD_HOST_STATIC_LIBRARY") - (("BUILD_STATIC_EXECUTABLE") "BUILD_HOST_STATIC_EXECUTABLE")) - #t)) - (add-after 'patch-host 'prepare-build-environment - (lambda* (#:key inputs #:allow-other-keys) - (setenv "CC" "clang") - #t))) - #:make-flags (list ,%common-strict-cflags ,%clang-strict-cflags))))) + (list #:make-flags #~(list #$%common-strict-cflags + #$%clang-strict-cflags) + #:phases android-phases)))) ;; Combinaisons: ;; +--------------------------------+----------+----------+--------------+--------------+ @@ -226,7 +329,8 @@ found in many Samsung smartphones and tablets.") ;; +--------------------------------+----------+----------+--------------+--------------+ (list libsamsung-ipc - libsamsung-ipc-gcc-android - libsamsung-ipc-gcc-autotools - libsamsung-ipc-clang-android - libsamsung-ipc-clang-autotools) + libsamsung-ipc-static + (with-fixed-android-make-stub libsamsung-ipc-clang-android) + (with-fixed-android-make-stub libsamsung-ipc-gcc-android) + libsamsung-ipc-clang-autotools + libsamsung-ipc-gcc-autotools) diff --git a/scripts/manifest.scm b/scripts/manifest.scm new file mode 100644 index 0000000..dfc82c7 --- /dev/null +++ b/scripts/manifest.scm @@ -0,0 +1,59 @@ +;;; Copyright © 2021 Denis Carikli <GNUtoo@cyberdimension.org> +;;; +;;; This file is free software; you can redistribute it and/or modify it +;;; under the terms of the GNU General Public License as published by +;;; the Free Software Foundation; either version 3 of the License, or (at +;;; your option) any later version. +;;; +;;; This file is distributed in the hope that it will be useful, but +;;; WITHOUT ANY WARRANTY; without even the implied warranty of +;;; MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +;;; GNU General Public License for more details. +;;; +;;; You should have received a copy of the GNU General Public License +;;; along with GNU Guix. If not, see <http://www.gnu.org/licenses/>. +;;; The guix.scm file is a convention: A file named guix.scm is +;;; found in several project source code, either in the top +;;; directory or in sub-directories like contrib for instance. + +;;; This file can be used to setup a development environment for Guix +;;; users with the following command: +;;; guix shell --pure --container -f scripts/manifest.scm + +(use-modules + (gnu packages autotools) + (gnu packages base) + (gnu packages code) + (gnu packages commencement) + (gnu packages compression) + (gnu packages curl) + (gnu packages disk) + (gnu packages gawk) + (gnu packages pkg-config) + (gnu packages python) + (gnu packages python-xyz) + (gnu packages tls)) + +(list + autoconf + automake + bzip2 + coreutils + curl + ddrescue + diffutils + findutils + gawk + gzip + gcc-toolchain + grep + lcov + libtool + gnu-make + openssl + pkg-config + python + python-sh + sed + tar + xz) diff --git a/scripts/rebase-build-check-android.sh b/scripts/rebase-build-check-android.sh new file mode 100755 index 0000000..e43e3c6 --- /dev/null +++ b/scripts/rebase-build-check-android.sh @@ -0,0 +1,102 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +# Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. +set -e + +usage() +{ + printf "Usage:\n" + printf "%s build-from <base-commit-ref> " "$0" + printf "# Build all commits since <base-commit-ref>\n" "%0" + printf "%s continue " "$0" + printf "# Continue rebasing and building commits\n" "%0" + exit 64; # EX_USAGE from sysexits.h +} + +print_header() +{ + set +e + message="$1" + + len=$(expr $(echo -n ${message} | wc -c) + 2) + + nr_chars=$(expr $(expr 80 - ${len}) / 2) + + i="${nr_chars}" + + while [ ${i} -gt 0 ] ; do + echo -n "#" + i="$(expr ${i} - 1)" + done + + echo -n " ${message} " + + i="${nr_chars}" + + while [ ${i} -gt 0 ] ; do + echo -n "#" + i="$(expr ${i} - 1)" + done + echo + set -e +} + +build_and_git_rebase_continue() +{ + total_commits="$1" + + total_targets="$(./vendor/replicant/build.sh targets | wc -l)" + parallel_tasks=$(echo "$(grep 'processor' /proc/cpuinfo | wc -l ) + 1" | bc) + + local_modules="$(grep \ + "^LOCAL_MODULE := " \ + hardware/replicant/libsamsung-ipc/Android.mk | \ + awk '{print $3}' | sort -u)" + + source build/envsetup.sh + + # Currently all the Replicant versions supported by libsamsung-ipc + # have an aosp_arm-eng target. Using aosp_arm-eng also ensures + # that TARGET_DEVICE isn't set by the device repository. This also + # leaves us more freedom in libsamsung-ipc as we could for + # instance decide to not build unused code based on TARGET_DEVICE. + lunch aosp_arm-eng + + commit_nr=1 + while true ; do + print_header "[ commit ${commit_nr} of ${total_commits} ]" + make "-j${parallel_tasks}" ${local_modules} + git -C hardware/replicant/libsamsung-ipc rebase --continue || break + commit_nr="$(expr ${commit_nr} + 1)" + done +} + +if [ $# -eq 2 ] && [ "$1" == "build-from" ] ; then + base_commit="$2" + nr_commits="$(git -C hardware/replicant/libsamsung-ipc log --oneline \ + ${base_commit}~1..HEAD --oneline | wc -l)" + GIT_EDITOR="sed 's#^pick #edit #g' -i " \ + git -C hardware/replicant/libsamsung-ipc \ + rebase -i "${base_commit}" + + build_and_git_rebase_continue "${nr_commits}" +elif [ $# -eq 1 ] && [ "$1" == "continue" ] ; then + nr_commits="$(git -C hardware/replicant/libsamsung-ipc \ + log --oneline REBASE_HEAD~1..ORIG_HEAD --oneline | wc -l)" + build_and_git_rebase_continue "${nr_commits}" +else + usage +fi diff --git a/scripts/rebase-build-check-gnu-linux.sh b/scripts/rebase-build-check-gnu-linux.sh new file mode 100755 index 0000000..a909290 --- /dev/null +++ b/scripts/rebase-build-check-gnu-linux.sh @@ -0,0 +1,81 @@ +#!/bin/bash +# -*- coding: utf-8 -*- +# Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> +# +# This program is free software: you can redistribute it and/or modify +# it under the terms of the GNU Affero General Public License as published by +# the Free Software Foundation, either version 3 of the License, or +# (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU Affero General Public License for more details. +# +# You should have received a copy of the GNU Affero General Public License +# along with this program. If not, see <https://www.gnu.org/licenses/>. + +die() +{ + echo "$@" + exit 1; +} + +usage() +{ + printf "Usage:\n" + printf "%s build-from <base-commit-ref> " "$0" + printf "# Build all commits since <base-commit-ref>\n" "%0" + printf "%s continue " "$0" + printf "# Continue rebasing and building commits\n" "%0" + exit 64; # EX_USAGE from sysexits.h +} + +print_header() +{ + message="$1" + + len=$(expr $(echo -n ${message} | wc -c) + 2) + + nr_chars=$(expr $(expr 80 - ${len}) / 2) + + i="${nr_chars}" + while [ ${i} -gt 0 ] ; do + echo -n "#" + i="$(expr ${i} - 1)" + done + + echo -n " ${message} " + + i="${nr_chars}" + while [ ${i} -gt 0 ] ; do + echo -n "#" + i="$(expr ${i} - 1)" + done + echo +} + +build_and_git_rebase_continue() +{ + commits="$1" + commit=1 + + while true ; do + print_header "[ ${commit} of ${commits} ]" + guix build --file=scripts/guix.scm || die "guix build failed" + commit="$(expr ${commit} + 1)" + git rebase --continue || break + done +} + +if [ $# -eq 2 ] && [ "$1" == "build-from" ] ; then + base_commit="$2" + nr_commits="$(git log --oneline ${base_commit}~1..HEAD --oneline | wc -l)" + GIT_EDITOR="sed 's#^pick #edit #g' -i " git rebase -i "${base_commit}" + build_and_git_rebase_continue "${nr_commits}" +elif [ $# -eq 1 ] && [ "$1" == "continue" ] ; then + nr_commits="$(git log --oneline REBASE_HEAD~1..ORIG_HEAD --oneline | wc -l)" + build_and_git_rebase_continue "${nr_commits}" +else + usage +fi diff --git a/strict-cflags.sh b/strict-cflags.sh new file mode 100755 index 0000000..55380f3 --- /dev/null +++ b/strict-cflags.sh @@ -0,0 +1,35 @@ +#!/bin/sh +# +# This file is part of libsamsung-ipc. +# +# Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> +# +# libsamsung-ipc is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# libsamsung-ipc is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + +strict_cflags="\ + -W \ + -Wall \ + -Werror \ + -Werror=address \ + -Werror=return-type \ + -Werror=sequence-point \ + -Winit-self \ + -Wno-unused \ + -Wpedantic \ + -Wpointer-arith \ + -Wunused \ + -Wunused-function \ +" + +echo ${strict_cflags} diff --git a/tools/Makefile.am b/tools/Makefile.am index 4d5fa8b..024df50 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -1,11 +1,19 @@ NULL = +EXTRA_DIST = $(NULL) AM_CFLAGS = \ -I$(top_srcdir)/include \ + $(LIBCURL_CFLAGS) \ $(NULL) +AM_LDFLAGS = $(ALL_STATIC_LDFLAGS) + +if WANT_STRICT_CFLAGS +AM_CFLAGS += $(STRICT_CFLAGS) +endif + bin_PROGRAMS = \ - ipc-modem \ + https-send-sms \ ipc-test \ nv_data-imei \ nv_data-md5 \ @@ -13,23 +21,24 @@ bin_PROGRAMS = \ # TODO: Find a way to make test more modular and represent each run of the # nv_data-imei in TEST while having it implemented in a single python file -PY_LOG_COMPILER = $(PYTHON) +if WANT_VALGRIND_CHECKING +AM_TESTS_ENVIRONMENT = VALGRIND='$(VALGRIND)'; export VALGRIND; +endif +PY_LOG_COMPILER = $(PYTHON3) TEST_EXTENSIONS = .py -TESTS = nv_data-imei.py \ - nv_data-md5.py +TESTS = \ + tests/nv_data-imei.py \ + tests/nv_data-md5.py +EXTRA_DIST += $(TESTS) -ipc_modem_SOURCES = ipc-modem.c -ipc_modem_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la -ipc_modem_LDFLAGS = +https_send_sms_SOURCES = https-send-sms.c +https_send_sms_LDADD = $(LIBCURL_LIBS) ipc_test_SOURCES = ipc-test.c ipc_test_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la -ipc_test_LDFLAGS = nv_data_md5_SOURCES = nv_data-md5.c nv_data_md5_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la -nv_data_md5_LDFLAGS = -nv_data_imei_SOURCES = nv_data-imei.c +nv_data_imei_SOURCES = nv_data-imei.c nv_data-imei.h nv_data_imei_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la -nv_data_imei_LDFLAGS = diff --git a/tools/https-send-sms.c b/tools/https-send-sms.c new file mode 100644 index 0000000..80ad00b --- /dev/null +++ b/tools/https-send-sms.c @@ -0,0 +1,205 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ +#include <assert.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> +#include <sysexits.h> + +#include <curl/curl.h> + +/* CURL documentation for curl_easy_escape[1] mentions that "This + * function does not accept input strings longer than + * CURL_MAX_INPUT_LENGTH (8 MB)." but CURL_MAX_INPUT_LENGTH is not + * exported in the curl public headers (in /usr/include/curl). + */ +#define CURL_MAX_INPUT_LENGTH 8000000 + +long send_https(CURL *hnd, char *url, __attribute__((unused)) char *post_data) +{ + CURLcode ret; + long return_code; + + curl_easy_setopt(hnd, CURLOPT_BUFFERSIZE, 102400L); + curl_easy_setopt(hnd, CURLOPT_URL, url); + curl_easy_setopt(hnd, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(hnd, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(hnd, CURLOPT_HTTP_VERSION, + (long)CURL_HTTP_VERSION_2TLS); + curl_easy_setopt(hnd, CURLOPT_FTP_SKIP_PASV_IP, 1L); + curl_easy_setopt(hnd, CURLOPT_TCP_KEEPALIVE, 1L); + + ret = curl_easy_perform(hnd); + assert(ret == CURLE_OK); + + curl_easy_getinfo(hnd, CURLINFO_RESPONSE_CODE, &return_code); + + return return_code; +} + +int create_parameter(CURL *hnd, + char **out, const char *parameter, const char *value) +{ + char *result = NULL; + char *encoded_value; + size_t size = 0; + size_t rc; + + assert(strlen(value) < CURL_MAX_INPUT_LENGTH); + encoded_value = curl_easy_escape(hnd, value, 0); + assert(encoded_value != NULL); + + rc = snprintf(result, size, "%s=%s", parameter, encoded_value); + + assert(rc > 0); + size = rc; + + result = malloc(size + 1); + if (result == NULL) { + rc = -errno; + printf("%s: error %zd: %s\n", __func__, rc, strerror(rc)); + return rc; + } + + rc = snprintf(result, size + 1, "%s=%s", parameter, encoded_value); + assert(rc == size); + + assert(rc < CURL_MAX_INPUT_LENGTH); + + *out = result; + + curl_free(encoded_value); + + return 0; +} + +int send_sms_get(const char *username, const char *password, + const char *message) +{ + CURL *hnd; + char *parameter = NULL; + int rc; + CURLU *url; + char *url_string; + + url = curl_url(); + hnd = curl_easy_init(); + + rc = curl_url_set(url, CURLUPART_URL, + "https://smsapi.free-mobile.fr/sendmsg", 0); + assert(rc == 0); + + rc = create_parameter(hnd, ¶meter, "user", username); + assert(rc == 0); + rc = curl_url_set(url, CURLUPART_QUERY, parameter, CURLU_APPENDQUERY); + assert(rc == 0); + free(parameter); + + rc = create_parameter(hnd, ¶meter, "pass", password); + rc = curl_url_set(url, CURLUPART_QUERY, parameter, CURLU_APPENDQUERY); + assert(rc == 0); + free(parameter); + + rc = create_parameter(hnd, ¶meter, "msg", message); + rc = curl_url_set(url, CURLUPART_QUERY, parameter, CURLU_APPENDQUERY); + assert(rc == 0); + free(parameter); + + rc = curl_url_get(url, CURLUPART_URL, &url_string, 0); + assert(rc == 0); + + rc = send_https(hnd, url_string, NULL); + + switch (rc) { + case 200: + /* SMS SENT */ + rc = 0; + break; + case 400: + printf("Error %d: %s\n", + rc, + "Missing parameter (user, login, message)."); + rc = EX_USAGE; + break; + case 402: + printf("Error %d: %s\n", + rc, + "Too many SMS sent in too little time: Retry later.\n"); + rc = EX_TEMPFAIL; + break; + case 403: + printf("Error %d: %s\n", + rc, + "Possible causes:\n" + "- Service is not enabled in your account settings.\n" + "- Wrong login or password.\n"); + rc = EX_CONFIG; + break; + case 500: + printf("Error %d: %s\n", + rc, + "Service unavailable: Retry later"); + rc = EX_UNAVAILABLE; + break; + default: + printf("Unknown error %d.\n", rc); + rc = EX_PROTOCOL; + break; + } + + curl_easy_cleanup(hnd); + curl_url_cleanup(url); + + return rc; +} + +void usage(char *progname) +{ + printf("Usage: %s free-mobile <username> <token> <message>\n\n", + progname); + printf("Example:\n\t%s %s \"%s\" \"%s\" \"%s\"\n", + progname, + "free-mobile", + "12345678", + "1234abcdEFGH", + "hello world!"); +} + +int main(int argc, char *argv[]) +{ + char *message; + char *password; + char *username; + int rc; + + if (argc != 5 || strncmp("free-mobile", argv[1], + strlen("free-mobile"))) { + usage(argv[0]); + return EX_USAGE; + } + + username = argv[2]; + password = argv[3]; + message = argv[4]; + + rc = send_sms_get(username, password, message); + if (rc == 0) + printf("OK\n"); + return rc; +} diff --git a/tools/ipc-modem.c b/tools/ipc-modem.c deleted file mode 100644 index cc53749..0000000 --- a/tools/ipc-modem.c +++ /dev/null @@ -1,607 +0,0 @@ -/* - * This file is part of libsamsung-ipc. - * - * Copyright (C) 2011 Simon Busch <morphis@gravedo.de> - * Copyright (C) 2011 Paul Kocialkowsk <contact@paulk.fr> - * - * libsamsung-ipc is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 2 of the License, or - * (at your option) any later version. - * - * libsamsung-ipc is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. - */ - -#include <assert.h> -#include <fcntl.h> -#include <getopt.h> -#include <pthread.h> -#include <stdbool.h> -#include <stdint.h> -#include <stdio.h> -#include <stdlib.h> -#include <termios.h> -#include <unistd.h> -#include <string.h> - -#include <sys/ioctl.h> -#include <sys/stat.h> -#include <sys/types.h> - -#include <samsung-ipc.h> - -#define MODEM_STATE_LPM 0 -#define MODEM_STATE_NORMAL 2 -#define MODEM_STATE_SIM_OK 4 - -int state = MODEM_STATE_LPM; -int seq; -int in_call; -int out_call; -int call_done; - -char call_number[14]; -char sim_pin[8]; - -int seq_get(void) -{ - if (seq == 0xff) - seq = 0x00; - - seq++; - - return seq; -} - -void modem_snd_no_mic_mute(struct ipc_client *client) -{ - uint8_t data = 0; - - ipc_client_send(client, seq_get(), IPC_SND_MIC_MUTE_CTRL, IPC_TYPE_SET, - (void *) &data, 1); -} - -void modem_snd_clock_ctrl(struct ipc_client *client) -{ - uint8_t data = 0x01; - - ipc_client_send(client, seq_get(), IPC_SND_CLOCK_CTRL, IPC_TYPE_EXEC, - (void *) &data, 1); -} - -void modem_snd_spkr_volume_ctrl(struct ipc_client *client) -{ - uint16_t data = 0x0411; - - ipc_client_send(client, seq_get(), IPC_SND_SPKR_VOLUME_CTRL, - IPC_TYPE_SET, (void *) &data, 2); -} - -void modem_snd_audio_path_ctrl(struct ipc_client *client) -{ - uint8_t data = 0x01; - - ipc_client_send(client, seq_get(), IPC_SND_AUDIO_PATH_CTRL, - IPC_TYPE_SET, (void *) &data, 1); -} - - - -void modem_exec_call_out(struct ipc_client *client, char *num) -{ - struct ipc_call_outgoing_data call_out; - - modem_snd_no_mic_mute(client); - - memset(&call_out, 0, sizeof(struct ipc_call_outgoing_data)); - - call_out.type = IPC_CALL_TYPE_VOICE; - call_out.identity = IPC_CALL_IDENTITY_DEFAULT; - call_out.number_length = strlen(num); - /* TODO: Add support for prefixes */ - /* 0x21 = +33 */ - call_out.prefix = IPC_CALL_PREFIX_NONE; //0x21;//IPC_CALL_PREFIX_NONE; - memcpy(call_out.number, num, call_out.number_length); - - ipc_client_send(client, seq_get(), IPC_CALL_OUTGOING, IPC_TYPE_EXEC, - (void *) &call_out, - sizeof(struct ipc_call_outgoing_data)); - - out_call = 1; - - modem_snd_no_mic_mute(client); - modem_snd_spkr_volume_ctrl(client); - modem_snd_audio_path_ctrl(client); -} - -void modem_exec_call_answer(struct ipc_client *client) -{ - modem_snd_clock_ctrl(client); - - ipc_client_send(client, seq_get(), IPC_CALL_ANSWER, IPC_TYPE_EXEC, NULL, - 0); - - modem_snd_no_mic_mute(client); -} - -void modem_get_call_list(struct ipc_client *client) -{ - ipc_client_send(client, seq_get(), IPC_CALL_LIST, IPC_TYPE_GET, NULL, - 0); - - modem_snd_no_mic_mute(client); -} - -void modem_exec_power_normal(struct ipc_client *client) -{ - uint16_t data = 0x0202; - - ipc_client_send(client, seq_get(), IPC_PWR_PHONE_STATE, IPC_TYPE_EXEC, - (void *) &data, sizeof(data)); -} - -void modem_set_sms_device_ready(struct ipc_client *client) -{ - ipc_client_send(client, seq_get(), IPC_SMS_DEVICE_READY, IPC_TYPE_SET, - NULL, 0); -} - -void modem_set_sec_pin_status(struct ipc_client *client, char *pin1, char *pin2) -{ - struct ipc_sec_pin_status_request_data pin_status; - - printf("[I] Sending PIN1 unlock request\n"); - - ipc_sec_pin_status_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin1, - pin2); - - ipc_client_send(client, seq_get(), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, - (void *) &pin_status, sizeof(pin_status)); -} - -void modem_response_sec(struct ipc_client *client, struct ipc_message *resp) -{ - struct ipc_sec_pin_status_response_data *sim_status; - unsigned char type; - - switch (resp->command) { - case IPC_SEC_PIN_STATUS: - sim_status = - (struct ipc_sec_pin_status_response_data *)resp->data; - - switch (sim_status->status) { - case IPC_SEC_PIN_STATUS_CARD_NOT_PRESENT: - printf("[I] SIM card is definitely absent\n"); - break; - case IPC_SEC_PIN_STATUS_LOCK_SC: - switch (sim_status->facility_lock) { - case IPC_SEC_FACILITY_LOCK_TYPE_SC_PIN1_REQ: - printf("[I] " - "We need the PIN1 to unlock the card!" - "\n"); - if (strlen(sim_pin) > 0) { - modem_set_sec_pin_status(client, - sim_pin, NULL); - } else { - printf("[E] No SIM Pin, use --pin\n"); - } - break; - case IPC_SEC_FACILITY_LOCK_TYPE_SC_PUK_REQ: - printf("[I] Please provide the SIM card PUK!" - "\n"); - break; - case IPC_SEC_FACILITY_LOCK_TYPE_SC_CARD_BLOCKED: - printf("[I] Ouch, the SIM Card is blocked.\n"); - break; - } - break; - case IPC_SEC_PIN_STATUS_INIT_COMPLETE: - printf("[3] SIM init complete\n"); - if (state == MODEM_STATE_NORMAL) - state = MODEM_STATE_SIM_OK; - break; - case IPC_SEC_PIN_STATUS_PB_INIT_COMPLETE: - printf("[I] SIM Phone Book init complete\n"); - break; - } - break; - case IPC_SEC_SIM_ICC_TYPE: - type = *((char *) resp->data); - switch (type) { - case IPC_SEC_SIM_CARD_TYPE_UNKNOWN: - printf("[I] No SIM card type: unknown (absent?)\n"); - break; - case IPC_SEC_SIM_CARD_TYPE_SIM: - case IPC_SEC_SIM_CARD_TYPE_USIM: - printf("[I] SIM card found\n"); - break; - } - break; - } -} - -void modem_response_sms(struct ipc_client *client, struct ipc_message *resp) -{ - switch (resp->command) { - case IPC_SMS_DEVICE_READY: - if (state == MODEM_STATE_LPM) { - printf("[4] " - "Modem is ready, requesting normal power mode" - "\n"); - modem_exec_power_normal(client); - } else if (state == MODEM_STATE_SIM_OK) { - printf("[5] Modem is fully ready\n"); - modem_set_sms_device_ready(client); - } - break; - } -} - -void modem_response_call(struct ipc_client *client, struct ipc_message *resp) -{ - struct ipc_call_status_data *stat; - - switch (resp->command) { - case IPC_CALL_LIST: - /* - * if (in_call) - * modem_exec_call_answer(client); - * if (out_call) - * modem_snd_no_mic_mute(client); - */ - break; - case IPC_CALL_INCOMING: - printf("[I] Got an incoming call!\n"); - in_call = 1; - modem_get_call_list(client); - break; - case IPC_CALL_STATUS: - stat = (struct ipc_call_status_data *)resp->data; - - if (stat->status == IPC_CALL_STATUS_DIALING) { - printf("[I] Sending clock ctrl and restore alsa\n"); - modem_snd_clock_ctrl(client); - /* - * system("alsa_ctl -f /data/alsa_state_modem restore"); - */ - - printf("[I] CALL STATUS DIALING!!!\n"); - - modem_snd_spkr_volume_ctrl(client); - modem_snd_audio_path_ctrl(client); - - modem_get_call_list(client); - } - - if (stat->status == IPC_CALL_STATUS_CONNECTED) { - printf("[I] CALL STATUS CONNECTED!!!\n"); - modem_snd_no_mic_mute(client); - } - - if (stat->status == IPC_CALL_STATUS_RELEASED) { - printf("[I] CALL STATUS RELEASED!!!\n"); - modem_snd_no_mic_mute(client); - } - break; - } -} - -void modem_response_pwr(__attribute__((unused)) struct ipc_client *client, - struct ipc_message *resp) -{ - int state_n; - - switch (resp->command) { - case IPC_PWR_PHONE_PWR_UP: - printf("[2] Phone is powered up (LPM)!\n"); - state = MODEM_STATE_LPM; - break; - - case IPC_PWR_PHONE_STATE: - state_n = *((int *)resp->data); -#if 0 - switch (state_n) { - /* FIXME: Broken */ - case IPC_PWR_PHONE_STATE_NORMAL: - printf("Power state is now: NORMAL\n"); - break; - case IPC_PWR_PHONE_STATE_LPM: - printf("Power state is now: LPM (Low Power Mode)?\n"); - break; - } -#endif - state = state_n; - break; - - } -} - -void modem_response_net(__attribute__((unused)) struct ipc_client *client, - struct ipc_message *resp) -{ - struct ipc_net_regist_response_data *regi; - char mnc[6]; - - switch (resp->command) { - case IPC_NET_REGIST: - regi = (struct ipc_net_regist_response_data *) resp->data; - if (regi->status == IPC_NET_REGISTRATION_STATUS_HOME) - printf("[I] Registered with network successfully!\n"); - break; - case IPC_NET_SERVING_NETWORK: - memcpy(mnc, (char *)((char *) resp->data + 3), 5); - mnc[5] = 0; - printf("[6] Registered with network! " - "Got PLMN (Mobile Network Code): '%s'\n", - mnc); - if (call_done == 0) { - printf("Requesting outgoing call to %s!\n", - call_number); - modem_exec_call_out(client, call_number); - } - call_done = 1; - break; - } -} - -void modem_response_handle(struct ipc_client *client, struct ipc_message *resp) -{ - switch (IPC_GROUP(resp->command)) { - case IPC_GROUP_NET: - modem_response_net(client, resp); - break; - case IPC_GROUP_PWR: - modem_response_pwr(client, resp); - break; - case IPC_GROUP_SEC: - modem_response_sec(client, resp); - break; - case IPC_GROUP_SMS: - modem_response_sms(client, resp); - break; - case IPC_GROUP_CALL: - modem_response_call(client, resp); - break; - case IPC_GROUP_DISP: - if (in_call) - modem_snd_no_mic_mute(client); - break; - } -} - - -int modem_read_loop(struct ipc_client *client) -{ - struct ipc_message resp; - int rc; - - memset(&resp, 0, sizeof(resp)); - - while (1) { - usleep(3000); - - rc = ipc_client_poll(client, NULL, NULL); - if (rc < 0) - continue; - - rc = ipc_client_recv(client, &resp); - if (rc < 0) { - printf("[E] " - "Can't RECV from modem: please run this again" - "\n"); - break; - } - - modem_response_handle(client, &resp); - - if (resp.data != NULL) - free(resp.data); - } - - return 0; -} - -void modem_log_handler(__attribute__((unused)) void *user_data, - const char *msg) -{ - int i, l; - char *message; - - message = strdup(msg); - l = strlen(message); - - if (l > 1) { - for (i = l ; i > 0 ; i--) { - if (message[i] == '\n') - message[i] = 0; - else if (message[i] != 0) - break; - } - - printf("[D] %s\n", message); - } - - free(message); -} - -void modem_log_handler_quiet(__attribute__((unused)) void *user_data, - __attribute__((unused)) const char *msg) -{ -} - -int modem_start(struct ipc_client *client) -{ - int rc = -1; - - ipc_client_data_create(client); - rc = ipc_client_boot(client); - if (rc < 0) - return -1; - - usleep(300); - - rc = ipc_client_open(client); - if (rc < 0) - return -1; - - rc = ipc_client_power_on(client); - if (rc < 0) - return -1; - - return 0; -} - -int modem_stop(struct ipc_client *client) -{ - ipc_client_power_off(client); - ipc_client_close(client); - - return 0; -} - -void print_help(void) -{ - printf("usage: ipc-modem <command>\n"); - printf("commands:\n"); - printf("\tstart boot modem and start read loop\n"); - printf("\tboot boot modem only\n"); - printf("\tpower-on power on the modem\n"); - printf("\tpower-off power off the modem\n"); - printf("arguments:\n"); - printf("\t--debug enable debug messages\n"); - printf("\t--pin=[PIN] provide SIM card PIN\n"); - printf("\t--call=[NUMBER] call NUMBER\n"); -} - -int main(int argc, char *argv[]) -{ - struct ipc_client *client_fmt; - int c = 0; - int opt_i = 0; - int rc = -1; - int debug = 0; - - struct option opt_l[] = { - {"help", no_argument, 0, 0 }, - {"debug", no_argument, 0, 0 }, - {"pin", required_argument, 0, 0 }, - {"call", required_argument, 0, 0 }, - {0, 0, 0, 0 } - }; - - if (argc < 2) { - print_help(); - exit(1); - } - - while (c >= 0) { - c = getopt_long(argc, argv, "", opt_l, &opt_i); - if (c < 0) - break; - - switch (c) { - case 0: - if (strncmp(opt_l[opt_i].name, "help", 4) == 0) { - print_help(); - exit(1); - } else if (strcmp(opt_l[opt_i].name, "debug") == 0) { - debug = 1; - printf("[I] Debug enabled\n"); - } else if ((strcmp(opt_l[opt_i].name, "pin") == 0) && - (optarg)) { - if (strlen(optarg) < 8) { - assert(strlen(optarg) < - sizeof(sim_pin)); - - printf("[I] Got SIM PIN!\n"); - strcpy(sim_pin, optarg); - } else { - printf("[E] SIM PIN is too long!\n"); - return 1; - } - } else if (strcmp(opt_l[opt_i].name, "call") == 0) { - if (optarg) { - if (strlen(optarg) < 14) { - assert(strlen(optarg) < - sizeof(call_number)); - printf("[I] " - "Got call number!\n"); - strcpy(call_number, optarg); - } else { - printf("[E] " - "Call number is too long!" - "\n"); - return 1; - } - } - } - - break; - } - } - - client_fmt = ipc_client_create(IPC_CLIENT_TYPE_FMT); - - if (client_fmt == 0) { - printf("[E] Could not create IPC client; aborting ...\n"); - goto modem_quit; - } - - if (debug == 0) { - ipc_client_log_callback_register(client_fmt, - modem_log_handler_quiet, NULL); - } else { - ipc_client_log_callback_register(client_fmt, modem_log_handler, - NULL); - } - - while (optind < argc) { - if (strncmp(argv[optind], "power-on", 8) == 0) { - if (ipc_client_power_on(client_fmt) < 0) - printf("[E] Something went wrong " - "while powering modem on\n"); - goto modem_quit; - } else if (strncmp(argv[optind], "power-off", 9) == 0) { - if (ipc_client_power_off(client_fmt) < 0) - printf("[E] Something went wrong " - "while powering modem off\n"); - goto modem_quit; - } else if (strncmp(argv[optind], "boot", 9) == 0) { - rc = ipc_client_boot(client_fmt); - if (rc < 0) - printf("[E] Something went wrong " - "while bootstrapping modem\n"); - } else if (strncmp(argv[optind], "start", 5) == 0) { - printf("[0] Starting modem on FMT client\n"); - rc = modem_start(client_fmt); - if (rc < 0) { - printf("[E] Something went wrong\n"); - modem_stop(client_fmt); - return 1; - } - - printf("[1] Starting modem_read_loop on FMT client\n"); - modem_read_loop(client_fmt); - - modem_stop(client_fmt); - } else { - printf("[E] Unknown argument: '%s'\n", argv[optind]); - print_help(); - return 1; - } - - optind++; - } - -modem_quit: - if (client_fmt != 0) - ipc_client_destroy(client_fmt); - - return 0; -} diff --git a/tools/ipc-modem/Makefile.am b/tools/ipc-modem/Makefile.am new file mode 100644 index 0000000..64cde49 --- /dev/null +++ b/tools/ipc-modem/Makefile.am @@ -0,0 +1,28 @@ +NULL = +EXTRA_DIST = $(NULL) + +AM_CFLAGS = \ + -I$(top_srcdir)/include \ + $(NULL) + +if WANT_STRICT_CFLAGS +AM_CFLAGS += $(STRICT_CFLAGS) +endif + +bin_PROGRAMS = ipc-modem + +# TODO: Find a way to make test more modular and represent each run of the +# ipc-modem in TEST while having it implemented in a single python file +PY_LOG_COMPILER = $(PYTHON3) +TEST_EXTENSIONS = .py +TESTS = tests/ipc-modem.py +EXTRA_DIST += $(TESTS) + +ipc_modem_SOURCES = \ +ipc-modem.c \ +ipc-modem.h \ +ipc-modem-log.c \ +ipc-modem-log.h + +ipc_modem_LDADD = $(top_builddir)/samsung-ipc/libsamsung-ipc.la +ipc_modem_LDFLAGS = -lpthread $(ALL_STATIC_LDFLAGS) diff --git a/tools/ipc-modem/ipc-modem-log.c b/tools/ipc-modem/ipc-modem-log.c new file mode 100644 index 0000000..7e6b48d --- /dev/null +++ b/tools/ipc-modem/ipc-modem-log.c @@ -0,0 +1,84 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2011 Simon Busch <morphis@gravedo.de> + * Copyright (C) 2011 Paul Kocialkowsk <contact@paulk.fr> + * Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdarg.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> +#include <syslog.h> + +#include "ipc-modem-log.h" + +static enum log_target log_target; + +void modem_log_handler(void *user_data, const char *msg) +{ + int i, l; + char *message; + + message = strdup(msg); + l = strlen(message); + + if (l > 1) { + for (i = l ; i > 0 ; i--) { + if (message[i] == '\n') + message[i] = 0; + else if (message[i] != 0) + break; + } + + if (log_target == LOG_TO_STDOUT && user_data) + printf("[%s] %s\n", (char *)user_data, message); + else if (log_target == LOG_TO_STDOUT) + printf("[%s] %s\n", MODEM_LOG_DEBUG, message); + else if (log_target == LOG_TO_SYSLOG && user_data) + syslog(LOG_INFO, + "[%s] %s\n", (char *)user_data, message); + else if (log_target == LOG_TO_SYSLOG) + syslog(LOG_INFO, "[%s] %s\n", MODEM_LOG_DEBUG, message); + } + + free(message); +} + +void modem_log_handler_quiet(__attribute__((unused)) void *user_data, + __attribute__((unused)) const char *msg) +{ +} + +void ipc_modem_log(__attribute__((unused)) struct ipc_client *client, + char *prefix, const char *message, ...) +{ + va_list args; + char buffer[4096]; + + va_start(args, message); + vsnprintf((char *) &buffer, sizeof(buffer), message, args); + va_end(args); + + modem_log_handler(prefix, buffer); +} + +void ipc_modem_set_log_target(enum log_target target) +{ + log_target = target; +} + diff --git a/tools/ipc-modem/ipc-modem-log.h b/tools/ipc-modem/ipc-modem-log.h new file mode 100644 index 0000000..1786295 --- /dev/null +++ b/tools/ipc-modem/ipc-modem-log.h @@ -0,0 +1,41 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef IPC_MODEM_LOG_H +#define IPC_MODEM_LOG_H + +#include <stdarg.h> + +#include <samsung-ipc.h> + +#define MODEM_LOG_ERROR "E" +#define MODEM_LOG_INFO "I" +#define MODEM_LOG_DEBUG "D" + +enum log_target { + LOG_TO_STDOUT, + LOG_TO_SYSLOG, +}; + +void ipc_modem_log(struct ipc_client *client, + char *prefix, const char *message, ...); +void modem_log_handler(void *user_data, const char *msg); +void modem_log_handler_quiet(void *user_data, const char *msg); +void ipc_modem_set_log_target(enum log_target target); + +#endif /* IPC_MODEM_LOG_H */ diff --git a/tools/ipc-modem/ipc-modem.c b/tools/ipc-modem/ipc-modem.c new file mode 100644 index 0000000..c70bcc1 --- /dev/null +++ b/tools/ipc-modem/ipc-modem.c @@ -0,0 +1,781 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2011 Simon Busch <morphis@gravedo.de> + * Copyright (C) 2011 Paul Kocialkowsk <contact@paulk.fr> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <assert.h> +#include <fcntl.h> +#include <getopt.h> +#include <pthread.h> +#include <stdbool.h> +#include <stdint.h> +#include <stdio.h> +#include <stdlib.h> +#include <strings.h> +#include <sysexits.h> +#include <termios.h> +#include <unistd.h> +#include <string.h> + +#include <sys/ioctl.h> +#include <sys/stat.h> +#include <sys/types.h> + +#include <samsung-ipc.h> + +#include "ipc-modem.h" +#include "ipc-modem-log.h" + +int seq_get(struct ipc_modem_data *data) +{ + if (data->seq == 0xff) + data->seq = 0x00; + + data->seq++; + + return data->seq; +} + +void modem_snd_no_mic_mute(struct ipc_modem_data *data) +{ + uint8_t mic_mute_data = 0; + + ipc_client_send(data->client, + seq_get(data), IPC_SND_MIC_MUTE_CTRL, IPC_TYPE_SET, + (void *) &mic_mute_data, 1); +} + +void modem_snd_clock_ctrl(struct ipc_modem_data *data) +{ + uint8_t clock_ctrl_data = 0x01; + + ipc_client_send(data->client, + seq_get(data), IPC_SND_CLOCK_CTRL, IPC_TYPE_EXEC, + (void *) &clock_ctrl_data, 1); +} + +void modem_snd_spkr_volume_ctrl(struct ipc_modem_data *data) +{ + uint16_t spkr_volume_data = 0x0411; + + ipc_client_send(data->client, seq_get(data), IPC_SND_SPKR_VOLUME_CTRL, + IPC_TYPE_SET, (void *) &spkr_volume_data, 2); +} + +void modem_snd_audio_path_ctrl(struct ipc_modem_data *data) +{ + uint8_t audio_path_ctrl_data = 0x01; + + ipc_client_send(data->client, seq_get(data), IPC_SND_AUDIO_PATH_CTRL, + IPC_TYPE_SET, (void *) &audio_path_ctrl_data, 1); +} + + + +void modem_exec_call_out(struct ipc_modem_data *data, char *num) +{ + struct ipc_call_outgoing_data call_out; + + modem_snd_no_mic_mute(data); + + memset(&call_out, 0, sizeof(struct ipc_call_outgoing_data)); + + call_out.type = IPC_CALL_TYPE_VOICE; + call_out.identity = IPC_CALL_IDENTITY_DEFAULT; + call_out.number_length = strlen(num); + /* TODO: Add support for prefixes */ + /* 0x21 = +33 */ + call_out.prefix = IPC_CALL_PREFIX_NONE; //0x21;//IPC_CALL_PREFIX_NONE; + memcpy(call_out.number, num, call_out.number_length); + + ipc_client_send(data->client, + seq_get(data), IPC_CALL_OUTGOING, IPC_TYPE_EXEC, + (void *) &call_out, + sizeof(struct ipc_call_outgoing_data)); + + data->out_call = 1; + + modem_snd_no_mic_mute(data); + modem_snd_spkr_volume_ctrl(data); + modem_snd_audio_path_ctrl(data); +} + +void modem_exec_call_answer(struct ipc_modem_data *data) +{ + modem_snd_clock_ctrl(data); + + ipc_client_send(data->client, + seq_get(data), IPC_CALL_ANSWER, IPC_TYPE_EXEC, NULL, 0); + + modem_snd_no_mic_mute(data); +} + +void modem_get_call_list(struct ipc_modem_data *data) +{ + ipc_client_send(data->client, + seq_get(data), IPC_CALL_LIST, IPC_TYPE_GET, NULL, 0); + + modem_snd_no_mic_mute(data); +} + +void modem_exec_power_normal(struct ipc_modem_data *data) +{ + uint16_t exec_data = IPC_PWR_PHONE_STATE_REQUEST_NORMAL; + + ipc_client_send(data->client, + seq_get(data), IPC_PWR_PHONE_STATE, IPC_TYPE_EXEC, + (void *) &exec_data, sizeof(data)); +} + +void modem_set_sms_device_ready(struct ipc_modem_data *data) +{ + ipc_client_send(data->client, + seq_get(data), IPC_SMS_DEVICE_READY, IPC_TYPE_SET, + NULL, 0); +} + +void modem_set_sec_pin_status(struct ipc_modem_data *data, + char *pin1, char *pin2) +{ + struct ipc_sec_pin_status_request_data pin_status; + + ipc_modem_log(data->client, + MODEM_LOG_INFO, "Sending PIN1 unlock request\n"); + + ipc_sec_pin_status_setup(&pin_status, IPC_SEC_PIN_TYPE_PIN1, pin1, + pin2); + + ipc_client_send(data->client, + seq_get(data), IPC_SEC_PIN_STATUS, IPC_TYPE_SET, + (void *) &pin_status, sizeof(pin_status)); +} + +void modem_response_sec(struct ipc_modem_data *data, struct ipc_message *resp) +{ + struct ipc_sec_pin_status_response_data *sim_status; + unsigned char type; + + switch (resp->command) { + case IPC_SEC_PIN_STATUS: + sim_status = + (struct ipc_sec_pin_status_response_data *)resp->data; + + switch (sim_status->status) { + case IPC_SEC_PIN_STATUS_CARD_NOT_PRESENT: + ipc_modem_log(data->client, MODEM_LOG_INFO, + "SIM card is definitely absent\n"); + break; + case IPC_SEC_PIN_STATUS_LOCK_SC: + switch (sim_status->facility_lock) { + case IPC_SEC_FACILITY_LOCK_TYPE_SC_PIN1_REQ: + ipc_modem_log( + data->client, + MODEM_LOG_INFO, + "We need the PIN1 to unlock the card!" + "\n"); + if (strlen(data->sim_pin) > 0) { + modem_set_sec_pin_status(data, + data->sim_pin, + NULL); + } else { + ipc_modem_log( + data->client, + MODEM_LOG_ERROR, + "No SIM Pin, use --pin\n"); + } + break; + case IPC_SEC_FACILITY_LOCK_TYPE_SC_PUK_REQ: + ipc_modem_log( + data->client, + MODEM_LOG_INFO, + "Please provide the SIM card PUK!" + "\n"); + break; + case IPC_SEC_FACILITY_LOCK_TYPE_SC_CARD_BLOCKED: + ipc_modem_log( + data->client, + MODEM_LOG_INFO, + "Ouch, the SIM Card is blocked.\n"); + break; + } + break; + case IPC_SEC_PIN_STATUS_INIT_COMPLETE: + ipc_modem_log(data->client, "3", "SIM init complete\n"); + if (data->state == MODEM_STATE_NORMAL) + data->state = MODEM_STATE_SIM_OK; + break; + case IPC_SEC_PIN_STATUS_PB_INIT_COMPLETE: + ipc_modem_log(data->client, + MODEM_LOG_INFO, + "SIM Phone Book init complete\n"); + break; + } + break; + case IPC_SEC_SIM_ICC_TYPE: + type = *((char *) resp->data); + switch (type) { + case IPC_SEC_SIM_CARD_TYPE_UNKNOWN: + ipc_modem_log( + data->client, + MODEM_LOG_INFO, + "No SIM card type: unknown (absent?)\n"); + break; + case IPC_SEC_SIM_CARD_TYPE_SIM: + case IPC_SEC_SIM_CARD_TYPE_USIM: + ipc_modem_log(data->client, + MODEM_LOG_INFO, "SIM card found\n"); + break; + } + break; + } +} + +void modem_response_sms(struct ipc_modem_data *data, struct ipc_message *resp) +{ + switch (resp->command) { + case IPC_SMS_DEVICE_READY: + if (data->state == MODEM_STATE_LPM) { + ipc_modem_log( + data->client, + "4", + "Modem is ready, requesting normal power mode" + "\n"); + modem_exec_power_normal(data); + } else if (data->state == MODEM_STATE_SIM_OK) { + ipc_modem_log(data->client, + "5", "Modem is fully ready\n"); + modem_set_sms_device_ready(data); + } + break; + } +} + +void modem_response_call(struct ipc_modem_data *data, struct ipc_message *resp) +{ + struct ipc_call_status_data *stat; + + switch (resp->command) { + case IPC_CALL_LIST: + /* + * if (data->in_call) + * modem_exec_call_answer(data->client); + * if (data->out_call) + * modem_snd_no_mic_mute(data); + */ + break; + case IPC_CALL_INCOMING: + ipc_modem_log(data->client, + MODEM_LOG_INFO, "Got an incoming call!\n"); + data->in_call = 1; + modem_get_call_list(data); + break; + case IPC_CALL_STATUS: + stat = (struct ipc_call_status_data *)resp->data; + + if (stat->status == IPC_CALL_STATUS_DIALING) { + ipc_modem_log( + data->client, + MODEM_LOG_INFO, + "Sending clock ctrl and restore alsa\n"); + modem_snd_clock_ctrl(data); + /* + * system("alsa_ctl -f /data/alsa_state_modem restore"); + */ + + ipc_modem_log(data->client, + MODEM_LOG_INFO, + "CALL STATUS DIALING!!!\n"); + + modem_snd_spkr_volume_ctrl(data); + modem_snd_audio_path_ctrl(data); + + modem_get_call_list(data); + } + + if (stat->status == IPC_CALL_STATUS_CONNECTED) { + ipc_modem_log(data->client, + MODEM_LOG_INFO, + "CALL STATUS CONNECTED!!!\n"); + modem_snd_no_mic_mute(data); + } + + if (stat->status == IPC_CALL_STATUS_RELEASED) { + ipc_modem_log(data->client, + MODEM_LOG_INFO, + "CALL STATUS RELEASED!!!\n"); + modem_snd_no_mic_mute(data); + } + break; + } +} + +void modem_response_pwr(struct ipc_modem_data *data, struct ipc_message *resp) +{ + int state_n; + + switch (resp->command) { + case IPC_PWR_PHONE_PWR_UP: + ipc_modem_log(data->client, + "2", "Phone is powered up (LPM)!\n"); + data->state = MODEM_STATE_LPM; + break; + + case IPC_PWR_PHONE_STATE: + state_n = *((int *)resp->data); +#if 0 + switch (state_n) { + /* FIXME: Broken */ + case IPC_PWR_PHONE_STATE_NORMAL: + ipc_modem_log(data->client, + MODEM_LOG_INFO, + "Power state is now: NORMAL\n"); + break; + case IPC_PWR_PHONE_STATE_LPM: + ipc_modem_log( + data->client, + MODEM_LOG_INFO, + "Power state is now: LPM (Low Power Mode)?\n"); + break; + } +#endif + data->state = state_n; + break; + + } +} + +void modem_response_net(struct ipc_modem_data *data, + struct ipc_message *resp) +{ + struct ipc_net_regist_response_data *regi; + char mnc[6]; + + switch (resp->command) { + case IPC_NET_REGIST: + regi = (struct ipc_net_regist_response_data *) resp->data; + if (regi->status == IPC_NET_REGISTRATION_STATUS_HOME) + ipc_modem_log( + data->client, + MODEM_LOG_INFO, + "Registered with network successfully!\n"); + break; + case IPC_NET_SERVING_NETWORK: + memcpy(mnc, (char *)((char *) resp->data + 3), 5); + mnc[5] = 0; + ipc_modem_log(data->client, + "6", + "Registered with network! " + "Got PLMN (Mobile Network Code): '%s'\n", + mnc); + if (data->call_done == 0) { + ipc_modem_log(data->client, + MODEM_LOG_INFO, + "Requesting outgoing call to %s!\n", + data->call_number); + modem_exec_call_out(data, data->call_number); + } + data->call_done = 1; + break; + } +} + +void modem_response_handle(struct ipc_modem_data *data, + struct ipc_message *resp) +{ + switch (IPC_GROUP(resp->command)) { + case IPC_GROUP_NET: + modem_response_net(data, resp); + break; + case IPC_GROUP_PWR: + modem_response_pwr(data, resp); + break; + case IPC_GROUP_SEC: + modem_response_sec(data, resp); + break; + case IPC_GROUP_SMS: + modem_response_sms(data, resp); + break; + case IPC_GROUP_CALL: + modem_response_call(data, resp); + break; + case IPC_GROUP_DISP: + if (data->in_call) + modem_snd_no_mic_mute(data); + break; + } +} + + +int modem_read_loop(struct ipc_modem_data *data) +{ + struct ipc_message resp; + int rc; + + memset(&resp, 0, sizeof(resp)); + + while (1) { + usleep(3000); + + rc = ipc_client_poll(data->client, NULL, NULL); + if (rc < 0) + continue; + + rc = ipc_client_recv(data->client, &resp); + if (rc < 0) { + ipc_modem_log( + data->client, + MODEM_LOG_ERROR, + "Can't RECV from modem: please run this again" + "\n"); + break; + } + + modem_response_handle(data, &resp); + + if (resp.data != NULL) + free(resp.data); + } + + return 0; +} + +int modem_dummy_read_loop(__attribute__((unused)) struct ipc_client *client) +{ + while (true) { + ipc_modem_log(client, + MODEM_LOG_INFO, "%s: looping\n", __func__); + sleep(1); + } + + return 0; +} + +int modem_start(struct ipc_client *client) +{ + int rc = -1; + + ipc_client_data_create(client); + rc = ipc_client_boot(client); + if (rc < 0) + return -1; + + usleep(300); + + rc = ipc_client_open(client); + if (rc < 0) + return -1; + + rc = ipc_client_power_on(client); + if (rc < 0) + return -1; + + return 0; +} + +int modem_stop(struct ipc_client *client) +{ + ipc_client_power_off(client); + ipc_client_close(client); + + return 0; +} + +void print_help(void) +{ + printf("usage: ipc-modem <command>\n" + "commands:\n" + "\tboot boot modem only\n" + "\tpower-on power on the modem only\n" + "\tpower-off power off the modem only\n" + "\tstart " + "boot modem and start read loop\n" + "arguments:\n" + "\t--call=<NUMBER> call NUMBER\n" + "\t--debug enable debug messages\n" + "\t--dry-run " + "Test the ipc-modem program without talking to the modem.\n" + "\t--help print this help message\n" + "\t--log-target=[stdout|syslog] " + "direct logs to stdout or syslog\n" + "\t--pin=<PIN> provide SIM card PIN\n"); +} + +int handle_command(struct ipc_modem_data *data) +{ + int rc = 0; + + switch (data->command) { + case CMD_POWER_ON: + if (data->dry_run) + break; + + rc = ipc_client_power_on(data->client); + if (rc < 0) + ipc_modem_log(data->client, "[E]", + "[E] Something went wrong " + "while powering modem on\n"); + goto modem_quit; + case CMD_POWER_OFF: + if (data->dry_run) + break; + + rc = ipc_client_power_off(data->client); + if (rc < 0) + ipc_modem_log(data->client, + MODEM_LOG_ERROR, + "Something went wrong " + "while powering modem off\n"); + goto modem_quit; + case CMD_BOOT: + if (data->dry_run) + break; + + rc = ipc_client_boot(data->client); + if (rc < 0) + ipc_modem_log(data->client, + MODEM_LOG_ERROR, + "Something went wrong " + "while bootstrapping modem\n"); + break; + case CMD_START: + if (data->dry_run) { + ipc_modem_log( + data->client, + "1", + "Starting dummy modem_read_loop on %s client\n", + "FMT"); + modem_dummy_read_loop(data->client); + break; + } + + ipc_modem_log(data->client, + "0", "Starting modem on FMT client\n"); + + rc = modem_start(data->client); + if (rc < 0) { + ipc_modem_log(data->client, + MODEM_LOG_ERROR, + "Something went wrong\n"); + modem_stop(data->client); + return EX_UNAVAILABLE; + } + ipc_modem_log(data->client, + "1", + "Starting modem_read_loop on FMT client\n"); + modem_read_loop(data); + + modem_stop(data->client); + break; + default: + /* We should handle all commands */ + ipc_modem_log(data->client, + MODEM_LOG_ERROR, + "%s: Unknown command %d\n", __func__, + data->command); + + assert(false); + } + +modem_quit: + if (data->client != 0) + ipc_client_destroy(data->client); + + return rc; +} + +void print_cmdline_opts(struct ipc_modem_data *data) + +{ + if (data->debug) + ipc_modem_log(data->client, MODEM_LOG_INFO, "Debug enabled\n"); + if (data->debug && data->dry_run) + ipc_modem_log(data->client, MODEM_LOG_INFO, "dry-run mode\n"); +} + +int parse_cmdline_opts(struct ipc_modem_data *data, int argc, char *argv[]) +{ + int c = 0; + int opt_i = 0; + + struct option opt_l[] = { + {"call", required_argument, 0, 0 }, + {"debug", no_argument, 0, 0 }, + {"dry-run", no_argument, 0, 0 }, + {"help", no_argument, 0, 0 }, + {"log-target", required_argument, 0, 0 }, + {"pin", required_argument, 0, 0 }, + {0, 0, 0, 0 } + }; + + if (argc < 2) { + print_help(); + exit(EX_USAGE); + } + + /* Handle options arguments */ + while (true) { + c = getopt_long(argc, argv, "", opt_l, &opt_i); + if (c != 0) + break; + + if (strcmp(opt_l[opt_i].name, "call") == 0) { + if (optarg) { + if (strlen(optarg) == 0) { + ipc_modem_log(data->client, + MODEM_LOG_ERROR, + "Missing call number\n"); + return EX_USAGE; + } else if (strlen(optarg) < 14) { + assert(strlen(optarg) < + sizeof(data->call_number)); + ipc_modem_log(data->client, + MODEM_LOG_INFO, + "Got call number!\n"); + strcpy(data->call_number, optarg); + } else { + ipc_modem_log( + data->client, + MODEM_LOG_ERROR, + "Call number is too long!\n"); + return EX_USAGE; + } + } + } else if ((strcmp(opt_l[opt_i].name, "log-target") == 0)) { + if (optarg) { + if (!strcmp(optarg, "syslog")) { + ipc_modem_set_log_target(LOG_TO_SYSLOG); + } else if (strcmp(optarg, "stdout")) { + ipc_modem_log( + data->client, MODEM_LOG_ERROR, + "Invalid log target '%s'\n", + optarg); + return EX_USAGE; + } + } + } else if (strcmp(opt_l[opt_i].name, "debug") == 0) { + data->debug = true; + } else if (strcmp(opt_l[opt_i].name, "dry-run") == 0) { + data->dry_run = true; + } else if (strncmp(opt_l[opt_i].name, "help", 4) == 0) { + print_help(); + exit(0); + } else if ((strcmp(opt_l[opt_i].name, "pin") == 0) && + (optarg)) { + if (strlen(optarg) < 8) { + assert(strlen(optarg) < + sizeof(data->sim_pin)); + + ipc_modem_log( + data->client, + MODEM_LOG_INFO, "Got SIM PIN!\n"); + strcpy(data->sim_pin, optarg); + } else { + ipc_modem_log(data->client, + MODEM_LOG_ERROR, + "SIM PIN is too long!\n"); + return EX_USAGE; + } + } + } + + /* Handle non options arguments */ + while (optind < argc) { + if (strncmp(argv[optind], "boot", 9) == 0) { + data->command = CMD_BOOT; + break; + } else if (strncmp(argv[optind], "power-on", 8) == 0) { + data->command = CMD_POWER_ON; + break; + } else if (strncmp(argv[optind], "power-off", 9) == 0) { + data->command = CMD_POWER_OFF; + break; + } else if (strncmp(argv[optind], "start", 5) == 0) { + data->command = CMD_START; + break; + } else { + ipc_modem_log(data->client, + MODEM_LOG_ERROR, + "Unknown argument: '%s'\n", + argv[optind]); + print_help(); + return EX_USAGE; + } + + optind++; + } + + if (data->command == CMD_NONE) { + ipc_modem_log( + data->client, MODEM_LOG_ERROR, + "\n" + "Error: No command given. You need to use a command.\n" + " See the help below for more details.\n" + "\n"); + print_help(); + return EX_USAGE; + } + + return 0; +} + +int main(int argc, char *argv[]) +{ + struct ipc_modem_data data; + int ret; + + bzero((void *)&data, sizeof(data)); + + data.client = ipc_client_create(IPC_CLIENT_TYPE_DUMMY); + + ret = parse_cmdline_opts(&data, argc, argv); + if (ret) + return ret; + + if (!data.dry_run) { + ipc_client_destroy(data.client); + data.client = ipc_client_create(IPC_CLIENT_TYPE_FMT); + + if (data.client == 0) { + data.client = ipc_client_create(IPC_CLIENT_TYPE_DUMMY); + if (data.client) + ipc_modem_log( + data.client, + MODEM_LOG_ERROR, + "Could not create IPC client; " + "aborting ...\n"); + else + printf("Could not create IPC client; " + "aborting ...\n"); + + return EX_UNAVAILABLE; + } + } + + if (data.debug == 0) + ipc_client_log_callback_register(data.client, + modem_log_handler_quiet, + NULL); + else + ipc_client_log_callback_register(data.client, + modem_log_handler, + NULL); + + print_cmdline_opts(&data); + + return handle_command(&data); +} diff --git a/tools/ipc-modem/ipc-modem.h b/tools/ipc-modem/ipc-modem.h new file mode 100644 index 0000000..0ba2f8e --- /dev/null +++ b/tools/ipc-modem/ipc-modem.h @@ -0,0 +1,51 @@ +/* + * This file is part of libsamsung-ipc. + * + * Copyright (C) 2011 Simon Busch <morphis@gravedo.de> + * Copyright (C) 2011 Paul Kocialkowsk <contact@paulk.fr> + * Copyright (C) 2022 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> + * + * libsamsung-ipc is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 2 of the License, or + * (at your option) any later version. + * + * libsamsung-ipc is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + */ +#ifndef IPC_MODEM_H +#define IPC_MODEM_H + +#define MODEM_STATE_LPM 0 +#define MODEM_STATE_NORMAL 2 +#define MODEM_STATE_SIM_OK 4 + +enum command { + CMD_NONE, + CMD_START, + CMD_BOOT, + CMD_POWER_ON, + CMD_POWER_OFF, +}; + +struct ipc_modem_data { + struct ipc_client *client; + char call_number[14]; + char sim_pin[8]; + enum command command; + bool debug; + bool dry_run; + /* State */ + bool call_done; + bool in_call; + bool out_call; + int state; + int seq; +}; + +#endif /* IPC_MODEM */ diff --git a/tools/ipc-modem/tests/ipc-modem.py b/tools/ipc-modem/tests/ipc-modem.py new file mode 100755 index 0000000..d04f40d --- /dev/null +++ b/tools/ipc-modem/tests/ipc-modem.py @@ -0,0 +1,145 @@ +#!/usr/bin/env python3 +# +# This file is part of libsamsung-ipc. +# +# Copyright (C) 2020 Denis 'GNUtoo' Carikli <GNUtoo@cyberdimension.org> +# +# libsamsung-ipc is free software: you can redistribute it and/or modify +# it under the terms of the GNU General Public License as published by +# the Free Software Foundation, either version 2 of the License, or +# (at your option) any later version. +# +# libsamsung-ipc is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with libsamsung-ipc. If not, see <http://www.gnu.org/licenses/>. + +import os +import re +import sys +import sh + +# sysexits.h +class SysExit(object): + #define EX_USAGE 64 /* command line usage error */ + EX_USAGE = sh.ErrorReturnCode_64 + +def usage(progname): + print('{} [test]'.format(progname)) + sys.exit(1) + +def get_output(data): + return str(data).replace(os.linesep, '') + +class IpcModem(object): + def __init__(self): + srcdir = os.environ.get('srcdir', None) + + command_path = '' + if srcdir: + command_path = '.' + os.sep + 'ipc-modem' + # Enable to run tests without automake + else: + command_path = os.path.dirname(sys.argv[0]) \ + + os.sep \ + + '..' \ + + os.sep \ + + 'ipc-modem' + + if 'VALGRIND' in os.environ: + self.timeout = 60 + ipc_modem = sh.Command(os.environ['VALGRIND']) + self.ipc_modem = ipc_modem.bake('-v', + '--log-file=valgrind.%p.log', + '--leak-check=full', + command_path, + '--dry-run') + else: + self.timeout = 3 + ipc_modem = sh.Command(command_path) + self.ipc_modem = ipc_modem.bake('--dry-run') + + def test_help(self): + try: + self.ipc_modem() + except SysExit.EX_USAGE: + pass + else: + raise Exception() + + def test_boot(self, timeout=None): + if timeout==None: + timeout = self.timeout + + self.ipc_modem('boot', _timeout=timeout) + + def test_power_on(self, timeout=None): + if timeout==None: + timeout = self.timeout + + self.ipc_modem('power-on', _timeout=timeout) + + def test_power_off(self, timeout=None): + if timeout==None: + timeout = self.timeout + + self.ipc_modem('power-off', _timeout=timeout) + + def test_start(self, timeout=None): + if timeout==None: + timeout = self.timeout + + try: + self.ipc_modem('start', _timeout=timeout) + except sh.TimeoutException: + pass + else: + raise Exception() + + def test_call_with_number(self, timeout=None): + if timeout==None: + timeout = self.timeout + + expected_output = "[I] Got call number!" + output = "" + try: + output = get_output(self.ipc_modem('power-on', + '--call=0102030405', + _timeout=timeout)) + except: + raise Exception() + + if output != expected_output: + raise Exception() + + def test_call_without_number(self, timeout=None): + if timeout==None: + timeout = self.timeout + + expected_output = "[E] Missing call number" + output = get_output(self.ipc_modem('power-on', + '--call=', + _timeout=timeout, + _ok_code=SysExit.EX_USAGE.exit_code)) + if output != expected_output: + raise Exception() + + def test_commands(self): + self.test_boot() + self.test_power_on() + self.test_power_off() + self.test_start() + self.test_call_with_number() + self.test_call_without_number() + +def main(): + ipc_modem = IpcModem() + ipc_modem.test_help() + ipc_modem.test_commands() + +if __name__ == '__main__': + rc = main() + sys.exit(rc) diff --git a/tools/nv_data-imei.c b/tools/nv_data-imei.c index 2c04079..aa62e0c 100644 --- a/tools/nv_data-imei.c +++ b/tools/nv_data-imei.c @@ -84,7 +84,7 @@ static int list_supported(void) return 0; } -static int get_offset(struct command *command, void *arg) +static int get_offset(const struct command *command, void *arg) { struct offset *offset = arg; size_t i; @@ -146,7 +146,7 @@ static int get_offset(struct command *command, void *arg) return 0; } -static int get_imei(struct command *command, void *arg) +static int get_imei(const struct command *command, void *arg) { struct imei *imei = arg; @@ -180,7 +180,7 @@ static int get_imei(struct command *command, void *arg) imei->optarg); printf("In addition it is also invalid" " as it is composed of " - "%d digits instead of %d.\n", + "%zd digits instead of %d.\n", len, IMEI_LENGTH); return -EINVAL; } else if (!str_is_digit) { @@ -192,7 +192,7 @@ static int get_imei(struct command *command, void *arg) } else if (!str_len_valid) { printf("The '%s' " "IMEI is invalid as it is composed of " - "%d digits instead of %d.\n", + "%zd digits instead of %d.\n", imei->optarg, len, IMEI_LENGTH); return -EINVAL; } @@ -213,7 +213,7 @@ static int get_imei(struct command *command, void *arg) return 0; } -static struct command_option commands_options[] = { +static const struct command_option commands_options[] = { { OPTION_FILE, "", @@ -242,10 +242,10 @@ static struct command_option commands_options[] = { "--imei=355921041234567", get_imei, }, - { /* Sentinel */ }, + { 0 }, }; -static struct command commands[] = { +static const struct command commands[] = { { "list-supported", "Display supported devices and EFS", @@ -274,7 +274,7 @@ static struct command commands[] = { OPTION_FILE|OPTION_IMEI, bruteforce_imei_offset, }, - { /* Sentinel */ }, + { 0 }, }; #if DEBUG @@ -348,12 +348,12 @@ static void print_warnings(void) } /* TODO: Enforce type to only allow valid OPTION_* */ -static void *get_option(uint8_t given_option) +static const struct command_option *get_option(uint8_t given_option) { int i = 0; while (true) { - struct command_option *command_option = + const struct command_option *command_option = &(commands_options[i++]); /* TODO: Get C to do something like if (!option) */ @@ -372,7 +372,7 @@ static int print_all_options(void) int i = 0; while (true) { - struct command_option *option = &(commands_options[i++]); + const struct command_option *option = &(commands_options[i++]); /* TODO: Get C to do something like if (!option) */ if (!option->option) @@ -402,7 +402,7 @@ static int nv_data_imei_help(void) printf("Commands:\n"); while (true) { - struct command *cmd = &(commands[i++]); + const struct command *cmd = &(commands[i++]); /* TODO: Get C to do something like if (!cmd) */ if (!cmd->name) @@ -419,12 +419,12 @@ static int nv_data_imei_help(void) return 0; } -static void *get_command(const char *name) +static const struct command *get_command(const char *name) { int i = 0; while (true) { - struct command *cmd = &(commands[i++]); + const struct command *cmd = &(commands[i++]); /* TODO: Get C to do something like if (!cmd) */ if (!cmd->name) @@ -444,7 +444,7 @@ static void *get_command(const char *name) static int command_help(const char *command_name) { - struct command *command; + const struct command *command; size_t i; command = get_command(command_name); @@ -462,8 +462,8 @@ static int command_help(const char *command_name) if (command->options & BIT(i)) { bool required = !!(command->required_options & BIT(i)); - struct command_option *option = get_option( - command->options & BIT(i)); + const struct command_option *option = + get_option(command->options & BIT(i)); /* Check if option and commands are in sync */ assert(option != NULL); @@ -486,8 +486,8 @@ static int command_help(const char *command_name) printf("Options:\n"); for (i = 0; i < (8 * sizeof(command->options)); i++) { if (command->options & BIT(i)) { - struct command_option *option = get_option( - command->options & BIT(i)); + const struct command_option *option = + get_option(command->options & BIT(i)); /* Check if option and commands are in sync */ assert(option != NULL); @@ -510,8 +510,8 @@ static int command_help(const char *command_name) if (command->options) { for (i = 0; i < (8 * sizeof(command->options)); i++) { if (command->required_options & BIT(i)) { - struct command_option *option = get_option( - command->options & BIT(i)); + const struct command_option *option = + get_option(command->options & BIT(i)); /* Check if option and commands are in sync */ assert(option != NULL); @@ -766,7 +766,11 @@ int write_imei(char *nv_data_path, struct offset *offset, assert(imei->imei); assert(strlen(imei->imei) == IMEI_LENGTH); - asprintf(&md5_path, "%s.md5", nv_data_path); + rc = asprintf(&md5_path, "%s.md5", nv_data_path); + if (rc == -1) { + ipc_client_log(client, "%s: asprintf failed", __func__); + return -1; + } /* We only support one device so far */ nv_data_secret = XMM616_NV_DATA_SECRET; @@ -843,9 +847,9 @@ int main(int argc, char * const argv[]) opterr = 0; struct imei imei; struct offset offset; - struct command *command = NULL; - struct command_option *option = NULL; - char *nv_data_path; + const struct command *command = NULL; + const struct command_option *option = NULL; + char *nv_data_path = NULL; int c, rc; memset(&imei, 0, sizeof(imei)); diff --git a/tools/nv_data-imei.h b/tools/nv_data-imei.h index cb35808..7a153c2 100644 --- a/tools/nv_data-imei.h +++ b/tools/nv_data-imei.h @@ -66,7 +66,7 @@ struct command_option { const char *option_string; const char *help; const char *example; - int (*get_data)(struct command *command, void *arg); + int (*get_data)(const struct command *command, void *arg); }; #define NO_OPTIONS 0 diff --git a/tools/nv_data-md5.c b/tools/nv_data-md5.c index e8c9fc8..5edb257 100644 --- a/tools/nv_data-md5.c +++ b/tools/nv_data-md5.c @@ -20,6 +20,7 @@ #include <stdio.h> #include <stdlib.h> #include <string.h> +#include <sysexits.h> #include <sys/types.h> @@ -100,4 +101,6 @@ int main(int argc, char *argv[]) error: if (client != NULL) ipc_client_destroy(client); + + return EX_SOFTWARE; } diff --git a/tools/nv_data-imei.py b/tools/tests/nv_data-imei.py index da58a50..3447690 100755 --- a/tools/nv_data-imei.py +++ b/tools/tests/nv_data-imei.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # This file is part of libsamsung-ipc. # @@ -30,89 +30,110 @@ class SysExit(object): EX_NOINPUT = sh.ErrorReturnCode_66 def usage(progname): - print("{} [test]".format(progname)) + print('{} [test]'.format(progname)) sys.exit(1) commands = [ - "list-supported", - "read-imei", - "write-imei", - "bruteforce-imei", + 'list-supported', + 'read-imei', + 'write-imei', + 'bruteforce-imei', ] def get_output(data): - return str(data).replace(os.linesep, "") + return str(data).replace(os.linesep, '') class NvDataImei(object): def __init__(self): srcdir = os.environ.get('srcdir', None) - # Enable also to test without automake - if not srcdir: - srcdir = os.path.dirname(sys.argv[0]) - self.nv_data_imei = sh.Command(srcdir + os.sep + "nv_data-imei") + command_path = '' + if srcdir: + command_path = '.' + os.sep + 'nv_data-imei' + # Enable to run tests without automake + else: + command_path = os.path.dirname(sys.argv[0]) \ + + os.sep \ + + '..' \ + + os.sep \ + + 'nv_data-imei' + + if 'VALGRIND' in os.environ: + self.nv_data_imei = sh.Command(os.environ['VALGRIND']) + self.nv_data_imei = self.nv_data_imei.bake( + '-v', + '--log-file=valgrind.%p.log', + '--leak-check=full', + command_path) + else: + self.nv_data_imei = sh.Command(command_path) + def test_help(self): try: - self.nv_data_imei("") + self.nv_data_imei('') except SysExit.EX_USAGE: pass else: raise Exception() - for help_arg in ["-h", "--help"]: + for help_arg in ['-h', '--help']: self.nv_data_imei(help_arg) for command in commands: self.nv_data_imei(command, help_arg) try: - self.nv_data_imei("file", command, help_arg) + self.nv_data_imei('file', command, help_arg) except SysExit.EX_USAGE: pass else: raise Exception() - self.nv_data_imei("list-supported") + self.nv_data_imei('list-supported') def test_commands(self): # Create nv_data.bin - valid_imei = "123456789012345" + valid_imei = '123456789012345' offset = 0x100 XMM616_NV_DATA_SIZE = 0x200000 nv_data_bin = get_output(sh.mktemp()) - sh.ddrescue("/dev/zero", nv_data_bin, "-s", str(XMM616_NV_DATA_SIZE)) + sh.ddrescue('/dev/zero', nv_data_bin, '-s', str(XMM616_NV_DATA_SIZE)) - self.nv_data_imei(nv_data_bin, "write-imei", "-o", str(hex(offset)), - "-i", valid_imei) - output = get_output(self.nv_data_imei(nv_data_bin, "read-imei", "-o", + self.nv_data_imei(nv_data_bin, 'write-imei', '-o', str(hex(offset)), + '-i', valid_imei) + output = get_output(self.nv_data_imei(nv_data_bin, 'read-imei', '-o', str(hex(offset)))) print(output) - expect = "IMEI: " + valid_imei + expect = 'IMEI: ' + valid_imei if output != expect: raise Exception() - output = get_output(self.nv_data_imei(nv_data_bin, "bruteforce-imei", - "-i", valid_imei)) + output = get_output(self.nv_data_imei(nv_data_bin, 'bruteforce-imei', + '-i', valid_imei)) print(output) - expect = re.escape("Found IMEI at {} ({})".format(str(hex(offset)), + expect = re.escape('Found IMEI at {} ({})'.format(str(hex(offset)), offset)) if not re.search(expect, output): raise Exception() - inaccessible_nv_data_bin = str(sh.mktemp("-u")).replace(os.linesep,"") - sh.ddrescue("/dev/zero", inaccessible_nv_data_bin, "-s", + inaccessible_nv_data_bin = str(sh.mktemp('-u')).replace(os.linesep,'') + sh.ddrescue('/dev/zero', inaccessible_nv_data_bin, '-s', str(XMM616_NV_DATA_SIZE)) - sh.chmod("000", inaccessible_nv_data_bin); + sh.chmod('000', inaccessible_nv_data_bin); try: - self.nv_data_imei(inaccessible_nv_data_bin, "write-imei", - "-o", "0x0", "-i", valid_imei) - self.nv_data_imei(inaccessible_nv_data_bin, "read-imei", - "-o", "0x0") - self.nv_data_imei(inaccessible_nv_data_bin, "bruteforce-imei", - "-i", valid_imei) + self.nv_data_imei(inaccessible_nv_data_bin, 'write-imei', + '-o', '0x0', '-i', valid_imei) + self.nv_data_imei(inaccessible_nv_data_bin, 'read-imei', + '-o', '0x0') + self.nv_data_imei(inaccessible_nv_data_bin, 'bruteforce-imei', + '-i', valid_imei) except SysExit.EX_NOINPUT: pass else: raise Exception() + os.unlink(inaccessible_nv_data_bin) + os.unlink(nv_data_bin) + os.unlink(nv_data_bin + '.md5') + def main(): nv_data_imei = NvDataImei() nv_data_imei.test_help() diff --git a/tools/nv_data-md5.py b/tools/tests/nv_data-md5.py index 2897f18..374ded2 100755 --- a/tools/nv_data-md5.py +++ b/tools/tests/nv_data-md5.py @@ -1,4 +1,4 @@ -#!/usr/bin/env python +#!/usr/bin/env python3 # # This file is part of libsamsung-ipc. # @@ -23,20 +23,36 @@ import sys import sh def usage(progname): - print("{} [test]".format(progname)) + print('{} [test]'.format(progname)) sys.exit(1) def get_output(data): - return str(data).replace(os.linesep, "") + return str(data).replace(os.linesep, '') class NvDataMD5(object): def __init__(self): srcdir = os.environ.get('srcdir', None) - # Enable also to test without automake - if not srcdir: - srcdir = os.path.dirname(sys.argv[0]) - self.nv_data_md5 = sh.Command(srcdir + os.sep + "nv_data-md5") + command_path = '' + if srcdir: + command_path = '.' + os.sep + 'nv_data-md5' + # Enable to run tests without automake + else: + command_path = os.path.dirname(sys.argv[0]) \ + + os.sep \ + + '..' \ + + os.sep \ + + 'nv_data-md5' + + if 'VALGRIND' in os.environ: + self.nv_data_md5 = sh.Command(os.environ['VALGRIND']) + self.nv_data_md5 = self.nv_data_md5.bake( + '-v', + '--log-file=valgrind.%p.log', + '--leak-check=full', + command_path) + else: + self.nv_data_md5 = sh.Command(command_path) def test_help(self): try: self.nv_data_md5() @@ -46,12 +62,12 @@ class NvDataMD5(object): raise Exception() def test_commands(self): - expected_md5 = "5293814414abb3831e3fc1a1b35e69bc" + expected_md5 = '5293814414abb3831e3fc1a1b35e69bc' NV_DATA_SIZE = 0x200000 nv_data_bin = get_output(sh.mktemp()) # Create nv_data.bin - sh.ddrescue("/dev/zero", nv_data_bin, "-s", str(NV_DATA_SIZE)) + sh.ddrescue('/dev/zero', nv_data_bin, '-s', str(NV_DATA_SIZE)) output = get_output(self.nv_data_md5(nv_data_bin)) @@ -60,6 +76,8 @@ class NvDataMD5(object): if output != expected_md5: raise Exception() + os.unlink(nv_data_bin) + def main(): nv_data_md5 = NvDataMD5() nv_data_md5.test_help() |