zoukankan      html  css  js  c++  java
  • [Andorid] 通过JNI实现kernel与app进行spi通讯

    CPU:RK3399

    系统:Android 7.1

    人脸识别的要求越来越高,因此主板增加了 SE 加密芯片,加密芯片通过 spi 接口与 CPU 通讯。

    对于 kernel 层的代码,Linux 原始代码中有很经典的参考驱动,可以仿照写 spi 驱动。

    如果没有过多要求,只需要修改设备号和节点名称,然后能和 dts 匹配成功就行,最后记得修改生成的节点权限

    path:kernel/drivers/spi/spidev.c

    diff --git a/device/rockchip/common/ueventd.rockchip.rc b/device/rockchip/common/ueventd.rockchip.rc
    index 8d5d28d..4b6ac2a 100644
    --- a/device/rockchip/common/ueventd.rockchip.rc
    +++ b/device/rockchip/common/ueventd.rockchip.rc
    @@ -65,6 +65,8 @@
     /dev/ttyS2                     0666   system     system
     /dev/ttyS3                     0666   system     system
     
    +/dev/thm36                     0666   system     system
    +
     # for radio
     /dev/ttyUSB0                   0660   radio      radio
     /dev/ttyUSB1                   0660   radio      radio

    JNI 的代码就需要自己完成(不需要 HAL 层),然后将 JNI 添加到 App 中编译。

    下面代码只是实现简单的读写功能,完成 app 和 kernel 之间的通讯,复杂的地方就是数组之间的转化。

    JNI 文件名:thm36_jni.c

    #include <jni.h>
    #include <stdio.h>
    #include <fcntl.h>
    #include <stdlib.h>
    #include <assert.h>
    #include <termios.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <sys/stat.h>
    #include <fcntl.h>
    #include <string.h>
    
    #include "android/log.h"
    
    static const char *TAG = "thm36_jni";
    
    #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)
    
    #define DEV_NAME    "/dev/thm36"
    
    static jint fd;
    
    JNIEXPORT jint JNICALL Java_com_example_aaron_se_Thm36Native_thm36Open(JNIEnv *env, jclass clazz)
    {
        LOGD("JNI spi open ... ...");
        
        fd = open(DEV_NAME, O_RDWR);
        if (fd < 0)
        {
            LOGD("open device fail!");
            return -1;
        }
        
        return 0;
    }
    
    JNIEXPORT void JNICALL Java_com_example_aaron_se_Thm36Native_thm36Close(JNIEnv *env, jclass clazz)
    {
        LOGD("JNI spi close ... ...");
        
        close(fd);
    }
    
    JNIEXPORT jint JNICALL Java_com_example_aaron_se_Thm36Native_thm36Read(JNIEnv *env, jclass clazz, jbyteArray jread_arr, jint len)
    {
        jbyte *array = NULL;
        jboolean *buf;
        int  i = 0;
        
        LOGD("JNI spi read ... ...");
        
        array = (*env)->GetByteArrayElements(env, jread_arr, NULL);
        if (array == NULL)
        {
            LOGD("JNI spi read: GetByteArrayElements faid!");
            return -1;
        }
        
        buf = (jboolean *)calloc(sizeof(*array), sizeof(jboolean));
        if (buf == NULL)
        {
            LOGD("JNI spi read: calloc fail!");
            return -1;
        }
        
        read(fd, buf, len);
        for (i=0; i<len; i++)
        {
            LOGD("JNI spi read: buf: %#x", *(buf + i));
            *(array + i) = (jchar)(*(buf + i));
        }
        
        (*env)->ReleaseByteArrayElements(env, jread_arr, array, 0);
        
        free(buf);
        
        return 0;
    }
    
    JNIEXPORT jint JNICALL Java_com_example_aaron_se_Thm36Native_thm36Write(JNIEnv *env, jclass clazz, jbyteArray jwrite_arr, jint len)
    {
        jbyte *array = NULL;
        jboolean *buf;
        int i = 0;
        
        LOGD("JNI spi write ... ...");
        
        array = (*env)->GetByteArrayElements(env, jwrite_arr, NULL);
        if (array == NULL)
        {
            LOGD("JNI spi write: GetByteArrayElements fail!");
            return -1;
        }
        
        buf = (jboolean *)calloc(sizeof(*array), sizeof(jboolean));
        if(buf == NULL)
        {
            LOGD("JNI spi write: calloc fail!");
            return -1;
        }
        
        for(i = 0; i < len; i++)
        {
            *(buf + i) = (jboolean)(*(array + i));
            LOGD("JNI spi write: data : %#x
    ",*(buf + i));
        }
        
        (*env)->ReleaseByteArrayElements(env, jwrite_arr, array, 0);
        
        write(fd, buf, len);
        
        free(buf);
        
        return 0;
    }

    编译文件:Android.mk

    LOCAL_PATH := $(call my-dir)
    
    include $(CLEAR_VARS)
    
    TARGET_PLATFORM := android-3
    LOCAL_MODULE    := thm36_jni
    LOCAL_SRC_FILES := thm36_jni.c
    LOCAL_LDLIBS    := -llog
    
    include $(BUILD_SHARED_LIBRARY)

    App 的测试代码也很简单,一个是主活动,一个是与 JNI 链接

    MainActivity.java

    // JNI中的函数名前面部分要与此相同
    package com.example.aaron.se;
    
    import android.support.v7.app.AppCompatActivity;
    import android.os.Bundle;
    import android.util.Log;
    import android.view.View;
    import android.widget.Button;
    
    public class MainActivity extends AppCompatActivity implements View.OnClickListener{
    
        Thm36Native thm36 = new Thm36Native();
        byte[] tx = {(byte)0xAA, 0x00, 0x06, 0x00, (byte)0xCA, 0x00, 0x00, 0x00, 0x00, (byte)0xCA};
        byte[] rx = new byte[22];
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            Button btn = (Button) findViewById(R.id.btn);
    
            btn.setOnClickListener(MainActivity.this);
        }
    
        @Override
        public void onClick(View view) {
            switch (view.getId()) {
                case R.id.btn:
                    thm36.thm36Open();
                    thm36.thm36Write(tx, tx.length);
                    thm36.thm36Read(rx, rx.length);
                    thm36.thm36Close();
                    break;
    
                default:
                    break;
            }
        }
    }

    Thm36Native.java

    package com.example.aaron.se;
    
    import android.util.Log;
    
    public class Thm36Native {
    
        private final String TAG = "Thm36Native";
    
        public native int thm36Open();
        public native void thm36Close();
        public native int thm36Read(byte[] buf, int len);
        public native int thm36Write(byte[] buf, int len);
    
        static {
            System.loadLibrary("thm36");
        }
    }

    参考:

    https://blog.csdn.net/hanbo622/article/details/38944895

  • 相关阅读:
    SpringBoot整合JavaMail发送邮件
    SpringBoot使用SpringDataJPA完成CRUD
    开源「高逼格」简历例句
    Spring Boot 两种多数据源配置:JdbcTemplate、Spring-data-jpa
    Spring Boot
    Socket网络编程
    项目action:前台传多个dataWrap给后台
    Java——定时任务调度工具
    Spring5源码,@ModelAttribute
    windows下MongoDB的安装及配置
  • 原文地址:https://www.cnblogs.com/lialong1st/p/11608989.html
Copyright © 2011-2022 走看看