diff --git a/TestComm/.gitignore b/TestComm/.gitignore
new file mode 100644
index 00000000..aa724b77
--- /dev/null
+++ b/TestComm/.gitignore
@@ -0,0 +1,15 @@
+*.iml
+.gradle
+/local.properties
+/.idea/caches
+/.idea/libraries
+/.idea/modules.xml
+/.idea/workspace.xml
+/.idea/navEditor.xml
+/.idea/assetWizardSettings.xml
+.DS_Store
+/build
+/captures
+.externalNativeBuild
+.cxx
+local.properties
diff --git a/TestComm/app/.gitignore b/TestComm/app/.gitignore
new file mode 100644
index 00000000..42afabfd
--- /dev/null
+++ b/TestComm/app/.gitignore
@@ -0,0 +1 @@
+/build
\ No newline at end of file
diff --git a/TestComm/app/build.gradle b/TestComm/app/build.gradle
new file mode 100644
index 00000000..afdc5d40
--- /dev/null
+++ b/TestComm/app/build.gradle
@@ -0,0 +1,52 @@
+plugins {
+ id 'com.android.application'
+}
+
+android {
+ compileSdk 32
+
+ defaultConfig {
+ applicationId "com.xinyingpower.testcomm"
+ minSdk 28
+ targetSdk 32
+ versionCode 1
+ versionName "1.0"
+
+ testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
+ externalNativeBuild {
+ cmake {
+ cppFlags '-std=c++17'
+ }
+ }
+ }
+
+ buildTypes {
+ release {
+ minifyEnabled false
+ proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
+ }
+ }
+ compileOptions {
+ sourceCompatibility JavaVersion.VERSION_1_8
+ targetCompatibility JavaVersion.VERSION_1_8
+ }
+ externalNativeBuild {
+ cmake {
+ path file('src/main/cpp/CMakeLists.txt')
+ version '3.18.1'
+ }
+ }
+ buildFeatures {
+ viewBinding true
+ }
+}
+
+dependencies {
+
+ implementation 'androidx.appcompat:appcompat:1.3.0'
+ implementation 'com.google.android.material:material:1.4.0'
+ implementation 'androidx.constraintlayout:constraintlayout:2.0.4'
+ testImplementation 'junit:junit:4.13.2'
+ androidTestImplementation 'androidx.test.ext:junit:1.1.3'
+ androidTestImplementation 'androidx.test.espresso:espresso-core:3.4.0'
+}
\ No newline at end of file
diff --git a/TestComm/app/proguard-rules.pro b/TestComm/app/proguard-rules.pro
new file mode 100644
index 00000000..481bb434
--- /dev/null
+++ b/TestComm/app/proguard-rules.pro
@@ -0,0 +1,21 @@
+# Add project specific ProGuard rules here.
+# You can control the set of applied configuration files using the
+# proguardFiles setting in build.gradle.
+#
+# For more details, see
+# http://developer.android.com/guide/developing/tools/proguard.html
+
+# If your project uses WebView with JS, uncomment the following
+# and specify the fully qualified class name to the JavaScript interface
+# class:
+#-keepclassmembers class fqcn.of.javascript.interface.for.webview {
+# public *;
+#}
+
+# Uncomment this to preserve the line number information for
+# debugging stack traces.
+#-keepattributes SourceFile,LineNumberTable
+
+# If you keep the line number information, uncomment this to
+# hide the original source file name.
+#-renamesourcefileattribute SourceFile
\ No newline at end of file
diff --git a/TestComm/app/src/androidTest/java/com/xinyingpower/testcomm/ExampleInstrumentedTest.java b/TestComm/app/src/androidTest/java/com/xinyingpower/testcomm/ExampleInstrumentedTest.java
new file mode 100644
index 00000000..44bbb0d8
--- /dev/null
+++ b/TestComm/app/src/androidTest/java/com/xinyingpower/testcomm/ExampleInstrumentedTest.java
@@ -0,0 +1,26 @@
+package com.xinyingpower.testcomm;
+
+import android.content.Context;
+
+import androidx.test.platform.app.InstrumentationRegistry;
+import androidx.test.ext.junit.runners.AndroidJUnit4;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+
+import static org.junit.Assert.*;
+
+/**
+ * Instrumented test, which will execute on an Android device.
+ *
+ * @see Testing documentation
+ */
+@RunWith(AndroidJUnit4.class)
+public class ExampleInstrumentedTest {
+ @Test
+ public void useAppContext() {
+ // Context of the app under test.
+ Context appContext = InstrumentationRegistry.getInstrumentation().getTargetContext();
+ assertEquals("com.xinyingpower.testcomm", appContext.getPackageName());
+ }
+}
\ No newline at end of file
diff --git a/TestComm/app/src/main/AndroidManifest.xml b/TestComm/app/src/main/AndroidManifest.xml
new file mode 100644
index 00000000..1c677876
--- /dev/null
+++ b/TestComm/app/src/main/AndroidManifest.xml
@@ -0,0 +1,27 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/cpp/CMakeLists.txt b/TestComm/app/src/main/cpp/CMakeLists.txt
new file mode 100644
index 00000000..282af7cc
--- /dev/null
+++ b/TestComm/app/src/main/cpp/CMakeLists.txt
@@ -0,0 +1,56 @@
+# For more information about using CMake with Android Studio, read the
+# documentation: https://d.android.com/studio/projects/add-native-code.html
+
+# Sets the minimum version of CMake required to build the native library.
+
+cmake_minimum_required(VERSION 3.18.1)
+
+# Declares and names the project.
+
+project("testcomm")
+
+# Creates and names a library, sets it as either STATIC
+# or SHARED, and provides the relative paths to its source code.
+# You can define multiple libraries, and CMake builds them for you.
+# Gradle automatically packages shared libraries with your APK.
+
+add_library( # Sets the name of the library.
+ testcomm
+
+ # Sets the library as a shared library.
+ SHARED
+
+ # Provides a relative path to your source file(s).
+ SpiPort.cpp
+ #spi-test-random.cpp
+ # NRSEC3000ctl.cpp
+ SpiLib.cpp
+ native-lib.cpp
+ GPIOControl.cpp)
+
+# Searches for a specified prebuilt library and stores the path as a
+# variable. Because CMake includes system libraries in the search path by
+# default, you only need to specify the name of the public NDK library
+# you want to add. CMake verifies that the library exists before
+# completing its build.
+
+find_library( # Sets the name of the path variable.
+ log-lib
+
+ # Specifies the name of the NDK library that
+ # you want CMake to locate.
+
+ log)
+
+# Specifies libraries CMake should link to your target library. You
+# can link multiple libraries, such as libraries you define in this
+# build script, prebuilt third-party libraries, or system libraries.
+
+target_link_libraries( # Specifies the target library.
+ testcomm
+
+ android
+
+ # Links the target library to the log library
+ # included in the NDK.
+ ${log-lib})
\ No newline at end of file
diff --git a/TestComm/app/src/main/cpp/GPIOControl.cpp b/TestComm/app/src/main/cpp/GPIOControl.cpp
new file mode 100644
index 00000000..187f7e33
--- /dev/null
+++ b/TestComm/app/src/main/cpp/GPIOControl.cpp
@@ -0,0 +1,134 @@
+//
+// Created by Matthew on 2023/12/27.
+//
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+#include "GPIOControl.h"
+
+#ifdef _DEBUG
+#include
+#endif
+
+#define IOT_PARAM_WRITE 0xAE
+#define IOT_PARAM_READ 0xAF
+#define MAX_STRING_LEN 32
+
+typedef struct
+{
+ int cmd;
+ int value;
+ int result;
+ long value2;
+ char str[MAX_STRING_LEN];
+}IOT_PARAM;
+
+void GpioControl::setInt(int cmd, int value)
+{
+ int fd = open("/dev/mtkgpioctrl", O_RDONLY);
+ IOT_PARAM param;
+ param.cmd = cmd;
+ param.value = value;
+ // LOGE("set_int fd=%d,cmd=%d,value=%d\r\n",fd, cmd, value);
+ if( fd > 0 )
+ {
+ int res = ioctl(fd, IOT_PARAM_WRITE, ¶m);
+ // LOGE("set_int22 cmd=%d,value=%d,result=%d\r\n",param.cmd, param.value, param.result);
+ close(fd);
+ }
+ return;
+}
+
+int GpioControl::getInt(int cmd)
+{
+ int fd = open("/dev/mtkgpioctrl", O_RDONLY);
+ // LOGE("get_int fd=%d,cmd=%d\r\n",fd, cmd);
+ if( fd > 0 )
+ {
+ IOT_PARAM param;
+ param.cmd = cmd;
+ ioctl(fd, IOT_PARAM_READ, ¶m);
+#ifdef _DEBUG
+ ALOGI("getInt cmd=%d,value=%d,result=%d\r\n",param.cmd, param.value, param.result);
+#endif
+ close(fd);
+ return param.value;
+ }
+ return -1;
+}
+
+void GpioControl::setLong(int cmd, long value)
+{
+ int fd = open("/dev/mtkgpioctrl", O_RDONLY);
+ IOT_PARAM param;
+ param.cmd = cmd;
+ param.value2 = value;
+ // LOGE("set_long fd=%d,cmd=%d,value2=%ld\r\n",fd, param.cmd, param.value2);
+
+ if( fd > 0 )
+ {
+ ioctl(fd, IOT_PARAM_WRITE, ¶m);
+ // LOGE("set_long22 cmd=%d,value2=%ld,result=%d\r\n",param.cmd, param.value2, param.result);
+ close(fd);
+ }
+}
+
+long GpioControl::getLong(int cmd)
+{
+ int fd = open("/dev/mtkgpioctrl", O_RDONLY);
+ // LOGE("get_long fd=%d,cmd=%d\r\n",fd, cmd);
+ if( fd > 0 )
+ {
+ IOT_PARAM param;
+ param.cmd = cmd;
+ ioctl(fd, IOT_PARAM_READ, ¶m);
+ // LOGE("get_long22 cmd=%d,value2=%ld,result=%d\r\n",param.cmd, param.value2, param.result);
+ close(fd);
+ return param.value2;
+ }
+ return -1;
+}
+
+void GpioControl::setString(int cmd, const std::string& value)
+{
+ IOT_PARAM param;
+ // char *pval = jstringToChars(env, value);
+ int fd = open("/dev/mtkgpioctrl", O_RDONLY);
+ int len = MAX_STRING_LEN < value.size() ? MAX_STRING_LEN : value.size();
+
+ param.cmd = cmd;
+ memset(param.str, 0, MAX_STRING_LEN);
+ memcpy(param.str, value.c_str(), len);
+ // LOGE("set_string fd=%d,cmd=%d,str=%s\r\n",fd, param.cmd, param.str);
+ if( fd > 0 )
+ {
+ ioctl(fd, IOT_PARAM_WRITE, ¶m);
+ // LOGE("set_string22 cmd=%d,str=%s,result=%d\r\n",param.cmd, param.str, param.result);
+ close(fd);
+ }
+ return;
+}
+
+std::string GpioControl::getString(int cmd)
+{
+ int fd = open("/dev/mtkgpioctrl", O_RDONLY);
+ // LOGE("get_string fd=%d,cmd=%d\r\n",fd, cmd);
+ if( fd > 0 )
+ {
+ IOT_PARAM param;
+ param.cmd = cmd;
+ ioctl(fd, IOT_PARAM_READ, ¶m);
+ // LOGE("get_string22 cmd=%d,str=%s,result=%d\r\n",param.cmd, param.str, param.result);
+ close(fd);
+ return std::string(param.str);
+ }
+ return "";
+}
diff --git a/TestComm/app/src/main/cpp/GPIOControl.h b/TestComm/app/src/main/cpp/GPIOControl.h
new file mode 100644
index 00000000..54a46177
--- /dev/null
+++ b/TestComm/app/src/main/cpp/GPIOControl.h
@@ -0,0 +1,167 @@
+//
+// Created by Matthew on 2023/12/27.
+//
+
+#ifndef MICROPHOTO_GPIOCONTROL_H
+#define MICROPHOTO_GPIOCONTROL_H
+
+#include
+
+#define CMD_GET_LIGHT_ADC 101
+#define CMD_SET_LIGHT_ADC 102
+#define CMD_GET_KEY_LOCKSTATE 103
+#define CMD_GET_BAT_ADC 104
+#define CMD_SET_FLASH_LED 105
+#define CMD_SET_NETWORK_STATE 106
+#define CMD_SET_OTG_STATE 107
+#define CMD_GET_OTG_STATE 108
+#define CMD_GET_CHARGING_VOL_STATE 110
+#define CMD_GET_CHARGING_SHUNT_VOLTAGE_STATE 111
+#define CMD_GET_CHARGING_BUS_VOLTAGE_STATE 112
+#define CMD_GET_CHARGING_POWER_STATE 113
+#define CMD_GET_CHARGING_CURRENT_STATE 114
+#define CMD_GET_BAT_VOL_STATE 115
+#define CMD_GET_BAT_SHUNT_VOLTAGE_STATE 116
+#define CMD_GET_BAT_BUS_VOLTAGE_STATE 117
+#define CMD_GET_BAT_POWER_STATE 118
+#define CMD_GET_BAT_CURRENT_STATE 119
+#define CMD_SET_485_STATE 121
+#define CMD_SET_SPI_MODE 123
+#define CMD_SET_SPI_BITS_PER_WORD 124
+#define CMD_SET_SPI_MAXSPEEDHZ 125
+#define CMD_SET_PWM_BEE_STATE 126
+#define CMD_SET_ALM_MODE 128
+#define CMD_SET_SPI_POWER 129
+#define CMD_SET_485_EN_STATE 131
+#define CMD_SET_CAM_3V3_EN_STATE 132
+#define CMD_SET_12V_EN_STATE 133
+#define CMD_SET_SYSTEM_RESET 202
+
+class GpioControl
+{
+public:
+
+ static void setInt(int cmd, int value);
+ static int getInt(int cmd);
+ static void setLong(int cmd, long value);
+ static long getLong(int cmd);
+ static void setString(int cmd, const std::string& value);
+ static std::string getString(int cmd);
+
+ static void setOtgState(bool on)
+ {
+ setInt(CMD_SET_OTG_STATE, on ? 1 : 0);
+ }
+
+ static bool getOtgState()
+ {
+ return getInt(CMD_SET_OTG_STATE) != 0;
+ }
+
+ static void setCam3V3Enable(bool enabled)
+ {
+ setInt(CMD_SET_CAM_3V3_EN_STATE, enabled ? 1 : 0);
+ }
+
+ static void reboot()
+ {
+ setInt(CMD_SET_SYSTEM_RESET, 1);
+ }
+
+ static void setLightAdc(int i)
+ {
+ setInt(CMD_SET_LIGHT_ADC, i);
+ }
+
+ static int getLightAdc()
+ {
+ return getInt(CMD_GET_LIGHT_ADC);
+ }
+
+ static int getChargingVoltage()
+ {
+ return getInt(CMD_GET_CHARGING_VOL_STATE);
+ }
+
+ static int getChargingShuntVoltage()
+ {
+ return getInt(CMD_GET_CHARGING_SHUNT_VOLTAGE_STATE);
+ }
+
+ static int getChargingBusVoltage() {
+ return getInt(CMD_GET_CHARGING_BUS_VOLTAGE_STATE);
+ }
+
+ static int getChargingPower() {
+ return getInt(CMD_GET_CHARGING_POWER_STATE);
+ }
+
+ static int getChargingCurrent() {
+ return getInt(CMD_GET_CHARGING_CURRENT_STATE);
+ }
+
+ static int getBatteryVoltage() {
+ return getInt(CMD_GET_BAT_VOL_STATE);
+ }
+
+ static int getBatteryShuntVoltage() {
+ return getInt(CMD_GET_BAT_SHUNT_VOLTAGE_STATE);
+ }
+
+ static int getBatteryBusVoltage() {
+ return getInt(CMD_GET_BAT_BUS_VOLTAGE_STATE);
+ }
+
+ static int getBatteryPower() {
+ return getInt(CMD_GET_BAT_POWER_STATE);
+ }
+
+ static int getBatteryCurrent() {
+ return getInt(CMD_GET_BAT_CURRENT_STATE);
+ }
+
+ static void set485WriteMode() {
+ setInt(CMD_SET_485_STATE, 1);
+ }
+
+ static void set485ReadMode() {
+ setInt(CMD_SET_485_STATE, 0);
+ }
+
+ static void setSpiMode(int i) {
+ setInt(CMD_SET_SPI_MODE, i);
+ }
+
+ static void setSpiBitsPerWord(int i) {
+ setInt(CMD_SET_SPI_BITS_PER_WORD, i);
+ }
+
+ static void setSpiMaxSpeedHz(long j) {
+ setLong(CMD_SET_SPI_MAXSPEEDHZ, j);
+ }
+
+ static void setBeeOn(bool z) {
+ setInt(CMD_SET_PWM_BEE_STATE, z ? 1 : 0);
+ }
+
+ static void setJidianqiState(bool z) {
+ setInt(CMD_SET_ALM_MODE, z ? 1 : 0);
+ }
+
+ static void setSpiPower(bool on) {
+ setInt(CMD_SET_SPI_POWER, on ? 1 : 0);
+ }
+
+ static void setRS485Enable(bool z) {
+ setInt(CMD_SET_485_EN_STATE, z ? 1 : 0);
+ }
+
+
+ static void set12VEnable(bool z) {
+ setInt(CMD_SET_12V_EN_STATE, z ? 1 : 0);
+ }
+
+};
+
+
+#endif //MICROPHOTO_GPIOCONTROL_H
diff --git a/TestComm/app/src/main/cpp/SerialPort.cpp b/TestComm/app/src/main/cpp/SerialPort.cpp
new file mode 100644
index 00000000..e035c8da
--- /dev/null
+++ b/TestComm/app/src/main/cpp/SerialPort.cpp
@@ -0,0 +1,142 @@
+/*
+ * Copyright 2009-2011 Cedric Priscal
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "SerialPort.h"
+
+#include "android/log.h"
+static const char *TAG="serial_port";
+#define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO, TAG, fmt, ##args)
+#define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
+#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
+
+static speed_t getBaudrate(int baudrate)
+{
+ switch(baudrate) {
+ case 0: return B0;
+ case 50: return B50;
+ case 75: return B75;
+ case 110: return B110;
+ case 134: return B134;
+ case 150: return B150;
+ case 200: return B200;
+ case 300: return B300;
+ case 600: return B600;
+ case 1200: return B1200;
+ case 1800: return B1800;
+ case 2400: return B2400;
+ case 4800: return B4800;
+ case 9600: return B9600;
+ case 19200: return B19200;
+ case 38400: return B38400;
+ case 57600: return B57600;
+ case 115200: return B115200;
+ case 230400: return B230400;
+ case 460800: return B460800;
+ case 500000: return B500000;
+ case 576000: return B576000;
+ case 921600: return B921600;
+ case 1000000: return B1000000;
+ case 1152000: return B1152000;
+ case 1500000: return B1500000;
+ case 2000000: return B2000000;
+ case 2500000: return B2500000;
+ case 3000000: return B3000000;
+ case 3500000: return B3500000;
+ case 4000000: return B4000000;
+ default: return -1;
+ }
+}
+
+/*
+ * Class: android_serialport_SerialPort
+ * Method: open
+ * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
+ */
+bool SerialPort::Open(std::string path, int baudrate, int flags)
+{
+ speed_t speed;
+
+ /* Check arguments */
+ {
+ speed = getBaudrate(baudrate);
+ if (speed == -1) {
+ /* TODO: throw an exception */
+ LOGE("Invalid baudrate");
+ return false;
+ }
+ }
+
+ /* Opening device */
+ {
+
+ m_fd = open(path.c_str(), O_RDWR | flags);
+ LOGD("open() m_fd = %d", m_fd);
+ if (m_fd == -1)
+ {
+ /* Throw an exception */
+ LOGE("Cannot open port");
+ /* TODO: throw an exception */
+ return false;
+ }
+ }
+
+ /* Configure device */
+ {
+ struct termios cfg;
+ LOGD("Configuring serial port");
+ if (tcgetattr(m_fd, &cfg))
+ {
+ LOGE("tcgetattr() failed");
+ close(m_fd);
+ /* TODO: throw an exception */
+ return false;
+ }
+
+ cfmakeraw(&cfg);
+ cfsetispeed(&cfg, speed);
+ cfsetospeed(&cfg, speed);
+
+ if (tcsetattr(m_fd, TCSANOW, &cfg))
+ {
+ LOGE("tcsetattr() failed");
+ close(m_fd);
+ /* TODO: throw an exception */
+ return false;
+ }
+ }
+
+ return true;
+}
+
+/*
+ * Class: cedric_serial_SerialPort
+ * Method: close
+ * Signature: ()V
+ */
+bool SerialPort::Close()
+{
+ LOGD("close(m_fd = %d)", m_fd);
+ close(m_fd);
+}
+
diff --git a/TestComm/app/src/main/cpp/SerialPort.h b/TestComm/app/src/main/cpp/SerialPort.h
new file mode 100644
index 00000000..28f603af
--- /dev/null
+++ b/TestComm/app/src/main/cpp/SerialPort.h
@@ -0,0 +1,18 @@
+#ifndef __SERIALPORT_H__
+#define __SERIALPORT_H__
+
+#include
+
+class SerialPort
+{
+public:
+
+ bool Open(std::string path, int, int);
+
+ bool Close();
+
+protected:
+ int m_fd;
+};
+
+#endif // __SERIALPORT_H__
diff --git a/TestComm/app/src/main/cpp/SpiLib.cpp b/TestComm/app/src/main/cpp/SpiLib.cpp
new file mode 100644
index 00000000..1934b923
--- /dev/null
+++ b/TestComm/app/src/main/cpp/SpiLib.cpp
@@ -0,0 +1,1290 @@
+#include "SpiLib.h"
+
+//typedef unsigned char u8;
+
+#define RE_SUC 0x01
+#define RE_ERROR 0x00
+
+
+
+int SpiLIb::spi_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int bytes)
+{
+ struct spi_ioc_transfer xfer[2];
+ int status;
+
+ memset(xfer, 0, sizeof(xfer));
+
+ xfer[0].tx_buf = (__u64)txbuf;
+ xfer[0].rx_buf = (__u64)rxbuf;
+ xfer[0].len = bytes;
+
+ status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);
+ if (status < 0)
+ {
+ perror("SPI_IOC_MESSAGE");
+ return -1;
+ }
+
+ return status;
+
+}
+
+void SpiLIb::spi_master_init(const char *name, int fd)
+{
+ __u8 mode = 3;
+ __u8 lsb, bits;
+ //__u32 speed = 30000000;
+ __u32 speed = 2000000;
+ //__u32 speed = 2000000;
+ //__u32 speed = 33000000;
+
+ // SPI_IOC_WR_MODE
+
+ ioctl(fd, SPI_IOC_WR_MODE, &mode);
+ ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
+
+ if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0)
+ {
+ perror("SPI rd_mode");
+ return;
+ }
+
+ if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0)
+ {
+ perror("SPI rd_lsb_fist");
+ return;
+ }
+
+ if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0)
+ {
+ perror("SPI rd bits_per_word");
+ return;
+ }
+
+ if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0)
+ {
+ perror("SPI rd max_speed_hz");
+ return;
+ }
+
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "%s: spi mode %d, %d bits %sper word, %d Hz max\n", name, mode, bits, lsb ? "(lsb first) " : "", speed);
+ //printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
+ // name, mode, bits, lsb ? "(lsb first) " : "", speed);
+}
+
+unsigned char SpiLIb::get_crc7(const unsigned char *buff, int len)
+{
+ unsigned char crc7_accum = 0;
+ int i;
+
+ for (i=0; i < len; i++) {
+ crc7_accum =
+ crc7_table[(crc7_accum << 1) ^ buff[i]];
+ }
+ return crc7_accum;
+}
+
+int SpiLIb::delay(int x)
+{
+ // while (--x);
+ // std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ usleep(50000);
+ return 0;
+}
+
+
+void SpiLIb::SendCmdHeader(int fd,u8 *cmd, u8 *rxbuf)
+{
+ int i=0;
+ int retval;
+
+#if defined (CONFIG_ATMEL_SPI_DEBUG)
+ printf("tx %1d bytes: ", CMD_HEAD_SIZE);
+ for (i = 0; i < CMD_HEAD_SIZE; i++)
+ {
+ printf(" %02x", cmd[i]);
+ }
+ printf("\n");
+#endif
+
+ /* send five command header */
+ for (i=0; i< CMD_HEAD_SIZE; i++)
+ {
+ retval = spi_transfer(fd, cmd+i, rxbuf+i, 1);
+ __android_log_print(ANDROID_LOG_INFO, "SPiCMD", "cmd[%d]=%x,rxbuf[%d]=%x",i,*(cmd+i),i, *(rxbuf+i));
+ delay(20);
+ }
+
+ cmd[0]=0xaa; //for response
+
+}
+
+void SpiLIb::RcvINS(int fd, u8 *txbuf, u8 *buf, u8 ins)
+{
+ int retval;
+ int cnt = 1000;
+ int count=0;
+ /* receive ins */
+ INS:
+ txbuf[0] = 0xaa;
+ delay(20);
+ while(cnt--)
+ {
+ retval = spi_transfer(fd, txbuf, buf, 1);
+ __android_log_print(ANDROID_LOG_INFO, "SPiINS", "txbuf=%x,buf=%x", *txbuf,*buf);
+ if(*buf == ins)
+ {
+ return;
+ break;
+ }
+ else
+ goto INS;
+ }
+}
+
+void SpiLIb::RcvLEN(int fd, u8 *txbuf, u8 *buf, u8 len)
+{
+
+ int retval;
+ /* receive length */
+ LEN:
+ for(int i=0;i>= 8;
+ memset(Z, entl & 0xFF, 1);
+ memcpy(Z + 2, pucID, idl);
+ memcpy(Z + 2 + idl, abxy, 32 *4);
+ memcpy(Z + 2 + idl + 4 * 32, pubkey, 32);
+ memcpy(Z + 2 + idl + 5 * 32, pubkey+32, 32);
+ nRet = SM3Hash(Z,l,tmpm);
+ if (nRet != 0)
+ goto quit;
+ free(Z);
+ l = inl + 32;
+ Z = (unsigned char *)malloc(l);
+ if (!Z) {
+ nRet = -1;
+ goto quit;
+ }
+ memcpy(Z,tmpm,32);
+ memcpy(Z+32, in, inl);
+ nRet = SM3Hash(Z,l,out);
+ quit:
+ if (Z)
+ free(Z);
+ return nRet;
+}//用于签名的处理哈希值,用户标识01*16
+
+int SpiLIb::SM2Sign(int index,const unsigned char *to_sign,unsigned char *out_sign)//SM2签名 所使用的哈希值应该来源于sm3hash_tosm2
+{
+ int i;
+ int cnt;
+ unsigned char txbuf[256];
+ unsigned char rxbuf[256];
+
+ int retval;
+ int msglen;
+ int fd;
+ const char *devname = "/dev/spidevSE";
+ //const char *devname = "/dev/spidev0.0";
+ //const char *devname = "/dev/mtkgpioctrl";
+
+ // NrsecSpiPort spi("/dev/spidevSE");
+ //
+ // // NrsecSpiPort spi("/dev/spidev0.0")
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ spi_master_init(devname, fd);
+
+
+ msglen = 5;
+ memset(rxbuf, 0, sizeof(rxbuf));
+ memset(txbuf, 0, sizeof(txbuf));
+
+ //printf("tx %1d bytes: ", msglen);
+ //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
+ SM2Sign_CMD[3]=index;
+
+ CMD_RESEND:
+
+ memcpy(txbuf, (const void *) SM2Sign_CMD, sizeof(SM2Sign_CMD));
+
+ SendCmdHeader(fd, txbuf, rxbuf);
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]);
+
+ SendId(fd,txbuf,rxbuf, 0x55);
+
+ memcpy(txbuf, to_sign, 32);
+
+ SendData(fd, txbuf, rxbuf,32);
+
+ SendEnd(fd,txbuf,rxbuf);
+
+ memcpy(txbuf, (const void *) SM2Sign_CMD, sizeof(SM2Sign_CMD));
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]);
+
+ RcvLEN(fd,txbuf,rxbuf+1, 1);
+
+ RcvData(fd, txbuf, rxbuf+2);
+
+ RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90);
+
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4);
+ for (i = 2; i < rxbuf[1]+2; i++) {
+ //sprintf(output, " %02x ", rxbuf[i]);
+ out_sign[i-2]= rxbuf[i];
+ }
+
+ close(fd);
+ return 0;
+}
+
+int SpiLIb::SM2VerifySign(int index, unsigned char *hash,unsigned char *vs)//SM2验签
+{
+ unsigned char txbuf[256];
+ unsigned char rxbuf[256];
+
+ int retval;
+ int msglen;
+ int fd;
+ const char *devname = "/dev/spidevSE";
+ //const char *devname = "/dev/spidev0.0";
+ //const char *devname = "/dev/mtkgpioctrl";
+
+ // NrsecSpiPort spi("/dev/spidevSE");
+ //
+ // // NrsecSpiPort spi("/dev/spidev0.0")
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ spi_master_init(devname, fd);
+
+
+ msglen = 5;
+ memset(rxbuf, 0, sizeof(rxbuf));
+ memset(txbuf, 0, sizeof(txbuf));
+
+ //printf("tx %1d bytes: ", msglen);
+ //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
+ SM2VerifySign_CMD[3]=index;
+
+ CMD_RESEND:
+
+ memcpy(txbuf, (const void *) SM2VerifySign_CMD, sizeof(SM2VerifySign_CMD));
+
+ SendCmdHeader(fd, txbuf, rxbuf);
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]);
+
+ SendId(fd,txbuf,rxbuf, 0x55);
+
+ memcpy(txbuf, hash, 32);
+ memcpy(txbuf+32,vs,64);
+
+ SendData(fd, txbuf, rxbuf,96);
+
+ SendEnd(fd,txbuf,rxbuf);
+
+ RcvSW(fd, txbuf, rxbuf, 0x90);
+
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4);
+
+
+ close(fd);
+ return 0;
+}
+
+int SpiLIb::SM2encrypt(int index,unsigned char *to_encrypt ,unsigned char *out_encrypt)//加密
+{
+ int i;
+ int cnt;
+ unsigned char txbuf[512];
+ unsigned char rxbuf[512];
+
+ int retval;
+ int msglen;
+ int fd;
+ const char *devname = "/dev/spidevSE";
+ //const char *devname = "/dev/spidev0.0";
+ //const char *devname = "/dev/mtkgpioctrl";
+
+ // NrsecSpiPort spi("/dev/spidevSE");
+ //
+ // // NrsecSpiPort spi("/dev/spidev0.0")
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ spi_master_init(devname, fd);
+
+
+ msglen = 5;
+ memset(rxbuf, 0, sizeof(rxbuf));
+ memset(txbuf, 0, sizeof(txbuf));
+
+ //printf("tx %1d bytes: ", msglen);
+ //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
+ SM2encrypt_CMD[3]=index;
+
+ CMD_RESEND:
+
+ memcpy(txbuf, (const void *) SM2encrypt_CMD, sizeof(SM2encrypt_CMD));
+
+ SendCmdHeader(fd, txbuf, rxbuf);
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]);
+
+ SendId(fd,txbuf,rxbuf, 0x55);
+
+ memcpy(txbuf, to_encrypt, 32);
+
+ SendData(fd, txbuf, rxbuf,32);
+
+ SendEnd(fd,txbuf,rxbuf);
+
+ memcpy(txbuf, (const void *) SM2encrypt_CMD, sizeof(SM2encrypt_CMD));
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]);
+
+ RcvLEN(fd,txbuf,rxbuf+1, 1);
+
+ RcvData(fd, txbuf, rxbuf+2);
+
+ RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90);
+
+ //__android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4);
+ for (i = 2; i < rxbuf[1]+2; i++) {
+ //sprintf(output, " %02x ", rxbuf[i]);
+ out_encrypt[i-2]= rxbuf[i];
+ }
+
+ close(fd);
+ return 0;
+}
+int SpiLIb::SM2decoder(int index,unsigned char *to_decoder ,unsigned char *out_decoder)//解密
+{
+ int i;
+ int cnt;
+ unsigned char txbuf[512];
+ unsigned char rxbuf[512];
+
+ int retval;
+ int msglen;
+ int fd;
+ const char *devname = "/dev/spidevSE";
+ //const char *devname = "/dev/spidev0.0";
+ //const char *devname = "/dev/mtkgpioctrl";
+
+ // NrsecSpiPort spi("/dev/spidevSE");
+ //
+ // // NrsecSpiPort spi("/dev/spidev0.0")
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ spi_master_init(devname, fd);
+
+
+ msglen = 5;
+ memset(rxbuf, 0, sizeof(rxbuf));
+ memset(txbuf, 0, sizeof(txbuf));
+
+ //printf("tx %1d bytes: ", msglen);
+ //__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
+ SM2decoder_CMD[3]=index;
+
+ CMD_RESEND:
+
+ memcpy(txbuf, (const void *) SM2decoder_CMD, sizeof(SM2decoder_CMD));
+
+ SendCmdHeader(fd, txbuf, rxbuf);
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]);
+
+ SendId(fd,txbuf,rxbuf, 0x55);
+
+ memcpy(txbuf, to_decoder, 128);
+
+ SendData(fd, txbuf, rxbuf,128);
+
+ SendEnd(fd,txbuf,rxbuf);
+
+ memcpy(txbuf, (const void *) SM2decoder_CMD, sizeof(SM2decoder_CMD));
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]);
+
+ RcvLEN(fd,txbuf,rxbuf+1, 1);
+
+ RcvData(fd, txbuf, rxbuf+2);
+
+ RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90);
+
+ //__android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4);
+ for (i = 2; i < rxbuf[1]+2; i++) {
+ //sprintf(output, " %02x ", rxbuf[i]);
+ out_decoder[i-2]= rxbuf[i];
+ }
+
+ close(fd);
+ return 0;
+}
+
+int SpiLIb::SM2cert(int type,int index,string cert,unsigned char *out_cert)//证书
+{
+ int i;
+ int cnt;
+ unsigned char txbuf[512];
+ unsigned char rxbuf[1024];
+
+ int retval;
+ int msglen;
+ int fd;
+ const char *devname = "/dev/spidevSE";
+ //const char *devname = "/dev/spidev0.0";
+ //const char *devname = "/dev/mtkgpioctrl";
+
+ // NrsecSpiPort spi("/dev/spidevSE");
+ //
+ // // NrsecSpiPort spi("/dev/spidev0.0")
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ spi_master_init(devname, fd);
+
+
+ msglen = 5;
+ memset(rxbuf, 0, sizeof(rxbuf));
+ memset(txbuf, 0, sizeof(txbuf));
+
+ //printf("tx %1d bytes: ", msglen);
+
+ int certlen=cert.length();
+ unsigned char to_cert[certlen];
+ for(int x=0;x
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+using namespace std;
+
+#define CMD_HEAD_SIZE 5
+using namespace std;
+typedef unsigned char u8;
+
+class SpiLIb{
+public:
+ int Spirandom();
+ int Version();
+ int Indentify(unsigned char *to_idt,unsigned char *out_idt);
+ int SM2keypair(int index);
+ int SM2OutPub(int index,unsigned char result[]);
+ int SM2OutPri(int index,unsigned char result[]);
+ int SM2InPub(int index,const unsigned char new_key[]);
+ int SM2InPri(int index,const unsigned char new_key[]);
+ int SM3Hash(unsigned char *to_hash ,int len,unsigned char *out_hash);
+ int sm3hash_tosm2(unsigned char *in,int inl,unsigned char *out, unsigned char *pubkey, unsigned char
+ *pucID, int idl);
+ int SM2Sign(int index,const unsigned char *to_sign,unsigned char *out_sign);
+ int SM2VerifySign(int index,unsigned char *hash,unsigned char *vs);
+ int SM2encrypt(int index,unsigned char *to_encrypt ,unsigned char *out_encrypt);
+ int SM2decoder(int index,unsigned char *to_decoder ,unsigned char *out_decoder);
+ int SM2cert(int type,int index,string cert,unsigned char *out_cert);
+
+
+
+
+private:
+ const unsigned char crc7_table[256]= {
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+ 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+ 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
+ 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
+ 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+ 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
+ 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
+ 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+ 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
+ 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
+ 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+ 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
+ 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
+ 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+ 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
+ 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
+ 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+ 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
+ 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
+ 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+ 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
+ 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+ 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
+ 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
+ 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+ 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
+ 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
+ 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+ 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
+ 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
+ };
+ const unsigned char EK_CMD[5]={0x80,0xd4,0x01,0x00,0x10};
+ const unsigned char AK_CMD[5]={0x80,0xd4,0x02,0x00,0x10};
+ const unsigned char IV_CMD[5]={0x80,0xd4,0x04,0x00,0x10};
+ volatile unsigned char SM1encrpt_CMD[5]={0xa0,0xe0,0x80,0xff,0xff};
+ volatile unsigned char SM1decoder_CMD[5]={0xa0,0xe0,0x81,0xff,0xff};
+ volatile unsigned char SM2Keypair_CMD[5]={0x80,0xb2,0x00,0xff,0x00};
+ volatile unsigned char SM2OutPub_CMD[5]={0x80,0xb8,0x01,0xff,0x40};
+ volatile unsigned char SM2OutPri_CMD[5]={0x80,0xb8,0x02,0xff,0x20};
+ volatile unsigned char SM2InPub_CMD[5]={0x80,0xba,0x01,0xff,0x40};
+ volatile unsigned char SM2InPri_CMD[5]={0x80,0xba,0x02,0xff,0x20};
+ volatile unsigned char SM3Hash_CMD[5]={0x80,0xb5,0x00,0xff,0xff};
+ volatile unsigned char SM2Sign_CMD[5]={0x80,0xb4,0x00,0xff,0x20};
+ volatile unsigned char SM2VerifySign_CMD[5]={0x80,0xb6,0x00,0xff,0x60};
+ volatile unsigned char SM2encrypt_CMD[5]={0x80,0xb3,0x01,0xff,0x20};
+ volatile unsigned char SM2decoder_CMD[5]={0x80,0xb3,0x81,0xff,0x80};
+ volatile unsigned char SM2cert_CMD[5]={0x80,0xb7,0xff,0xff,0xff};
+ volatile unsigned char Random_CMD[5]={0x00,0x84,0x00,0x00,0xff};
+ const unsigned char Version_CMD[5]={0x00,0x5b,0x00,0x00,0x40};
+ const unsigned char Indentify_CMD[5]={0x80,0xb3,0x01,0x04,0x20};
+
+ int spi_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int bytes);
+ void spi_master_init(const char *name, int fd);
+ unsigned char get_crc7(const unsigned char *buff, int len);
+ void SendCmdHeader(int fd,u8 *cmd, u8 *rxbuf);
+ int delay(int x);
+ void RcvINS(int fd, u8 *txbuf, u8 *buf, u8 ins);
+ void RcvLEN(int fd, u8 *txbuf, u8 *buf, u8 len);
+ void RcvData(int fd, u8 *txbuf, u8 *buf);
+ void RcvData(int fd, u8 *txbuf, u8 *buf, int len);
+ void RcvSW(int fd, u8 *txbuf, u8 *buf, u8 sw);
+ void SendEnd(int fd, u8 *txbuf, u8 *buf);
+ void SendId(int fd, u8 *txbuf, u8 *buf, u8 id);
+ void SendData(int fd,u8 *data, u8 *rxbuf,int data_size);
+
+
+
+};
+
+
+
+
+#endif //TESTCOMM_SPILIB_H
diff --git a/TestComm/app/src/main/cpp/SpiPort.cpp b/TestComm/app/src/main/cpp/SpiPort.cpp
new file mode 100644
index 00000000..44e1afb9
--- /dev/null
+++ b/TestComm/app/src/main/cpp/SpiPort.cpp
@@ -0,0 +1,62 @@
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "SpiPort.h"
+
+SpiPort::SpiPort(const std::string& path) : m_path(path), m_fd(0)
+{
+}
+
+SpiPort::~SpiPort()
+{
+ if (m_fd > 0)
+ {
+ close(m_fd);
+ }
+}
+
+bool SpiPort::Open()
+{
+ if(m_fd <= 0) m_fd = open(m_path.c_str(), O_RDWR/*|O_NDELAY|O_NOCTTY*/);
+ if(m_fd <= 0 ) {
+ int err = errno;
+ m_log = "open spi Error errno=" + std::to_string(err);
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "open spi Error errno=%d", err);
+ return false;
+ }
+ else __android_log_print(ANDROID_LOG_INFO, "SPi", "open spi Success m_fd=%d",m_fd);
+
+ return true;
+}
+
+// write
+int SpiPort::Write(unsigned char *buf, int len)
+{
+ return write(m_fd, buf, len);
+}
+
+// read
+int SpiPort::Read(unsigned char *buf, int len)
+{
+ return read(m_fd, buf, len);
+}
+
+//close
+bool SpiPort::Close()
+{
+ if(m_fd > 0)
+ {
+ close(m_fd);
+ m_fd = 0;
+ }
+
+ return true;
+}
\ No newline at end of file
diff --git a/TestComm/app/src/main/cpp/SpiPort.h b/TestComm/app/src/main/cpp/SpiPort.h
new file mode 100644
index 00000000..a4d82697
--- /dev/null
+++ b/TestComm/app/src/main/cpp/SpiPort.h
@@ -0,0 +1,30 @@
+#ifndef _SPIPORT_H_
+#define _SPIPORT_H_
+
+#include
+
+class SpiPort
+{
+public:
+
+ SpiPort(const std::string& path);
+ ~SpiPort();
+
+ bool Open();
+ int Write(unsigned char *buf, int len);
+ int Read(unsigned char *buf, int len);
+
+ bool Close();
+
+ std::string GetLog() const
+ {
+ return m_log;
+ }
+
+protected:
+ std::string m_path;
+ std::string m_log;
+ int m_fd;
+};
+
+#endif
\ No newline at end of file
diff --git a/TestComm/app/src/main/cpp/native-lib.cpp b/TestComm/app/src/main/cpp/native-lib.cpp
new file mode 100644
index 00000000..9d693290
--- /dev/null
+++ b/TestComm/app/src/main/cpp/native-lib.cpp
@@ -0,0 +1,604 @@
+#include
+#include
+
+#include "SpiPort.h"
+#include "SpiLib.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include "GPIOControl.h"
+
+#if 0
+int main() {
+ int fd;
+ struct termios options;
+ char *serialPort = "/dev/ttyS0"; // 串口设备文件路径
+ char *message = "Hello, serial port!\n";
+ int messageLength = strlen(message);
+ char buffer[50];
+ int bytesRead;
+
+ // 打开串口设备
+ fd = open(serialPort, O_RDWR | O_NOCTTY | O_NDELAY);
+ if (fd == -1) {
+ perror("open_port: Unable to open serial port - ");
+ return(-1);
+ }
+
+ // 获取并配置串口选项
+ tcgetattr(fd, &options);
+ cfsetispeed(&options, B9600); // 输入波特率
+ cfsetospeed(&options, B9600); // 输出波特率
+ options.c_cflag |= (CLOCAL | CREAD); // 开启接收
+ options.c_cflag &= ~CSIZE; // 清除当前数据位设置
+ options.c_cflag |= CS8; // 8位数据位
+ options.c_cflag &= ~PARENB; // 关闭校验位
+ options.c_cflag &= ~CSTOPB; // 1位停止位
+ options.c_cc[VTIME] = 0; // 非阻塞读取
+ options.c_cc[VMIN] = 10; // 读取字符的最小数目
+ tcflush(fd, TCIFLUSH); // 清空输入缓冲区
+
+ // 使用配置好的选项
+ tcsetattr(fd, TCSANOW, &options);
+
+ // 写入数据到串口
+ write(fd, message, messageLength);
+
+ // 从串口读取数据
+ bytesRead = read(fd, buffer, sizeof(buffer));
+ if (bytesRead > 0) {
+ buffer[bytesRead] = '\0'; // 确保字符串以null结尾
+ printf("Response from serial port: %s\n", buffer);
+ }
+
+ // 关闭串口
+ close(fd);
+
+ return 0;
+}
+#endif
+
+class NrsecSpiPort : public SpiPort {
+public:
+ NrsecSpiPort(const std::string& path) : SpiPort(path) {
+
+ }
+
+ bool Open()
+ {
+ if (!SpiPort::Open())
+ {
+ return false;
+ }
+
+ uint8_t mode = SPI_MODE_3;
+ uint8_t bits = 8;
+ uint32_t speed = 33000000;
+ uint8_t lsb = 1;
+ // const char *device = "/dev/spidev32766.1";
+
+ if (ioctl(m_fd, SPI_IOC_WR_MODE, &mode) == -1 ||
+ ioctl(m_fd, SPI_IOC_WR_BITS_PER_WORD, &bits) == -1 ||
+ ioctl(m_fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed) == -1 ||
+ ioctl(m_fd, SPI_IOC_WR_LSB_FIRST, &lsb) == -1)
+ {
+ Close();
+ return false;
+ }
+
+ return true;
+ }
+ bool GenKeyPair(int keyIdx) {
+ unsigned char header[] = {0x80, 0xb2, 0x00, (unsigned char)keyIdx, 0x00 };
+
+ int bytesWriten = Write(header, sizeof(header));
+ unsigned char buffer[2] = { 0 };
+ int bytesRead = Read(buffer, sizeof(buffer));
+ if (bytesRead > 0) {
+ int aa = 0;
+ } else {
+ int bb = 0;
+ }
+
+ return true;
+ }
+};
+
+static void set_baudrate (struct termios *opt, unsigned int baudrate)
+{
+ cfsetispeed(opt, baudrate);
+ cfsetospeed(opt, baudrate);
+}
+
+static void set_data_bit (struct termios *opt, unsigned int databit)
+{
+ opt->c_cflag &= ~CSIZE;
+ switch (databit)
+ {
+ case 8:
+ opt->c_cflag |= CS8;
+ break;
+ case 7:
+ opt->c_cflag |= CS7;
+ break;
+ case 6:
+ opt->c_cflag |= CS6;
+ break;
+ case 5:
+ opt->c_cflag |= CS5;
+ break;
+ default:
+ opt->c_cflag |= CS8;
+ break;
+ }
+}
+
+static void set_parity (struct termios *opt, char parity)
+{
+ switch (parity)
+ {
+ case'N':/* 无校验 */
+ case 'n':
+ opt->c_cflag &= ~PARENB;
+ break;
+ case'E':/*偶校验*/
+ case 'e':
+ opt->c_cflag |= PARENB;
+ opt->c_cflag &= ~PARODD;
+ break;
+ case'O':/* 奇校验 */
+ case 'o':
+ opt->c_cflag |= PARENB;
+ opt->c_cflag |= ~PARODD;
+ break;
+ default: /*其它选择为无校验 */
+ opt->c_cflag &= ~PARENB;
+ break;
+ }
+}
+
+static void set_stopbit (struct termios *opt, const char *stopbit)
+{
+ if (strcmp(stopbit, "1") == 0)
+ {
+ opt->c_cflag &= ~CSTOPB;/*1 位停止位 t */
+ }
+ else if(0 == strcmp(stopbit, "1.5"))
+ {
+ opt->c_cflag &= ~CSTOPB;/*1.5 位停止位 */
+ }
+ else if(0 == strcmp (stopbit,"2"))
+ {
+ opt->c_cflag |= CSTOPB; /*2 位停止位 */
+ }
+ else
+ {
+ opt->c_cflag &= ~CSTOPB; /*1 位停止位 */
+ }
+}
+
+int set_port_attr (int fd, int baudrate, int databit, const char *stopbit, char parity, int vtime, int vmin )
+{
+ struct termios opt;
+ tcgetattr(fd, &opt);
+ set_baudrate(&opt, baudrate);
+ opt.c_cflag |= CLOCAL|CREAD; /*|CRTSCTS */
+ set_data_bit(&opt, databit);
+ set_parity(&opt, parity);
+ set_stopbit(&opt, stopbit);
+ opt.c_oflag = 0;
+ opt.c_lflag |= 0;
+ opt.c_oflag &= ~OPOST;
+ opt.c_cc[VTIME] = vtime;
+ opt.c_cc[VMIN] = vmin;
+ tcflush (fd, TCIFLUSH);
+ return (tcsetattr (fd, TCSANOW, &opt));
+}
+#define MAX_STRING_LEN 32
+#define IOT_PARAM_WRITE 0xAE
+#define IOT_PARAM_READ 0xAF
+
+typedef struct
+{
+ int cmd;
+ int value;
+ int result;
+ long value2;
+ char str[MAX_STRING_LEN];
+}IOT_PARAM;
+
+#define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, "_test_", fmt, ##args)
+
+void setInt(int cmd, int value)
+{
+ int fd = open("/dev/mtkgpioctrl", O_RDONLY);
+ IOT_PARAM param;
+ param.cmd = cmd;
+ param.value = value;
+ // LOGE("set_int fd=%d,cmd=%d,value=%d\r\n",fd, cmd, value);
+ if( fd > 0 )
+ {
+ int res = ioctl(fd, IOT_PARAM_WRITE, ¶m);
+ // LOGE("set_int22 cmd=%d,value=%d,result=%d\r\n",param.cmd, param.value, param.result);
+ close(fd);
+ }
+ return;
+}
+static void setRS485Enable(bool z) {
+ setInt(CMD_SET_485_EN_STATE, z ? 1 : 0);
+}
+
+static void set485WriteMode() {
+ setInt(CMD_SET_485_STATE, 1);
+}
+
+static void set485ReadMode() {
+ setInt(CMD_SET_485_STATE, 0);
+}
+static void set12VEnable(bool z) {
+ setInt(CMD_SET_12V_EN_STATE, z ? 1 : 0);
+}
+
+int serial_port_comm()
+{
+ int fd;
+ int len, i,ret;
+ unsigned char sendbuf[] = {0x68,0x00,0x00,0x68,0xFF,0x02,0x01,0x16, 0x0D,0x0A};
+ char recvbuf[256];
+ char serial_description[] = "/dev/ttyS0";
+
+ DIR *dir = opendir("/dev");
+ if (dir == NULL) {
+ LOGE("_test_ opendir");
+ return -1;
+ }
+
+ // 读取目录项
+ struct dirent *entry;
+ while ((entry = readdir(dir)) != NULL) {
+ // 过滤出串口设备,通常以"ttyS"或"ttyUSB"开头
+ if ((strncmp(entry->d_name, "ttyS2", 5) == 0) ||
+ (strncmp(entry->d_name, "ttyS0", 5) == 0)) {
+ LOGE("_test_ Found serial port: %s\n", entry->d_name);
+ }
+ }
+
+ // 关闭目录
+ closedir(dir);
+
+ //fd = open(serial_description, O_RDWR | O_NDELAY);
+ fd = open(serial_description, O_RDWR | O_NOCTTY);
+ if(fd < 0)
+ {
+ LOGE("_test_ open serial error \n");
+ perror(serial_description);
+ return -1;
+ }
+ ret= set_port_attr (fd, B9600,8,"1",'N',150,0 );/*9600 8n1 */
+ if(ret < 0)
+ {
+ LOGE("_test_ set uart arrt faile \n");
+ exit(-1);
+ }
+ set485WriteMode();
+ len = write(fd, sendbuf, sizeof(sendbuf));/* 向串囗发送字符串 */
+ if (len < 0)
+ {
+ LOGE("_test_ write data error \n");
+ return -1;
+ }
+ set485ReadMode();
+ memset(recvbuf, 0, sizeof(recvbuf));
+ len = read(fd, recvbuf, sizeof(recvbuf));/* 在串口读取字符串 */
+ if (len < 0)
+ {
+ LOGE("_test_ read error \n");
+ return -1;
+ }
+ LOGE("_test_ recv=%s \n", recvbuf); /* 打印在串口读取的字符串 */
+ //lxy modify
+ close(fd);
+ return(0);
+}
+
+extern "C" JNIEXPORT jstring JNICALL
+Java_com_xinyingpower_testcomm_MainActivity_stringFromJNI(
+ JNIEnv* env,
+ jobject /* this */) {
+ std::string hello = "Hello from C++";
+ return env->NewStringUTF(hello.c_str());
+}
+
+extern "C" JNIEXPORT jstring JNICALL
+Java_com_xinyingpower_testcomm_MainActivity_testSpi(
+ JNIEnv* env,
+ jobject /* this */, jint port) {
+ //testSpi();
+ SpiLIb a;
+ unsigned char newkey[32]={0xaf,0x0c,0xa9,0x40,0x1f,0xe6,0xee,0x0f,0x4c,
+ 0xfb,0xf7,0x17,0x71,0xde,0x61,0x59
+ ,0x0a,0x05,0x77,
+ 0xfa,0xe7,0xd1,0x8d,0x10,0x3a,0x79,0x23,0xf2,0xb3,
+ 0x6d,0xea,0x8e
+// ,0xe0,0x64,0xe7,0x5d,0x49,0x84,0xe4,
+// 0x5f,0xc9,0x07,0x03,0x52,0x33,0x79,0x87,0xd4,0x62,
+// 0x62,0xc0,0xcc,0xf0,0xd6,0x85,0x20,0x7f,0x7a,0xe8,
+// 0xc8,0xed,0x12,0xdb,0xdc
+ };
+ unsigned char outpub[32],outsign[64], *outen = new unsigned char [256];
+ unsigned char pucid[16]={0x01,0x01,0x01,0x01,0x01,0x01,0x01,
+ 0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01,0x01};
+ string b="C=CN,ST=jiangsu,L=nanjing,O=GDD,OU=nari,CN=test001";
+ //a.SM2keypair(0x00);
+ //a.SM3Hash(newkey,16, outpub);
+ //a.sm3hash_tosm2(newkey,16,outpub,newkey,pucid,16);
+ //a.SM2Sign(0x00,outpub,outsign);
+ //a.SM2VerifySign(0x00,outpub,outsign);
+
+ //lxy modify modify
+ LOGE("_test_ setRS485Enable true");
+ setRS485Enable(true);
+
+ set12VEnable(true);
+ serial_port_comm();
+
+ //lxy modify modify
+ LOGE("_test_ setRS485Enable false");
+ setRS485Enable(false);
+ return env->NewStringUTF("");
+
+#if 0
+ DIR *dir = opendir("/dev");
+ if (dir == NULL) {
+ perror("opendir");
+ //return env->NewStringUTF("error");
+ //return -1;
+ }
+
+ // 读取目录项
+ struct dirent *entry;
+ while ((entry = readdir(dir)) != NULL) {
+ // 过滤出串口设备,通常以"ttyS"或"ttyUSB"开头
+ if ((strncmp(entry->d_name, "ttyS2", 5) == 0) ||
+ (strncmp(entry->d_name, "ttyS0", 5) == 0)) {
+ printf("Found serial port: %s\n", entry->d_name);
+ }
+ }
+
+ // 关闭目录
+ closedir(dir);
+#endif
+ a.SM2cert(0x00,0x00,b,outen);
+ for (int i = 0; i < 32; i++) {
+ //sprintf(output, " %02x ", rxbuf[i]);
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "%02x", outen[i]);
+ }
+// a.SM2decoder(0x00,outen,outpub);
+//
+// for (int i = 0; i < 64; i++) {
+// //sprintf(output, " %02x ", rxbuf[i]);
+// __android_log_print(ANDROID_LOG_INFO, "SPi", "%02x", outpub[i]);
+// }
+
+ //a.SM3Hash(0x00,0x10,newkey);
+ //testVersion();
+
+ return env->NewStringUTF("End");
+
+ // NrsecSpiPort spi("/dev/mtkgpioctrl");
+ NrsecSpiPort spi("/dev/spidevSE");
+
+ // NrsecSpiPort spi("/dev/spidev0.0");
+
+ if (!spi.Open()) {
+ return env->NewStringUTF(spi.GetLog().c_str());
+ }
+
+ spi.GenKeyPair(0);
+
+ unsigned char header[] = { 0x00, 0x5b, 0x00, 0x00, 0x40 };
+
+ int bytesWriten = spi.Write(header, sizeof(header));
+ unsigned char buffer[1024] = { 0 };
+ int bytesRead = spi.Read(buffer, 1);
+ if (bytesRead > 0) {
+ int aa = 0;
+ } else {
+ int bb = 0;
+ }
+ int len = buffer[0];
+ bytesRead += spi.Read(&buffer[1], len);
+
+ spi.Close();
+
+ std::string result;
+ char buf[32] = { 0 };
+ for (int idx = 0; idx < 32; idx++)
+ {
+ sprintf(buf, "%X ", buffer[idx]);
+ result += buf;
+ }
+
+
+
+ return env->NewStringUTF(result.c_str());
+}
+
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+//// lxy add
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+static speed_t getBaudrate(jint baudrate)
+{
+ switch(baudrate) {
+ case 0: return B0;
+ case 50: return B50;
+ case 75: return B75;
+ case 110: return B110;
+ case 134: return B134;
+ case 150: return B150;
+ case 200: return B200;
+ case 300: return B300;
+ case 600: return B600;
+ case 1200: return B1200;
+ case 1800: return B1800;
+ case 2400: return B2400;
+ case 4800: return B4800;
+ case 9600: return B9600;
+ case 19200: return B19200;
+ case 38400: return B38400;
+ case 57600: return B57600;
+ case 115200: return B115200;
+ case 230400: return B230400;
+ case 460800: return B460800;
+ case 500000: return B500000;
+ case 576000: return B576000;
+ case 921600: return B921600;
+ case 1000000: return B1000000;
+ case 1152000: return B1152000;
+ case 1500000: return B1500000;
+ case 2000000: return B2000000;
+ case 2500000: return B2500000;
+ case 3000000: return B3000000;
+ case 3500000: return B3500000;
+ case 4000000: return B4000000;
+ default: return -1;
+ }
+}
+char* jstring2str(JNIEnv* env, jstring jstr)
+{
+ char* rtn = NULL;
+ jclass clsstring = env->FindClass("java/lang/String");
+ jstring strencode = env->NewStringUTF("UTF-8");
+ jmethodID mid = env->GetMethodID(clsstring, "getBytes", "(Ljava/lang/String;)[B");
+ jbyteArray barr= (jbyteArray)env->CallObjectMethod(jstr,mid,strencode);
+ jsize alen = env->GetArrayLength(barr);
+ jbyte* ba = env->GetByteArrayElements(barr,JNI_FALSE);
+
+ if(alen > 0)
+ {
+ rtn = (char*)malloc(alen+1); //new char[alen+1];
+ memcpy(rtn,ba,alen);
+ rtn[alen] = 0;
+ }
+
+ env->ReleaseByteArrayElements(barr,ba,0);
+ return (char*)rtn;
+}
+
+
+int g_fd = -1;
+int serial_open(char *devPath, speed_t baudrate ) {
+ int ret = 0;
+ setRS485Enable(true);
+ int fd = open("/dev/ttyS0", O_RDWR |O_NOCTTY |O_NONBLOCK);
+ LOGE("_test_ serial_open fd=%d \n",fd);
+ if(fd < 0)
+ {
+ LOGE("_test_ open serial error \n");
+ return 0;
+ }
+ //ret= set_port_attr (fd, baudrate,8,"1",'N',150,0 );/*9600 8n1 */
+ ret= set_port_attr (fd, baudrate,8,"1",'N',150,0 );/*9600 8n1 */
+ if(ret < 0)
+ {
+ LOGE("_test_ set serial param fail \n");
+ return 0;
+ }
+ g_fd = fd;
+ return 1;
+}
+
+void serial_close()
+{
+ LOGE("_test_ serial_close fd=%d \n",g_fd);
+ if(g_fd != -1)
+ {
+ close(g_fd);
+ setRS485Enable(false);
+ }
+ g_fd = -1;
+}
+
+int serial_write(char *sendbuf, int length)
+{
+ int len = 0;
+ if(g_fd < 0)
+ return 0;
+ set485WriteMode();
+ len = write(g_fd, sendbuf, length);/* 向串囗发送字符串 */
+ LOGE("_test_ serial_write len=%d \n",len);
+ if (len < 0)
+ {
+ LOGE("_test_ write data error \n");
+ return 0;
+ }
+ return len;
+}
+
+int serial_read(char *readbuf,int length)
+{
+ int len = 0;
+ if(g_fd < 0)
+ return 0;
+ set485ReadMode();
+ memset(readbuf, 0, length);
+ len = read(g_fd, readbuf, length);/* 在串口读取字符串 */
+ LOGE("_test_ serial_read len=%d \n",len);
+ if (len < 0)
+ {
+ //LOGE("_test_ read error \n");
+ return 0;
+ }
+ return len;
+}
+
+extern "C" JNIEXPORT jboolean JNICALL Java_com_xinyingpower_testcomm_MainActivity_openSerial
+(JNIEnv* env, jobject, jstring dev, jint baudrate) {
+ char *devPath = jstring2str(env, dev);
+ LOGE("_test open serial path=%s, baudrate=%d\n", devPath, baudrate);
+ speed_t speed = getBaudrate(baudrate);
+ int res = serial_open(devPath, speed);
+ return res == 1 ? JNI_TRUE: JNI_FALSE;
+}
+
+extern "C" JNIEXPORT void JNICALL Java_com_xinyingpower_testcomm_MainActivity_closeSerial
+ (JNIEnv* env, jobject) {
+ serial_close();
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_com_xinyingpower_testcomm_MainActivity_writeSerial
+ (JNIEnv *env, jobject , jbyteArray jstr) {
+ jsize len = env->GetArrayLength(jstr);
+ if (len <= 0)
+ return 0;
+ jbyte *jdata = env->GetByteArrayElements(jstr, 0);
+ int res = serial_write((char*)jdata, len);
+ env->ReleaseByteArrayElements(jstr, jdata, 0);
+ return res;
+}
+
+extern "C" JNIEXPORT jint JNICALL Java_com_xinyingpower_testcomm_MainActivity_readSerial
+ (JNIEnv *env, jobject, jbyteArray out)
+{
+ jsize outlen = env->GetArrayLength(out);
+ //LOGE("_test readSerial outlen=%d\n", outlen);
+ if(outlen <= 0)
+ return 0;
+ jbyte* outData = env->GetByteArrayElements(out, 0);
+ char* outbuf = (char*)outData;
+ int res = serial_read(outbuf, outlen);
+ //LOGE("_test serial_read res=%d\n", res);
+ env->ReleaseByteArrayElements(out, outData, 0);
+ return res;
+}
\ No newline at end of file
diff --git a/TestComm/app/src/main/cpp/spi-test-random.cpp b/TestComm/app/src/main/cpp/spi-test-random.cpp
new file mode 100644
index 00000000..e519010a
--- /dev/null
+++ b/TestComm/app/src/main/cpp/spi-test-random.cpp
@@ -0,0 +1,426 @@
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+#include
+#include
+#include
+
+#include
+#include
+
+#include
+
+#define CMD_HEAD_SIZE 5
+typedef unsigned char u8;
+
+#define RE_SUC 0x01
+#define RE_ERROR 0x00
+
+const unsigned char crc7_table[256] = {
+ 0x00, 0x09, 0x12, 0x1b, 0x24, 0x2d, 0x36, 0x3f,
+ 0x48, 0x41, 0x5a, 0x53, 0x6c, 0x65, 0x7e, 0x77,
+ 0x19, 0x10, 0x0b, 0x02, 0x3d, 0x34, 0x2f, 0x26,
+ 0x51, 0x58, 0x43, 0x4a, 0x75, 0x7c, 0x67, 0x6e,
+ 0x32, 0x3b, 0x20, 0x29, 0x16, 0x1f, 0x04, 0x0d,
+ 0x7a, 0x73, 0x68, 0x61, 0x5e, 0x57, 0x4c, 0x45,
+ 0x2b, 0x22, 0x39, 0x30, 0x0f, 0x06, 0x1d, 0x14,
+ 0x63, 0x6a, 0x71, 0x78, 0x47, 0x4e, 0x55, 0x5c,
+ 0x64, 0x6d, 0x76, 0x7f, 0x40, 0x49, 0x52, 0x5b,
+ 0x2c, 0x25, 0x3e, 0x37, 0x08, 0x01, 0x1a, 0x13,
+ 0x7d, 0x74, 0x6f, 0x66, 0x59, 0x50, 0x4b, 0x42,
+ 0x35, 0x3c, 0x27, 0x2e, 0x11, 0x18, 0x03, 0x0a,
+ 0x56, 0x5f, 0x44, 0x4d, 0x72, 0x7b, 0x60, 0x69,
+ 0x1e, 0x17, 0x0c, 0x05, 0x3a, 0x33, 0x28, 0x21,
+ 0x4f, 0x46, 0x5d, 0x54, 0x6b, 0x62, 0x79, 0x70,
+ 0x07, 0x0e, 0x15, 0x1c, 0x23, 0x2a, 0x31, 0x38,
+ 0x41, 0x48, 0x53, 0x5a, 0x65, 0x6c, 0x77, 0x7e,
+ 0x09, 0x00, 0x1b, 0x12, 0x2d, 0x24, 0x3f, 0x36,
+ 0x58, 0x51, 0x4a, 0x43, 0x7c, 0x75, 0x6e, 0x67,
+ 0x10, 0x19, 0x02, 0x0b, 0x34, 0x3d, 0x26, 0x2f,
+ 0x73, 0x7a, 0x61, 0x68, 0x57, 0x5e, 0x45, 0x4c,
+ 0x3b, 0x32, 0x29, 0x20, 0x1f, 0x16, 0x0d, 0x04,
+ 0x6a, 0x63, 0x78, 0x71, 0x4e, 0x47, 0x5c, 0x55,
+ 0x22, 0x2b, 0x30, 0x39, 0x06, 0x0f, 0x14, 0x1d,
+ 0x25, 0x2c, 0x37, 0x3e, 0x01, 0x08, 0x13, 0x1a,
+ 0x6d, 0x64, 0x7f, 0x76, 0x49, 0x40, 0x5b, 0x52,
+ 0x3c, 0x35, 0x2e, 0x27, 0x18, 0x11, 0x0a, 0x03,
+ 0x74, 0x7d, 0x66, 0x6f, 0x50, 0x59, 0x42, 0x4b,
+ 0x17, 0x1e, 0x05, 0x0c, 0x33, 0x3a, 0x21, 0x28,
+ 0x5f, 0x56, 0x4d, 0x44, 0x7b, 0x72, 0x69, 0x60,
+ 0x0e, 0x07, 0x1c, 0x15, 0x2a, 0x23, 0x38, 0x31,
+ 0x46, 0x4f, 0x54, 0x5d, 0x62, 0x6b, 0x70, 0x79
+};
+
+const unsigned char EK_CMD[5]={0x80,0xd4,0x01,0x00,0x10};
+const unsigned char AK_CMD[5]={0x80,0xd4,0x02,0x00,0x10};
+const unsigned char IV_CMD[5]={0x80,0xd4,0x04,0x00,0x10};
+volatile unsigned char SM1encrpt_CMD[5]={0xa0,0xe0,0x80,0xff,0xff};
+volatile unsigned char SM1decoder_CMD[5]={0xa0,0xe0,0x81,0xff,0xff};
+volatile unsigned char SM2Keypair_CMD[5]={0x80,0xb2,0x00,0xff,0x00};
+volatile unsigned char SM2OutPub_CMD[5]={0x80,0xb8,0x01,0xff,0x40};
+volatile unsigned char SM2OutPri_CMD[5]={0x80,0xb8,0x02,0xff,0x20};
+volatile unsigned char SM2InPub_CMD[5]={0x80,0xba,0x01,0xff,0x40};
+volatile unsigned char SM2InPri_CMD[5]={0x80,0xba,0x02,0xff,0x20};
+volatile unsigned char SM3Hash_CMD[5]={0x80,0xb5,0x00,0xff,0xff};
+volatile unsigned char SM2Sign_CMD[5]={0x80,0xb4,0x00,0xff,0x20};
+volatile unsigned char SM2VerifySign_CMD[5]={0x80,0xb6,0x00,0xff,0x60};
+volatile unsigned char SM2encrypt_CMD[5]={0x80,0xb3,0x01,0xff,0x20};
+volatile unsigned char SM2decoder_CMD[5]={0x80,0xb3,0x81,0xff,0x80};
+volatile unsigned char SM2cert_CMD[5]={0x80,0xb7,0xff,0xff,0xff};
+volatile unsigned char Random_CMD[5]={0x00,0x84,0x00,0x00,0xff};
+const unsigned char Version_CMD[5]={0x00,0x5b,0x00,0x00,0x40};
+const unsigned char Indentify_CMD[5]={0x80,0xb3,0x01,0x04,0x20};
+
+int spi_transfer(int fd, unsigned char *txbuf, unsigned char *rxbuf, int bytes)
+{
+ struct spi_ioc_transfer xfer[2];
+ int status;
+
+ memset(xfer, 0, sizeof(xfer));
+
+ xfer[0].tx_buf = (__u64)txbuf;
+ xfer[0].rx_buf = (__u64)rxbuf;
+ xfer[0].len = bytes;
+
+ status = ioctl(fd, SPI_IOC_MESSAGE(1), xfer);
+ if (status < 0)
+ {
+ perror("SPI_IOC_MESSAGE");
+ return -1;
+ }
+
+ return status;
+
+}
+
+void spi_master_init(const char *name, int fd)
+{
+ __u8 mode = 3;
+ __u8 lsb, bits;
+ //__u32 speed = 30000000;
+ __u32 speed = 2000000;
+ //__u32 speed = 2000000;
+ //__u32 speed = 33000000;
+
+ // SPI_IOC_WR_MODE
+
+ ioctl(fd, SPI_IOC_WR_MODE, &mode);
+ ioctl(fd, SPI_IOC_WR_MAX_SPEED_HZ, &speed);
+
+ if (ioctl(fd, SPI_IOC_RD_MODE, &mode) < 0)
+ {
+ perror("SPI rd_mode");
+ return;
+ }
+
+ if (ioctl(fd, SPI_IOC_RD_LSB_FIRST, &lsb) < 0)
+ {
+ perror("SPI rd_lsb_fist");
+ return;
+ }
+
+ if (ioctl(fd, SPI_IOC_RD_BITS_PER_WORD, &bits) < 0)
+ {
+ perror("SPI rd bits_per_word");
+ return;
+ }
+
+ if (ioctl(fd, SPI_IOC_RD_MAX_SPEED_HZ, &speed) < 0)
+ {
+ perror("SPI rd max_speed_hz");
+ return;
+ }
+
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "%s: spi mode %d, %d bits %sper word, %d Hz max\n", name, mode, bits, lsb ? "(lsb first) " : "", speed);
+ //printf("%s: spi mode %d, %d bits %sper word, %d Hz max\n",
+ // name, mode, bits, lsb ? "(lsb first) " : "", speed);
+}
+
+unsigned char get_crc7(const unsigned char *buff, int len)
+{
+ unsigned char crc7_accum = 0;
+ int i;
+
+ for (i=0; i < len; i++) {
+ crc7_accum =
+ crc7_table[(crc7_accum << 1) ^ buff[i]];
+ }
+ return crc7_accum;
+}
+
+int delay(int x)
+{
+ // while (--x);
+ // std::this_thread::sleep_for(std::chrono::milliseconds(50));
+ usleep(50000);
+ return 0;
+}
+
+void delay_us(int x)
+{
+ usleep(x);
+};
+
+void SendCmdHeader(int fd,u8 *cmd, u8 *rxbuf)
+{
+ int i=0;
+ int retval;
+
+#if defined (CONFIG_ATMEL_SPI_DEBUG)
+ printf("tx %1d bytes: ", CMD_HEAD_SIZE);
+ for (i = 0; i < CMD_HEAD_SIZE; i++)
+ {
+ printf(" %02x", cmd[i]);
+ }
+ printf("\n");
+#endif
+
+ /* send five command header */
+ for (i=0; i< CMD_HEAD_SIZE; i++)
+ {
+ retval = spi_transfer(fd, cmd+i, rxbuf+i, 1);
+ __android_log_print(ANDROID_LOG_INFO, "SPiCMD", "cmd[%d]=%x,rxbuf[%d]=%x",i,*(cmd+i),i, *(rxbuf+i));
+ delay(20);
+ }
+
+ cmd[0]=0xaa; //for response
+
+}
+
+void RcvINS(int fd, u8 *txbuf, u8 *buf, u8 ins)
+{
+ int retval;
+ int cnt = 1000;
+ int count=0;
+ /* receive ins */
+INS:
+ txbuf[0] = 0xaa;
+ delay(20);
+ while(cnt--)
+ {
+ retval = spi_transfer(fd, txbuf, buf, 1);
+ __android_log_print(ANDROID_LOG_INFO, "SPiINS", "txbuf=%x,buf=%x", *txbuf,*buf);
+ if(*buf == ins)
+ {
+ return;
+ break;
+ }
+ else
+ goto INS;
+ }
+}
+
+void RcvLEN(int fd, u8 *txbuf, u8 *buf, u8 len)
+{
+
+ int retval;
+ /* receive length */
+LEN:
+ retval = spi_transfer(fd, txbuf, buf, 1);
+ __android_log_print(ANDROID_LOG_INFO, "SPiLEN", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf);
+}
+
+//Rcvdata
+void RcvData(int fd, u8 *txbuf, u8 *buf)
+{
+ int i;
+ int retval;
+
+ /* receive data and crc */
+ for(i=0; i<*(buf-1); i++)
+ {
+
+ retval = spi_transfer(fd, txbuf, buf+i, 1);
+ __android_log_print(ANDROID_LOG_INFO, "SPiDATA", "data[%d]=%x",i, *(buf+i));
+ }
+}
+
+
+//RcvSW
+void RcvSW(int fd, u8 *txbuf, u8 *buf, u8 sw)
+{
+ int i;
+ int retval;
+
+SW90:
+ /* receive state word */
+ delay(20);
+ while(1)
+ {
+ retval = spi_transfer(fd, txbuf, buf, 1);
+ if(*buf != sw)
+ {
+ goto SW90;
+ }
+ break;
+ }
+ retval = spi_transfer(fd, txbuf, buf+1, 1);
+}
+
+
+int testSpi()
+{
+ int i;
+ int cnt;
+ unsigned char txbuf[256];
+ unsigned char rxbuf[256];
+
+ int retval;
+ int msglen;
+ int fd;
+ const char *devname = "/dev/spidevSE";
+
+
+ // NrsecSpiPort spi("/dev/spidevSE");
+ //
+ // // NrsecSpiPort spi("/dev/spidev0.0");
+ // devname = "/dev/spidevSE";
+
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ spi_master_init(devname, fd);
+
+
+ msglen = 5;
+ memset(rxbuf, 0, sizeof(rxbuf));
+ memset(txbuf, 0, sizeof(txbuf));
+
+ printf("tx %1d bytes: ", msglen);
+
+CMD_RESEND:
+ txbuf[0] = 0x00;
+ txbuf[1] = 0x84;
+ txbuf[2] = 0x00;
+ txbuf[3] = 0x00;
+ txbuf[4] = 0x08;
+
+ SendCmdHeader(fd, txbuf, rxbuf);
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令
+
+ RcvLEN(fd, txbuf,rxbuf+1, txbuf[4]+1); //长度 多加一个字节的 CRC
+
+ RcvData(fd, txbuf, rxbuf+2);
+
+ RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90);
+
+ //计算接收到数据的CRC
+ if(get_crc7(rxbuf+2, rxbuf[1]-1) != rxbuf[rxbuf[1]+1])
+ {
+ //CRC Error 命令重发,超过3次,结束
+ if(cnt<3)
+ {
+ cnt++;
+ goto CMD_RESEND;
+ printf("cnt over\n");
+ }
+ else
+ {
+ printf("ERROR\n");
+ }
+ }
+
+ printf("rx %1d bytes: ", rxbuf[1]+4);
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4);
+ close(fd);
+
+ std::string result = "Random: ";
+ char output[16] = { 0 };
+ for (i = 0; i < rxbuf[1]+4; i++) {
+ sprintf(output, " %02x ", rxbuf[i]);
+ result += output;
+ }
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str());
+ // printf("\n");
+
+ return 0;
+}
+
+int testVersion()
+{
+ int i;
+ int cnt;
+ unsigned char txbuf[256];
+ unsigned char rxbuf[256];
+
+ int retval;
+ int msglen;
+ int fd;
+ //const char *devname = "/dev/spidevSE";
+ //const char *devname = "/dev/spidev0.0";
+ const char *devname = "/dev/mtkgpioctrl";
+
+ // NrsecSpiPort spi("/dev/spidevSE");
+ //
+ // // NrsecSpiPort spi("/dev/spidev0.0");
+
+ fd = open(devname, O_RDWR);
+ if (fd < 0) {
+ perror("open");
+ return 1;
+ }
+ spi_master_init(devname, fd);
+
+
+ msglen = 5;
+ memset(rxbuf, 0, sizeof(rxbuf));
+ memset(txbuf, 0, sizeof(txbuf));
+
+ //printf("tx %1d bytes: ", msglen);
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
+
+ CMD_RESEND:
+
+ memcpy(txbuf, Version_CMD, sizeof(Version_CMD));
+
+ SendCmdHeader(fd, txbuf, rxbuf);
+
+ RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令
+
+ RcvLEN(fd,txbuf,rxbuf+1, txbuf[4]); //长度 多加一个字节的 CRC
+
+ RcvData(fd, txbuf, rxbuf+2);
+
+ RcvSW(fd, txbuf, rxbuf+2+rxbuf[1], 0x90);
+
+ //计算接收到数据的CRC
+ if(get_crc7(rxbuf+2, rxbuf[1]-1) != rxbuf[rxbuf[1]+1])
+ {
+ //CRC Error 命令重发,超过3次,结束
+ if(cnt<3)
+ {
+ cnt++;
+ goto CMD_RESEND;
+ printf("cnt over\n");
+ }
+ else
+ {
+ printf("ERROR\n");
+ }
+ }
+
+ //printf("rx %1d bytes: ", rxbuf[1]+4);
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "rx %1d bytes:", rxbuf[1]+4);
+ std::string result = "Version: ";
+ char output[16] = { 0 };
+ for (i = 0; i < rxbuf[1]+4; i++) {
+ sprintf(output, " %c ", rxbuf[i]);
+ result += output;
+ }
+ __android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str());
+ //__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", rxbuf);
+ // printf("\n");
+
+ close(fd);
+ return 0;
+}
+
+
diff --git a/TestComm/app/src/main/cpp/test b/TestComm/app/src/main/cpp/test
new file mode 100644
index 00000000..e69de29b
diff --git a/TestComm/app/src/main/java/com/xinyingpower/testcomm/MainActivity.java b/TestComm/app/src/main/java/com/xinyingpower/testcomm/MainActivity.java
new file mode 100644
index 00000000..e731c731
--- /dev/null
+++ b/TestComm/app/src/main/java/com/xinyingpower/testcomm/MainActivity.java
@@ -0,0 +1,59 @@
+package com.xinyingpower.testcomm;
+
+import androidx.appcompat.app.AppCompatActivity;
+
+import android.os.Bundle;
+import android.os.Handler;
+import android.view.View;
+import android.widget.TextView;
+
+import com.xinyingpower.testcomm.databinding.ActivityMainBinding;
+
+public class MainActivity extends AppCompatActivity {
+
+ // Used to load the 'testcomm' library on application startup.
+ static {
+ System.loadLibrary("testcomm");
+ }
+
+ private ActivityMainBinding binding;
+
+ @Override
+ protected void onCreate(Bundle savedInstanceState) {
+ super.onCreate(savedInstanceState);
+
+ binding = ActivityMainBinding.inflate(getLayoutInflater());
+ setContentView(binding.getRoot());
+
+ // Example of a call to a native method
+ TextView tv = binding.sampleText;
+ // tv.setText(stringFromJNI());
+
+ binding.btnSpi.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ String str = testSpi(0);
+ binding.sampleText.setText(str);
+ }
+ });
+
+ Handler handler = new Handler();
+ Runnable runnable = new Runnable() {
+ @Override
+ public void run() {
+ binding.btnSpi.performClick();
+ }
+ };
+ handler.postDelayed(runnable, 1000);
+ }
+
+
+
+ /**
+ * A native method that is implemented by the 'testcomm' native library,
+ * which is packaged with this application.
+ */
+ public native String stringFromJNI();
+
+ public native String testSpi(int port);
+}
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/drawable-v24/ic_launcher_foreground.xml b/TestComm/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
new file mode 100644
index 00000000..2b068d11
--- /dev/null
+++ b/TestComm/app/src/main/res/drawable-v24/ic_launcher_foreground.xml
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/drawable/ic_launcher_background.xml b/TestComm/app/src/main/res/drawable/ic_launcher_background.xml
new file mode 100644
index 00000000..07d5da9c
--- /dev/null
+++ b/TestComm/app/src/main/res/drawable/ic_launcher_background.xml
@@ -0,0 +1,170 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/TestComm/app/src/main/res/layout/activity_main.xml b/TestComm/app/src/main/res/layout/activity_main.xml
new file mode 100644
index 00000000..458f1c53
--- /dev/null
+++ b/TestComm/app/src/main/res/layout/activity_main.xml
@@ -0,0 +1,28 @@
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml b/TestComm/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/TestComm/app/src/main/res/mipmap-anydpi-v26/ic_launcher.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml b/TestComm/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
new file mode 100644
index 00000000..eca70cfe
--- /dev/null
+++ b/TestComm/app/src/main/res/mipmap-anydpi-v26/ic_launcher_round.xml
@@ -0,0 +1,5 @@
+
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/mipmap-hdpi/ic_launcher.webp b/TestComm/app/src/main/res/mipmap-hdpi/ic_launcher.webp
new file mode 100644
index 00000000..c209e78e
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-hdpi/ic_launcher.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp b/TestComm/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..b2dfe3d1
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-hdpi/ic_launcher_round.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-mdpi/ic_launcher.webp b/TestComm/app/src/main/res/mipmap-mdpi/ic_launcher.webp
new file mode 100644
index 00000000..4f0f1d64
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-mdpi/ic_launcher.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp b/TestComm/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..62b611da
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-mdpi/ic_launcher_round.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-xhdpi/ic_launcher.webp b/TestComm/app/src/main/res/mipmap-xhdpi/ic_launcher.webp
new file mode 100644
index 00000000..948a3070
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-xhdpi/ic_launcher.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp b/TestComm/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..1b9a6956
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-xhdpi/ic_launcher_round.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp b/TestComm/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..28d4b77f
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-xxhdpi/ic_launcher.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp b/TestComm/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9287f508
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-xxhdpi/ic_launcher_round.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp b/TestComm/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp
new file mode 100644
index 00000000..aa7d6427
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-xxxhdpi/ic_launcher.webp differ
diff --git a/TestComm/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp b/TestComm/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp
new file mode 100644
index 00000000..9126ae37
Binary files /dev/null and b/TestComm/app/src/main/res/mipmap-xxxhdpi/ic_launcher_round.webp differ
diff --git a/TestComm/app/src/main/res/values-night/themes.xml b/TestComm/app/src/main/res/values-night/themes.xml
new file mode 100644
index 00000000..48eb05a0
--- /dev/null
+++ b/TestComm/app/src/main/res/values-night/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/values/colors.xml b/TestComm/app/src/main/res/values/colors.xml
new file mode 100644
index 00000000..f8c6127d
--- /dev/null
+++ b/TestComm/app/src/main/res/values/colors.xml
@@ -0,0 +1,10 @@
+
+
+ #FFBB86FC
+ #FF6200EE
+ #FF3700B3
+ #FF03DAC5
+ #FF018786
+ #FF000000
+ #FFFFFFFF
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/values/strings.xml b/TestComm/app/src/main/res/values/strings.xml
new file mode 100644
index 00000000..c69dab86
--- /dev/null
+++ b/TestComm/app/src/main/res/values/strings.xml
@@ -0,0 +1,3 @@
+
+ TestComm
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/values/themes.xml b/TestComm/app/src/main/res/values/themes.xml
new file mode 100644
index 00000000..3bc189d5
--- /dev/null
+++ b/TestComm/app/src/main/res/values/themes.xml
@@ -0,0 +1,16 @@
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/xml/backup_rules.xml b/TestComm/app/src/main/res/xml/backup_rules.xml
new file mode 100644
index 00000000..fa0f996d
--- /dev/null
+++ b/TestComm/app/src/main/res/xml/backup_rules.xml
@@ -0,0 +1,13 @@
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/main/res/xml/data_extraction_rules.xml b/TestComm/app/src/main/res/xml/data_extraction_rules.xml
new file mode 100644
index 00000000..9ee9997b
--- /dev/null
+++ b/TestComm/app/src/main/res/xml/data_extraction_rules.xml
@@ -0,0 +1,19 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/TestComm/app/src/test/java/com/xinyingpower/testcomm/ExampleUnitTest.java b/TestComm/app/src/test/java/com/xinyingpower/testcomm/ExampleUnitTest.java
new file mode 100644
index 00000000..b70d146d
--- /dev/null
+++ b/TestComm/app/src/test/java/com/xinyingpower/testcomm/ExampleUnitTest.java
@@ -0,0 +1,17 @@
+package com.xinyingpower.testcomm;
+
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * Example local unit test, which will execute on the development machine (host).
+ *
+ * @see Testing documentation
+ */
+public class ExampleUnitTest {
+ @Test
+ public void addition_isCorrect() {
+ assertEquals(4, 2 + 2);
+ }
+}
\ No newline at end of file
diff --git a/TestComm/build.gradle b/TestComm/build.gradle
new file mode 100644
index 00000000..5ae9a7b0
--- /dev/null
+++ b/TestComm/build.gradle
@@ -0,0 +1,9 @@
+// Top-level build file where you can add configuration options common to all sub-projects/modules.
+plugins {
+ id 'com.android.application' version '7.2.2' apply false
+ id 'com.android.library' version '7.2.2' apply false
+}
+
+task clean(type: Delete) {
+ delete rootProject.buildDir
+}
\ No newline at end of file
diff --git a/TestComm/gradle.properties b/TestComm/gradle.properties
new file mode 100644
index 00000000..dab7c28b
--- /dev/null
+++ b/TestComm/gradle.properties
@@ -0,0 +1,21 @@
+# Project-wide Gradle settings.
+# IDE (e.g. Android Studio) users:
+# Gradle settings configured through the IDE *will override*
+# any settings specified in this file.
+# For more details on how to configure your build environment visit
+# http://www.gradle.org/docs/current/userguide/build_environment.html
+# Specifies the JVM arguments used for the daemon process.
+# The setting is particularly useful for tweaking memory settings.
+org.gradle.jvmargs=-Xmx2048m -Dfile.encoding=UTF-8
+# When configured, Gradle will run in incubating parallel mode.
+# This option should only be used with decoupled projects. More details, visit
+# http://www.gradle.org/docs/current/userguide/multi_project_builds.html#sec:decoupled_projects
+# org.gradle.parallel=true
+# AndroidX package structure to make it clearer which packages are bundled with the
+# Android operating system, and which are packaged with your app"s APK
+# https://developer.android.com/topic/libraries/support-library/androidx-rn
+android.useAndroidX=true
+# Enables namespacing of each library's R class so that its R class includes only the
+# resources declared in the library itself and none from the library's dependencies,
+# thereby reducing the size of the R class for that library
+android.nonTransitiveRClass=true
\ No newline at end of file
diff --git a/TestComm/gradle/wrapper/gradle-wrapper.jar b/TestComm/gradle/wrapper/gradle-wrapper.jar
new file mode 100644
index 00000000..e708b1c0
Binary files /dev/null and b/TestComm/gradle/wrapper/gradle-wrapper.jar differ
diff --git a/TestComm/gradle/wrapper/gradle-wrapper.properties b/TestComm/gradle/wrapper/gradle-wrapper.properties
new file mode 100644
index 00000000..f65e2179
--- /dev/null
+++ b/TestComm/gradle/wrapper/gradle-wrapper.properties
@@ -0,0 +1,7 @@
+#Tue Apr 02 12:39:24 CST 2024
+distributionBase=GRADLE_USER_HOME
+distributionUrl=https\://mirrors.cloud.tencent.com/gradle/gradle-7.3.3-bin.zip
+
+distributionPath=wrapper/dists
+zipStorePath=wrapper/dists
+zipStoreBase=GRADLE_USER_HOME
diff --git a/TestComm/gradlew b/TestComm/gradlew
new file mode 100644
index 00000000..4f906e0c
--- /dev/null
+++ b/TestComm/gradlew
@@ -0,0 +1,185 @@
+#!/usr/bin/env sh
+
+#
+# Copyright 2015 the original author or authors.
+#
+# Licensed under the Apache License, Version 2.0 (the "License");
+# you may not use this file except in compliance with the License.
+# You may obtain a copy of the License at
+#
+# https://www.apache.org/licenses/LICENSE-2.0
+#
+# Unless required by applicable law or agreed to in writing, software
+# distributed under the License is distributed on an "AS IS" BASIS,
+# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+# See the License for the specific language governing permissions and
+# limitations under the License.
+#
+
+##############################################################################
+##
+## Gradle start up script for UN*X
+##
+##############################################################################
+
+# Attempt to set APP_HOME
+# Resolve links: $0 may be a link
+PRG="$0"
+# Need this for relative symlinks.
+while [ -h "$PRG" ] ; do
+ ls=`ls -ld "$PRG"`
+ link=`expr "$ls" : '.*-> \(.*\)$'`
+ if expr "$link" : '/.*' > /dev/null; then
+ PRG="$link"
+ else
+ PRG=`dirname "$PRG"`"/$link"
+ fi
+done
+SAVED="`pwd`"
+cd "`dirname \"$PRG\"`/" >/dev/null
+APP_HOME="`pwd -P`"
+cd "$SAVED" >/dev/null
+
+APP_NAME="Gradle"
+APP_BASE_NAME=`basename "$0"`
+
+# Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+DEFAULT_JVM_OPTS='"-Xmx64m" "-Xms64m"'
+
+# Use the maximum available, or set MAX_FD != -1 to use that value.
+MAX_FD="maximum"
+
+warn () {
+ echo "$*"
+}
+
+die () {
+ echo
+ echo "$*"
+ echo
+ exit 1
+}
+
+# OS specific support (must be 'true' or 'false').
+cygwin=false
+msys=false
+darwin=false
+nonstop=false
+case "`uname`" in
+ CYGWIN* )
+ cygwin=true
+ ;;
+ Darwin* )
+ darwin=true
+ ;;
+ MINGW* )
+ msys=true
+ ;;
+ NONSTOP* )
+ nonstop=true
+ ;;
+esac
+
+CLASSPATH=$APP_HOME/gradle/wrapper/gradle-wrapper.jar
+
+
+# Determine the Java command to use to start the JVM.
+if [ -n "$JAVA_HOME" ] ; then
+ if [ -x "$JAVA_HOME/jre/sh/java" ] ; then
+ # IBM's JDK on AIX uses strange locations for the executables
+ JAVACMD="$JAVA_HOME/jre/sh/java"
+ else
+ JAVACMD="$JAVA_HOME/bin/java"
+ fi
+ if [ ! -x "$JAVACMD" ] ; then
+ die "ERROR: JAVA_HOME is set to an invalid directory: $JAVA_HOME
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+ fi
+else
+ JAVACMD="java"
+ which java >/dev/null 2>&1 || die "ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+
+Please set the JAVA_HOME variable in your environment to match the
+location of your Java installation."
+fi
+
+# Increase the maximum file descriptors if we can.
+if [ "$cygwin" = "false" -a "$darwin" = "false" -a "$nonstop" = "false" ] ; then
+ MAX_FD_LIMIT=`ulimit -H -n`
+ if [ $? -eq 0 ] ; then
+ if [ "$MAX_FD" = "maximum" -o "$MAX_FD" = "max" ] ; then
+ MAX_FD="$MAX_FD_LIMIT"
+ fi
+ ulimit -n $MAX_FD
+ if [ $? -ne 0 ] ; then
+ warn "Could not set maximum file descriptor limit: $MAX_FD"
+ fi
+ else
+ warn "Could not query maximum file descriptor limit: $MAX_FD_LIMIT"
+ fi
+fi
+
+# For Darwin, add options to specify how the application appears in the dock
+if $darwin; then
+ GRADLE_OPTS="$GRADLE_OPTS \"-Xdock:name=$APP_NAME\" \"-Xdock:icon=$APP_HOME/media/gradle.icns\""
+fi
+
+# For Cygwin or MSYS, switch paths to Windows format before running java
+if [ "$cygwin" = "true" -o "$msys" = "true" ] ; then
+ APP_HOME=`cygpath --path --mixed "$APP_HOME"`
+ CLASSPATH=`cygpath --path --mixed "$CLASSPATH"`
+
+ JAVACMD=`cygpath --unix "$JAVACMD"`
+
+ # We build the pattern for arguments to be converted via cygpath
+ ROOTDIRSRAW=`find -L / -maxdepth 1 -mindepth 1 -type d 2>/dev/null`
+ SEP=""
+ for dir in $ROOTDIRSRAW ; do
+ ROOTDIRS="$ROOTDIRS$SEP$dir"
+ SEP="|"
+ done
+ OURCYGPATTERN="(^($ROOTDIRS))"
+ # Add a user-defined pattern to the cygpath arguments
+ if [ "$GRADLE_CYGPATTERN" != "" ] ; then
+ OURCYGPATTERN="$OURCYGPATTERN|($GRADLE_CYGPATTERN)"
+ fi
+ # Now convert the arguments - kludge to limit ourselves to /bin/sh
+ i=0
+ for arg in "$@" ; do
+ CHECK=`echo "$arg"|egrep -c "$OURCYGPATTERN" -`
+ CHECK2=`echo "$arg"|egrep -c "^-"` ### Determine if an option
+
+ if [ $CHECK -ne 0 ] && [ $CHECK2 -eq 0 ] ; then ### Added a condition
+ eval `echo args$i`=`cygpath --path --ignore --mixed "$arg"`
+ else
+ eval `echo args$i`="\"$arg\""
+ fi
+ i=`expr $i + 1`
+ done
+ case $i in
+ 0) set -- ;;
+ 1) set -- "$args0" ;;
+ 2) set -- "$args0" "$args1" ;;
+ 3) set -- "$args0" "$args1" "$args2" ;;
+ 4) set -- "$args0" "$args1" "$args2" "$args3" ;;
+ 5) set -- "$args0" "$args1" "$args2" "$args3" "$args4" ;;
+ 6) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" ;;
+ 7) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" ;;
+ 8) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" ;;
+ 9) set -- "$args0" "$args1" "$args2" "$args3" "$args4" "$args5" "$args6" "$args7" "$args8" ;;
+ esac
+fi
+
+# Escape application args
+save () {
+ for i do printf %s\\n "$i" | sed "s/'/'\\\\''/g;1s/^/'/;\$s/\$/' \\\\/" ; done
+ echo " "
+}
+APP_ARGS=`save "$@"`
+
+# Collect all arguments for the java command, following the shell quoting and substitution rules
+eval set -- $DEFAULT_JVM_OPTS $JAVA_OPTS $GRADLE_OPTS "\"-Dorg.gradle.appname=$APP_BASE_NAME\"" -classpath "\"$CLASSPATH\"" org.gradle.wrapper.GradleWrapperMain "$APP_ARGS"
+
+exec "$JAVACMD" "$@"
diff --git a/TestComm/gradlew.bat b/TestComm/gradlew.bat
new file mode 100644
index 00000000..107acd32
--- /dev/null
+++ b/TestComm/gradlew.bat
@@ -0,0 +1,89 @@
+@rem
+@rem Copyright 2015 the original author or authors.
+@rem
+@rem Licensed under the Apache License, Version 2.0 (the "License");
+@rem you may not use this file except in compliance with the License.
+@rem You may obtain a copy of the License at
+@rem
+@rem https://www.apache.org/licenses/LICENSE-2.0
+@rem
+@rem Unless required by applicable law or agreed to in writing, software
+@rem distributed under the License is distributed on an "AS IS" BASIS,
+@rem WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+@rem See the License for the specific language governing permissions and
+@rem limitations under the License.
+@rem
+
+@if "%DEBUG%" == "" @echo off
+@rem ##########################################################################
+@rem
+@rem Gradle startup script for Windows
+@rem
+@rem ##########################################################################
+
+@rem Set local scope for the variables with windows NT shell
+if "%OS%"=="Windows_NT" setlocal
+
+set DIRNAME=%~dp0
+if "%DIRNAME%" == "" set DIRNAME=.
+set APP_BASE_NAME=%~n0
+set APP_HOME=%DIRNAME%
+
+@rem Resolve any "." and ".." in APP_HOME to make it shorter.
+for %%i in ("%APP_HOME%") do set APP_HOME=%%~fi
+
+@rem Add default JVM options here. You can also use JAVA_OPTS and GRADLE_OPTS to pass JVM options to this script.
+set DEFAULT_JVM_OPTS="-Xmx64m" "-Xms64m"
+
+@rem Find java.exe
+if defined JAVA_HOME goto findJavaFromJavaHome
+
+set JAVA_EXE=java.exe
+%JAVA_EXE% -version >NUL 2>&1
+if "%ERRORLEVEL%" == "0" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is not set and no 'java' command could be found in your PATH.
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:findJavaFromJavaHome
+set JAVA_HOME=%JAVA_HOME:"=%
+set JAVA_EXE=%JAVA_HOME%/bin/java.exe
+
+if exist "%JAVA_EXE%" goto execute
+
+echo.
+echo ERROR: JAVA_HOME is set to an invalid directory: %JAVA_HOME%
+echo.
+echo Please set the JAVA_HOME variable in your environment to match the
+echo location of your Java installation.
+
+goto fail
+
+:execute
+@rem Setup the command line
+
+set CLASSPATH=%APP_HOME%\gradle\wrapper\gradle-wrapper.jar
+
+
+@rem Execute Gradle
+"%JAVA_EXE%" %DEFAULT_JVM_OPTS% %JAVA_OPTS% %GRADLE_OPTS% "-Dorg.gradle.appname=%APP_BASE_NAME%" -classpath "%CLASSPATH%" org.gradle.wrapper.GradleWrapperMain %*
+
+:end
+@rem End local scope for the variables with windows NT shell
+if "%ERRORLEVEL%"=="0" goto mainEnd
+
+:fail
+rem Set variable GRADLE_EXIT_CONSOLE if you need the _script_ return code instead of
+rem the _cmd.exe /c_ return code!
+if not "" == "%GRADLE_EXIT_CONSOLE%" exit 1
+exit /b 1
+
+:mainEnd
+if "%OS%"=="Windows_NT" endlocal
+
+:omega
diff --git a/TestComm/settings.gradle b/TestComm/settings.gradle
new file mode 100644
index 00000000..21db480c
--- /dev/null
+++ b/TestComm/settings.gradle
@@ -0,0 +1,22 @@
+pluginManagement {
+ repositories {
+ maven { url 'https://maven.aliyun.com/repository/gradle-plugin' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ gradlePluginPortal()
+ google()
+ mavenCentral()
+ }
+}
+dependencyResolutionManagement {
+ repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
+ repositories {
+ maven { url 'https://maven.aliyun.com/repository/public' }
+ maven { url 'https://maven.aliyun.com/repository/jcenter' }
+ maven { url 'https://maven.aliyun.com/repository/central' }
+ maven { url 'https://maven.aliyun.com/repository/google' }
+ google()
+ mavenCentral()
+ }
+}
+rootProject.name = "TestComm"
+include ':app'