1、在frameworks/base/services/jni下创建spijni文件夹。
2、在spijni目录下创建com_android_server_SpiService.cpp和Android.mk。
com_android_server_SpiService.cpp
#define LOG_TAG "SpiService"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/hardware.h>
#include <hardware/spihal.h>
#include <stdio.h>
#include <fcntl.h>
namespace android
{
/* 定义访问HAL层函数结构体 */
struct spi_device_t *spi_device = NULL;
/* 定义spi读函数 */
static jint spi_jni_read(JNIEnv *env, jobject clazz, jbyteArray jread_arr, jint len)
{
jbyte *array = NULL;
jboolean *buf;
int i = 0;
ALOGE("Jni Spi Read ...\n");
array = env->GetByteArrayElements(jread_arr, NULL);
if(array == NULL)
{
ALOGE("JniSpiRead: getByteArrayElements error!\n");
return -1;
}
buf = (jboolean *)calloc(sizeof(*array), sizeof(jboolean));
if(buf == NULL)
{
ALOGE("JniSpiRead: calloc error!\n");
return -1;
}
spi_device->spi_read(spi_device, buf, len);
for(i = 0; i < len; i++)
{
ALOGE("Spi Jni Read: data : %#x\n",*(buf + i));
*(array + i) = (jchar)(*(buf + i));
}
env->ReleaseByteArrayElements(jread_arr, array, 0);
free(buf);
buf = NULL;
return 0;
}
/* 定义spi写函数 */
static jint spi_jni_write(JNIEnv *env, jobject clazz, jbyteArray jwrite_arr, jint len)
{
jbyte *array = NULL;
jboolean *buf;
int i = 0;
ALOGE("Jni Spi Write ...\n");
array = env->GetByteArrayElements(jwrite_arr, NULL);
if(array == NULL)
{
ALOGE("JniSpiWrite: getByteArrayElements error!\n");
return -1;
}
buf = (jboolean *)calloc(sizeof(*array), sizeof(jboolean));
if(buf == NULL)
{
ALOGE("JniSpiWrite: calloc error!\n");
return -1;
}
for(i = 0; i < len; i++)
{
*(buf + i) = (jboolean)(*(array + i));
ALOGE("Spi Jni Write: data : %#x\n",*(buf + i));
}
env->ReleaseByteArrayElements(jwrite_arr, array, 0);
spi_device->spi_write(spi_device, buf, len);
free(buf);
buf = NULL;
return 0;
}
/* 定义spi打开函数 */
static inline int spi_jni_open(const hw_module_t * module, struct spi_device_t **device)
{
return module->methods->open(module, SPI_HARDWARE_MODULE_ID, (struct hw_device_t **)device);
}
/* 定义spi初始化函数 */
static jboolean spi_jni_init(JNIEnv *env, jclass clazz)
{
spi_module_t *Jspi_module;
ALOGE("Spi JNI: spi initializing ...\n");
if(hw_get_module(SPI_HARDWARE_MODULE_ID, (const struct hw_module_t **)&Jspi_module) == 0)
{
ALOGE("Spi JNI: spi stub found.\n");
if(spi_jni_open(&(Jspi_module->common), &spi_device) == 0)
{
ALOGE("Spi JNI: spi device is open.\n");
if(spi_device)
{
spi_device->spi_init(spi_device);
ALOGE("Spi JNI: spi init successfuly!\n");
return true;
}
ALOGE("Spi JNI: spi init failed.\n");
return false;
}
ALOGE("Spi JNI: failed to open spi device.\n");
return false;
}
ALOGE("Spi JNI: failed to get spi stub module.\n");
return false;
}
/* JNI方法 */
static const JNINativeMethod method_table[] =
{
{"native_init", "()Z", (void *)spi_jni_init},
{"native_write", "([BI)I", (void *)spi_jni_write},
{"native_read", "([BI)I", (void *)spi_jni_read},
};
/* 注册JNI方法 */
static int registerMethods(JNIEnv *env)
{
static const char *const kClassName = "com/android/server/SpiService";
jclass clazz;
clazz = env->FindClass(kClassName);
if(clazz == NULL)
{
ALOGE("Can't find class %s\n",kClassName);
return -1;
}
if(env->RegisterNatives(clazz,method_table, sizeof(method_table)/sizeof(method_table[0])) != JNI_OK)
{
ALOGE("Failed registering methods for %s\n",kClassName);
return -1;
}
return 0;
}
extern "C"
jint JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env = NULL;
jint result = -1;
ALOGE("Jni OnLoad ...\n");
if(vm->GetEnv((void **)&env, JNI_VERSION_1_4) != JNI_OK)
{
ALOGE("ERROR: GetEnv failed .\n");
goto fail;
}
assert(env != NULL);
if(registerMethods(env) != 0)
{
ALOGE("ERROR: PlatformLibrary native registeration failed .\n");
goto fail;
}
result = JNI_VERSION_1_4;
fail:
return result;
}
};
Android.mk
LOCAL_PATH:= $(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
com_android_server_SpiService.cpp \
LOCAL_C_INCLUDES += \
$(JNI_H_INCLUDE) \
frameworks/base/services \
frameworks/base/core/jni \
external/skia/include/core \
libcore/include \
libcore/include/libsuspend \
$(call include-path-for, libhardware)/hardware \
$(call include-path-for, libhardware_legacy)/hardware_legacy \
LOCAL_SHARED_LIBRARIES := \
libandroid_runtime \
libandroidfw \
libcutils \
liblog \
libhardware \
libhardware_legacy \
libnativehelper \
libsystem_server \
libutils \
libui \
libinput \
libskia \
libgui \
libusbhost \
libsuspend
ifeq ($(WITH_MALLOC_LEAK_CHECK),true)
LOCAL_CFLAGS += -DMALLOC_LEAK_CHECK
endif
LOCAL_MODULE:= libspi_servers
include $(BUILD_SHARED_LIBRARY)
3、在源码主目录下编译执行命令:mmm frameworks/base/services/jni。
4、生成库的路径out/target/product/sabresd_6dq/symbols/system/lib/libspi_servers.so。
5、把生成的该库放到开发板的/system/lib目录下
加执行权限 chown root libspi_servers.so
chmod 777 libspi_servers.so
注意:如果无法打开设备节点/dev/spi1.0则
加执行权限 chown root spi1.0
chmod 777 spi1.0
无法加执行权限时执行:mount -o rw,remount -t ext4 /dev/block/mmcblk0p5 /system
chmod 777 /system

本文详细介绍了在Android框架中实现SPI服务的JNI代码,包括文件结构搭建、方法实现及库编译流程,并指导如何将生成的库文件部署到开发板上。


被折叠的 条评论
为什么被折叠?



