操作
struct hw_device_t common;
/* attributes */
/* supporting control APIs go here */
int (*uart_read_hal)(struct uart_control_device_t *dev, char *buf, int count);
int (*uart_write_hal)(struct uart_control_device_t *dev, const char *cmd);
};
#define UART_HARDWARE_MODULE_ID "uart" //定义一个MODULE_ID,HAL层可以根据这个ID找到我们这个HAL stub
4.cn_com_smarthome_uart_MyUartService.cpp
#define LOG_TAG "MyUartService" #include "utils/Log.h" #include
#include #include #include #include #include "../../uart_stub/include/uart.h"
static uart_control_device_t *sUartDevice = 0;
static uart_module_t* sUartModule=0; JNINativeMethod是 jni层注册的方法,Framework层可以使用这些方法 *_init 、uart_read、uart_write 是在Framework中调用的方法名称,函数的类型及返回值如下:
*()Z无参数 返回值为bool型 * ()Ljava/lang/String; 无参数 返回值为String型
* (II)I 参数为2个int型 返回值为int型
static const JNINativeMethod gMethods[] = {
{"_init", "()Z", (void*)uart_init}, { "_uart_data_update", "()Ljava/lang/String;", (void*)uart_read },
{ "_uart_send_cmd", "(II)I", (void*)uart_write },
};
static int registerMethods(JNIEnv* env) {
static const char* const kClassName =
"cn/com/smarthome/uart/MyUartService"; //注意:必须和Framework层的service类名相
jclass clazz;
/* look up the class */
clazz = env->FindClass(kClassName); //查找被注册的类
if (clazz == NULL) {
LOGE("Can't find class %s\n", kClassName);
return -1;
}
/* register all the methods */
if (env->RegisterNatives(clazz, gMethods,
sizeof(gMethods) / sizeof(gMethods[0])) != JNI_OK)
{
LOGE("Failed registering methods for %s\n", kClassName);
return -1;
} //向类中注册本SO中Native的接口,接口定义在gMethods数组中
/* fill out the rest of the ID cache */
return 0;
}
/*
*
* * This is called by the VM when the shared library is first loaded.
* 在Android系统初始化时,就会自动加载该JNI方法调用表。
* 当第一次加载此库时,调用此函数注册本地方法 */
jint JNI_OnLoad(JavaVM* vm, void* reserved) {
JNIEnv* env = NULL;
jint result = -1;
LOGI("zzs_JNI_OnLoad");
if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
LOGE("ERROR: GetEnv failed\n");
goto fail;
} //获取当前的VM的环境,保存在env变量中
assert(env != NULL);
if (registerMethods(env) != 0) {
LOGE("ERROR: PlatformLibrary native registration failed\n");
goto fail;
} //自己写的函数,向当前JAVA环境中注册接口
/* success -- return valid version number */
result = JNI_VERSION_1_4;
fail:
return result;
} /* JNI_OnLoad()函数完成:
(1) 把虚拟机环境信息保存到本地库的一个结构体“JNIEnv”的实例中;
(2) 建立一个应用层中的UART控制服务与本地库的JNI函数表;
(3) 返回虚拟机本地库使用的JNI版本。
*/
5. uart_stub\module\uart.c
#define LOG_TAG "UartStub"
#include
#include
#include
#include
#include
#include
#include
#include "../include/uart.h"
#include "crc16.h"
#define N 6
#define START 0xAA //用于传输协议的宏
#define NEW 0x01
#define INFO 0x02
#define RFID 0x04
int fd;
typedef struct {
char head;
char dev_no;
char type_data;
char length;
char temp[2];
char hum[2];
char bright[2];
char adc[2];
char acc[3];
char rfid[N];
short crc16;
}dev_data; //传输协议的格式
//CRC16的校验函数,查表法,表在crc16.h内
static unsigned short get_crc16(const char * crc_head, int crc_lenth )
{
unsigned char ucCRCHi = 0x0;
unsigned char ucCRCLo = 0x0;
int iIndex;
while ( crc_lenth-- ) {
iIndex = ucCRCLo ^ *( crc_head++ );
ucCRCLo = ( unsigned char )( ucCRCHi ^ aucCRCHi[iIndex] );
ucCRCHi = aucCRCLo[iIndex];
}
return ( unsigned short )( ucCRCHi << 8 | ucCRCLo );
}
static int uart_device_close(struct hw_device_t* device)
{
struct uart_control_device_t* ctx = (struct uart_control_device_t*)device;
if (ctx) {
free(ctx);
}
close(fd);
return 0;
}
static int uart_read_drv(struct uart_control_device_t *dev, char *buf, int count)
{
dev_data info_buf;
char rev_buf[40] = {0}; //用于存放整个消息包
char data_buf[40] = {0}; //用于存放消息包内的数据段
char ch;
ssize_t cur_size = 0;
ssize_t r_size = 0;
char data_lenth = 0; //数据段的长度
char data_type; //数据类型
char *data_head; //数据段头
int dev_no; //设备号
char *crc_head; //用于CRC校验的头
int crc_lenth; //用于crc校验的长度,从消息包头到数据段尾
unsigned short crc16; //校验值
int timeout = 10; //超时处理,长时间读不到消息,当timeout减到0时,返回到上层
while (1)
{
timeout--; //由于采用轮询读的方法,如果没消息则会一直循环,设置一个超时值,当超出后还没数据的话,就退出此次读消息
if (!timeout) {
LOGI("No start info_buf");
return -1;
}
if (read (fd, &info_buf.head, 1) < 0) {
LOGE("read START err");
continue;
} //判断是否为帧头,不是就继续循环判断
if (info_buf.head != START) {
LOGI("head is %x", info_buf.head);
continue;
} else { //判断是否为帧头,不是就继续循环判断
timeout = 40;
if (read (fd, &info_buf.dev_no, 1) < 0) {
LOGE("read dev_no err");
return -1;
} //读出设备号
if (read (fd, &info_buf.type_data, 1) < 0) {
LOGE("read type_data err");
return -1;
} //读出数据类型
if (read (fd, &info_buf.length, 1) < 0) {
LOGE("read length err");
return -1;
} //读出数据长度
while (cur_size < (info_buf.length+2)) {
if ((r_size = read (fd, (rev_buf + 4) + cur_size, (info_buf.length + 2) - cur_size)) < 0) {
LOGI("read data err");
continue;
}
cur_size += r_size; //累加到总共已读数据,用以与应对数据长度比较
} //读出数据
break;
}
} <
上一篇:基于Android平台的校园通软件
下一篇:试论APP广告在手机中的应用