SM2签名和验签还在测试。

main
陈曦 2 years ago
commit c99503af23

1
app/.gitignore vendored

@ -0,0 +1 @@
/build

@ -0,0 +1,58 @@
plugins {
id("com.android.application")
}
android {
namespace = "com.xinyingpower.testcomm"
compileSdk = 33
defaultConfig {
applicationId = "com.xinyingpower.testcomm"
minSdk = 28
targetSdk = 33
versionCode = 1
versionName = "1.1"
testInstrumentationRunner = "androidx.test.runner.AndroidJUnitRunner"
externalNativeBuild {
cmake {
cppFlags += "-std=c++17"
}
}
}
buildTypes {
release {
isMinifyEnabled = 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.22.1"
}
}
buildFeatures {
viewBinding = true
}
ndkVersion = "25.1.8937393"
buildToolsVersion = "33.0.1"
}
dependencies {
implementation("androidx.appcompat:appcompat:1.6.1")
implementation("com.google.android.material:material:1.8.0")
implementation("androidx.constraintlayout:constraintlayout:2.1.4")
testImplementation("junit:junit:4.13.2")
androidTestImplementation("androidx.test.ext:junit:1.1.5")
androidTestImplementation("androidx.test.espresso:espresso-core:3.5.1")
}

@ -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

@ -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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
@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());
}
}

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools">
<application
android:allowBackup="true"
android:dataExtractionRules="@xml/data_extraction_rules"
android:fullBackupContent="@xml/backup_rules"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/Theme.TestComm"
tools:targetApi="31">
<activity
android:name=".MainActivity"
android:exported="true">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
</manifest>

@ -0,0 +1,41 @@
# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html.
# For more examples on how to use CMake, see https://github.com/android/ndk-samples.
# Sets the minimum CMake version required for this project.
cmake_minimum_required(VERSION 3.22.1)
# Declares the project name. The project name can be accessed via ${ PROJECT_NAME},
# Since this is the top level CMakeLists.txt, the project name is also accessible
# with ${CMAKE_PROJECT_NAME} (both CMake variables are in-sync within the top level
# build script scope).
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.
#
# In this top level CMakeLists.txt, ${CMAKE_PROJECT_NAME} is used to define
# the target library name; in the sub-module's CMakeLists.txt, ${PROJECT_NAME}
# is preferred for the same purpose.
#
# In order to load a library into your app from Java/Kotlin, you must call
# System.loadLibrary() and pass the name of the library defined here;
# for GameActivity/NativeActivity derived applications, the same library name must be
# used in the AndroidManifest.xml file.
add_library(${CMAKE_PROJECT_NAME} SHARED
# List C/C++ source files with relative paths to this CMakeLists.txt.
SpiPort.cpp
#spi-test-random.cpp
# NRSEC3000ctl.cpp
SpiLib.cpp
native-lib.cpp)
# Specifies libraries CMake should link to your target library. You
# can link libraries from various origins, such as libraries defined in this
# build script, prebuilt third-party libraries, or Android system libraries.
target_link_libraries(${CMAKE_PROJECT_NAME}
# List libraries link to the target library
android
log)

@ -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 <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <jni.h>
#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);
}

@ -0,0 +1,18 @@
#ifndef __SERIALPORT_H__
#define __SERIALPORT_H__
#include <string>
class SerialPort
{
public:
bool Open(std::string path, int, int);
bool Close();
protected:
int m_fd;
};
#endif // __SERIALPORT_H__

@ -0,0 +1,993 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <string>
#include <thread>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <android/log.h>
#include "SpiLib.h"
using namespace std;
#define CMD_HEAD_SIZE 5
//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:
retval = spi_transfer(fd, txbuf, buf, 1);
__android_log_print(ANDROID_LOG_INFO, "SPiLEN", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf);
}
//Rcvdata
void SpiLIb::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 SpiLIb::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);
__android_log_print(ANDROID_LOG_INFO, "SPiSW", "txbuf=%x,buf=%x", *txbuf,*buf);
if(*buf != sw)
{
goto SW90;
}
break;
}
retval = spi_transfer(fd, txbuf, buf+1, 1);
}
void SpiLIb::SendEnd(int fd, u8 *txbuf, u8 *buf)
{
int retval;
txbuf[0] = 0xaa;
retval = spi_transfer(fd, txbuf, buf, 1);
__android_log_print(ANDROID_LOG_INFO, "SPi_SENDEND", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf);
}
void SpiLIb::SendId(int fd, u8 *txbuf, u8 *buf, u8 id)
{
int retval;
txbuf[0]=id;
retval = spi_transfer(fd, txbuf, buf, 1);
__android_log_print(ANDROID_LOG_INFO, "SPi_SENDID", "txbuf=%x,rxbuf=%hhu", *txbuf,*buf);
}
void SpiLIb::SendData(int fd,u8 *data, u8 *rxbuf,int data_size)
{
int i=0;
int retval;
unsigned char crc[1];
crc[0]= get_crc7(data,data_size);
for (i=0; i< data_size; i++)
{
retval = spi_transfer(fd, data+i, rxbuf+i, 1);
__android_log_print(ANDROID_LOG_INFO, "SPi_SENDDATA", "i=%d,txbuf=%x,rxbuf=%x", i,*(data+i),*(rxbuf+i));
delay(20);
}
retval = spi_transfer(fd, crc, rxbuf, 1);
}
int SpiLIb::Spirandom()
{
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:
memcpy(txbuf, (const void *) Random_CMD, sizeof(Random_CMD));
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 SpiLIb::Version()
{
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;
}
int SpiLIb::SM2keypair(int index)//产生密钥
{
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));
SM2Keypair_CMD[3]=index;
//printf("tx %1d bytes: ", msglen);
//__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
CMD_RESEND:
memcpy(txbuf, (const void *) SM2Keypair_CMD, sizeof(SM2Keypair_CMD));
SendCmdHeader(fd, txbuf, rxbuf);
RcvSW(fd, txbuf, rxbuf, 0x90);
close(fd);
return 0;
}
int SpiLIb::SM2OutPub(int index,unsigned char result[])//导出公钥
{
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));
SM2OutPub_CMD[3]=index;
CMD_RESEND:
memcpy(txbuf, (const void *) SM2OutPub_CMD, sizeof(SM2OutPub_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 = "SM2公钥: ";
//char output[16] = { 0 };
for (i = 2; i < rxbuf[1]+2; i++) {
//sprintf(output, " %02x ", rxbuf[i]);
result[i-2]= rxbuf[i];
}
close(fd);
return 0;
}
int SpiLIb::SM2OutPri(int index,unsigned char result[])//导出私钥
{
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));
SM2OutPri_CMD[3]=index;
//printf("tx %1d bytes: ", msglen);
//__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
CMD_RESEND:
memcpy(txbuf, (const void *) SM2OutPri_CMD, sizeof(SM2OutPri_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);
for (i = 2; i < rxbuf[1]+2; i++) {
//sprintf(output, " %02x ", rxbuf[i]);
result[i-2]= rxbuf[i];
}
// std::string result = "OutPri";
// 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;
}
int SpiLIb::SM2InPub(int index,const unsigned char new_key[])//外部公钥导入存放在01
{
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));
SM2InPub_CMD[3]=index;
//printf("tx %1d bytes: ", msglen);
//__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
CMD_RESEND:
memcpy(txbuf, (const void *) SM2InPub_CMD, sizeof(SM2InPub_CMD));
SendCmdHeader(fd, txbuf, rxbuf);
RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令
SendId(fd,txbuf,rxbuf, 0x55);
memcpy(txbuf, new_key, 64);
SendData(fd, txbuf, rxbuf,64);
SendEnd(fd,txbuf,rxbuf);
RcvSW(fd, txbuf, rxbuf+1, 0x90);
std::string result = "InPub: success";
__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;
}
int SpiLIb::SM2InPri(int index,const unsigned char new_key[])//导入私钥 没测试
{
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));
SM2InPri_CMD[3]=index;
//printf("tx %1d bytes: ", msglen);
//__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
CMD_RESEND:
memcpy(txbuf, (const void *) SM2InPri_CMD, sizeof(SM2InPri_CMD));
SendCmdHeader(fd, txbuf, rxbuf);
RcvINS(fd,txbuf,rxbuf,txbuf[1]); // 指令
SendId(fd,txbuf,rxbuf, 0x55);
memcpy(txbuf, new_key, 32);
SendData(fd, txbuf, rxbuf,32);
SendEnd(fd,txbuf,rxbuf);
RcvSW(fd, txbuf, rxbuf+1, 0x90);
std::string result = "InPri: success";
__android_log_print(ANDROID_LOG_INFO, "SPi", "%s", result.c_str());
close(fd);
return 0;
}
int SpiLIb::SM3Hash(const unsigned char *to_hash ,int len,unsigned char *out_hash)//原始哈希 跑通了,没有验证
{
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));
int re[4]={0}; // 余数数组
int x = 0; // 余数数组下标
int a=len;
while (a != 0) {
re[x] = a % 16;
a /= 16;
x++;
}
SM3Hash_CMD[3]=re[2]+re[3]*16;
SM3Hash_CMD[4]=re[0]+re[1]*16;
__android_log_print(ANDROID_LOG_INFO, "len", "len=%x", len);
//printf("tx %1d bytes: ", msglen);
//__android_log_print(ANDROID_LOG_INFO, "SPi", "tx %1d bytes", msglen);
CMD_RESEND:
memcpy(txbuf, (const void *) SM3Hash_CMD, sizeof(SM3Hash_CMD));
SendCmdHeader(fd, txbuf, rxbuf);
RcvINS(fd,txbuf,rxbuf,txbuf[1]);
SendId(fd,txbuf,rxbuf, 0x55);
memcpy(txbuf, to_hash, len);
SendData(fd, txbuf, rxbuf,len);
SendEnd(fd,txbuf,rxbuf);
memcpy(txbuf, (const void *) SM3Hash_CMD, sizeof(SM3Hash_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_hash[i-2]= rxbuf[i];
}
close(fd);
return 0;
}
int SpiLIb::sm3hash_tosm2(unsigned char *in,int inl,unsigned char *out, unsigned char *pubkey, unsigned char
*pucID, int idl)
{
int nRet,l;
unsigned char *Z = NULL;
int entl = 0;
unsigned char tmpm[32];
unsigned char abxy[32 * 4] = {
0xFF,0xFF,0xFF,0xFE,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF, /* a */
0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0x00,0x00,0x00,0x00,0xFF,0xFF,0xFF,0xFF,0xFF,0xFF,
0xFF,0xFC,
0x28,0xE9,0xFA,0x9E,0x9D,0x9F,0x5E,0x34,0x4D,0x5A,/* b */
0x9E,0x4B,0xCF,0x65,0x09,0xA7,0xF3,0x97,0x89,0xF5,
0x15,0xAB,0x8F,0x92,0xDD,0xBC,0xBD,0x41,0x4D,0x94,
0x0E,0x93,
0x32,0xC4,0xAE,0x2C,0x1F,0x19,0x81,0x19,0x5F,0x99,/* x */
0x04,0x46,0x6A,0x39,0xC9,0x94,0x8F,0xE3,0x0B,0xBF,
0xF2,0x66,0x0B,0xE1,0x71,0x5A,0x45,0x89,0x33,0x4C,
0x74,0xC7,
0xBC,0x37,0x36,0xA2,0xF4,0xF6,0x77,0x9C,0x59,0xBD,/* y */
0xCE,0xE3,0x6B,0x69,0x21,0x53,0xD0,0xA9,0x87,0x7C,
0xC6,0x2A,0x47,0x40,0x02,0xDF,0x32,0xE5,0x21,0x39,
0xF0,0xA0
};
l = 2 + idl + 32 * 6;
Z = (unsigned char *)malloc(l);
if (!Z)
return -1;
entl = idl * 8;
memset(Z + 1, entl & 0xFF, 1);
entl >>= 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);
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);
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;
}

@ -0,0 +1,100 @@
#ifndef TESTCOMM_SPILIB_H
#define TESTCOMM_SPILIB_H
using namespace std;
typedef unsigned char u8;
class SpiLIb{
public:
int Spirandom();
int Version();
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(const 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)
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 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

@ -0,0 +1,61 @@
#include <termios.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <string.h>
#include <android/log.h>
#include <string>
#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;
}

@ -0,0 +1,30 @@
#ifndef _SPIPORT_H_
#define _SPIPORT_H_
#include <string>
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

@ -0,0 +1,135 @@
#include <jni.h>
#include <string>
#include "SpiPort.h"
#include "SpiLib.h"
#include <fcntl.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <linux/spi/spidev.h>
#include <android/log.h>
int testSpi();
int testVersion();
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;
}
};
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;
const unsigned char newkey[64]={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];
//a.SM2keypair(0x00);
a.SM3Hash(newkey,16, outpub);
for (int i = 0; i < 32; 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());
}

@ -0,0 +1,426 @@
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <fcntl.h>
#include <string.h>
#include <string>
#include <thread>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <linux/types.h>
#include <linux/spi/spidev.h>
#include <android/log.h>
#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;
}

@ -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);
}

@ -0,0 +1,170 @@
<?xml version="1.0" encoding="utf-8"?>
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path
android:fillColor="#3DDC84"
android:pathData="M0,0h108v108h-108z" />
<path
android:fillColor="#00000000"
android:pathData="M9,0L9,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,0L19,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,0L29,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,0L39,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,0L49,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,0L59,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,0L69,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,0L79,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M89,0L89,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M99,0L99,108"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,9L108,9"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,19L108,19"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,29L108,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,39L108,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,49L108,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,59L108,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,69L108,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,79L108,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,89L108,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M0,99L108,99"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,29L89,29"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,39L89,39"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,49L89,49"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,59L89,59"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,69L89,69"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M19,79L89,79"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M29,19L29,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M39,19L39,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M49,19L49,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M59,19L59,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M69,19L69,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
<path
android:fillColor="#00000000"
android:pathData="M79,19L79,89"
android:strokeWidth="0.8"
android:strokeColor="#33FFFFFF" />
</vector>

@ -0,0 +1,30 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:aapt="http://schemas.android.com/aapt"
android:width="108dp"
android:height="108dp"
android:viewportWidth="108"
android:viewportHeight="108">
<path android:pathData="M31,63.928c0,0 6.4,-11 12.1,-13.1c7.2,-2.6 26,-1.4 26,-1.4l38.1,38.1L107,108.928l-32,-1L31,63.928z">
<aapt:attr name="android:fillColor">
<gradient
android:endX="85.84757"
android:endY="92.4963"
android:startX="42.9492"
android:startY="49.59793"
android:type="linear">
<item
android:color="#44000000"
android:offset="0.0" />
<item
android:color="#00000000"
android:offset="1.0" />
</gradient>
</aapt:attr>
</path>
<path
android:fillColor="#FFFFFF"
android:fillType="nonZero"
android:pathData="M65.3,45.828l3.8,-6.6c0.2,-0.4 0.1,-0.9 -0.3,-1.1c-0.4,-0.2 -0.9,-0.1 -1.1,0.3l-3.9,6.7c-6.3,-2.8 -13.4,-2.8 -19.7,0l-3.9,-6.7c-0.2,-0.4 -0.7,-0.5 -1.1,-0.3C38.8,38.328 38.7,38.828 38.9,39.228l3.8,6.6C36.2,49.428 31.7,56.028 31,63.928h46C76.3,56.028 71.8,49.428 65.3,45.828zM43.4,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2c-0.3,-0.7 -0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C45.3,56.528 44.5,57.328 43.4,57.328L43.4,57.328zM64.6,57.328c-0.8,0 -1.5,-0.5 -1.8,-1.2s-0.1,-1.5 0.4,-2.1c0.5,-0.5 1.4,-0.7 2.1,-0.4c0.7,0.3 1.2,1 1.2,1.8C66.5,56.528 65.6,57.328 64.6,57.328L64.6,57.328z"
android:strokeWidth="1"
android:strokeColor="#00000000" />
</vector>

@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8"?>
<androidx.constraintlayout.widget.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MainActivity">
<TextView
android:id="@+id/sample_text"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Hello World!"
app:layout_constraintBottom_toBottomOf="parent"
app:layout_constraintEnd_toEndOf="parent"
app:layout_constraintStart_toStartOf="parent"
app:layout_constraintTop_toTopOf="parent" />
<Button
android:id="@+id/btnSpi"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="SPI"
app:layout_constraintLeft_toLeftOf="parent"
app:layout_constraintTop_toTopOf="parent"
/>
</androidx.constraintlayout.widget.ConstraintLayout>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

@ -0,0 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<adaptive-icon xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background" />
<foreground android:drawable="@drawable/ic_launcher_foreground" />
<monochrome android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.4 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 982 B

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.7 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 5.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.8 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 7.6 KiB

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.TestComm" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_200</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/black</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_200</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

@ -0,0 +1,10 @@
<?xml version="1.0" encoding="utf-8"?>
<resources>
<color name="purple_200">#FFBB86FC</color>
<color name="purple_500">#FF6200EE</color>
<color name="purple_700">#FF3700B3</color>
<color name="teal_200">#FF03DAC5</color>
<color name="teal_700">#FF018786</color>
<color name="black">#FF000000</color>
<color name="white">#FFFFFFFF</color>
</resources>

@ -0,0 +1,3 @@
<resources>
<string name="app_name">TestComm</string>
</resources>

@ -0,0 +1,16 @@
<resources xmlns:tools="http://schemas.android.com/tools">
<!-- Base application theme. -->
<style name="Theme.TestComm" parent="Theme.MaterialComponents.DayNight.DarkActionBar">
<!-- Primary brand color. -->
<item name="colorPrimary">@color/purple_500</item>
<item name="colorPrimaryVariant">@color/purple_700</item>
<item name="colorOnPrimary">@color/white</item>
<!-- Secondary brand color. -->
<item name="colorSecondary">@color/teal_200</item>
<item name="colorSecondaryVariant">@color/teal_700</item>
<item name="colorOnSecondary">@color/black</item>
<!-- Status bar color. -->
<item name="android:statusBarColor">?attr/colorPrimaryVariant</item>
<!-- Customize your theme here. -->
</style>
</resources>

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample backup rules file; uncomment and customize as necessary.
See https://developer.android.com/guide/topics/data/autobackup
for details.
Note: This file is ignored for devices older that API 31
See https://developer.android.com/about/versions/12/backup-restore
-->
<full-backup-content>
<!--
<include domain="sharedpref" path="."/>
<exclude domain="sharedpref" path="device.xml"/>
-->
</full-backup-content>

@ -0,0 +1,19 @@
<?xml version="1.0" encoding="utf-8"?><!--
Sample data extraction rules file; uncomment and customize as necessary.
See https://developer.android.com/about/versions/12/backup-restore#xml-changes
for details.
-->
<data-extraction-rules>
<cloud-backup>
<!-- TODO: Use <include> and <exclude> to control what is backed up.
<include .../>
<exclude .../>
-->
</cloud-backup>
<!--
<device-transfer>
<include .../>
<exclude .../>
</device-transfer>
-->
</data-extraction-rules>

@ -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 <a href="http://d.android.com/tools/testing">Testing documentation</a>
*/
public class ExampleUnitTest {
@Test
public void addition_isCorrect() {
assertEquals(4, 2 + 2);
}
}

@ -0,0 +1,4 @@
// Top-level build file where you can add configuration options common to all sub-projects/modules.
plugins {
id("com.android.application") version "8.1.2" apply false
}

@ -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

Binary file not shown.

@ -0,0 +1,6 @@
#Fri Oct 20 10:30:23 CST 2023
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-8.0-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

185
gradlew vendored

@ -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" "$@"

89
gradlew.bat vendored

@ -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

@ -0,0 +1,18 @@
pluginManagement {
repositories {
google()
mavenCentral()
gradlePluginPortal()
}
}
dependencyResolutionManagement {
repositoriesMode.set(RepositoriesMode.FAIL_ON_PROJECT_REPOS)
repositories {
google()
mavenCentral()
}
}
rootProject.name = "TestComm"
include(":app")
Loading…
Cancel
Save