读书的时候有写博客的习惯,后面就再也没写过了,发现很多知识点整理在电脑上容易丢失,也不能共享,所以今天又拿起笔开始写博客了,这篇文章的内容是基于兆芯平台的Android架构,实现了一个APP调用hal层来控制导光板的灯光效果。
Android上层平台和底层通信有两种模型: 1.NDK模型(不常用); 2.框架模型
Android系统使用JNI的原因有:
1、代码保护,Java程序很容易被反编译,C/C++反汇编难度大
2、可以很方便的使用开源库,大部分开源库都是C/C++编写的
3、执行效率的问题,将高执行效率的代码段用C/C++编写
4、Java在文件操作方面,找不到相应的API
1、NDK模型
由内核级别的驱动程序和APP组成,内核级别的驱动程序对外的接口是ioctl,而APP是由JAVA语言写的,JAVA语言并没有(或者并不支持)ioctl接口,所以内核级别的驱动程序和APP是不能直接连接(数据交换),那么就在中间增加了一层C/C++,这层C/C++支持ioctl接口,可以和内核级别的驱动程序连接,而APP的JAVA程序又可以调用C/C++,这样就连接起来了,JAVA通过JNI调用C/C++(JNI:java native interface是专门给java程序调用c/c++提供一种程序调用方法)。通过NDK这个工具将APP和第三方的一些库(C/C++)打包成apk安装包。存在问题:内核级别的驱动程序需要遵循GPL协议,而GPL协议需要开源,但是有些厂家的内核由于包含商业信息,故不完全开源,即一部分开源,一部分不开源,这样就有了框架模型。
2、框架模型
开源的一部分是需要遵循GPL协议的,放在内核里面,不开源的一部分就不能放在内核里面,故放在Android系统里面,即HAL,硬件抽象层,与硬件相关的代码,是不想开源的。 在硬件抽象层上面又加了一层硬件服务层,把封装好的硬件服务注册到Android系统中,那么APP通过service manager找到硬件服务层,硬件服务层找到硬件抽象层,硬件抽象层找到驱动程序。
框架设计模型设计总共分为4步:
- 第一步:是内核级的驱动开发,就是封装Linux驱动方法供hal层调用。
- 第二步:设计硬件抽象层HAL程序,下图是设计步骤
下面是具体的实现代码:
- sn3199_hal.c (相对android源码路径:hardware/libhardware/modules/sn3199/)
#include <cutils/log.h>
#include <stdint.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sys/types.h>
#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <linux/i2c.h>
#include <linux/i2c-dev.h>
#include <hardware/sn3199_hal.h>
#define LOG_TAG "sn3199_hal_default"
//全局变量
uchar s,t1,t2,flag,N;
uchar mode=2;
int i2c_fd = -1;
const unsigned char PWM64[64]=
{
0x00,0x01,0x02,0x03,0x04,0x05,0x06,0x07,
0x08,0x09,0x0b,0x0d,0x0f,0x11,0x13,0x16,
0x1a,0x1c,0x1d,0x1f,0x22,0x25,0x28,0x2e,
0x34,0x38,0x3c,0x40,0x44,0x48,0x4b,0x4f,
0x55,0x5a,0x5f,0x64,0x69,0x6d,0x72,0x77,
0x7d,0x80,0x88,0x8d,0x94,0x9a,0xa0,0xa7,
0xac,0xb0,0xb9,0xbf,0xc6,0xcb,0xcf,0xd6,
0xe1,0xe9,0xed,0xf1,0xf6,0xfa,0xfe,0xff
};
//adau1761单字节写入函数
void single_world_write(unsigned char chip_addr, int i2c_fd, unsigned short reg, unsigned char val)
{
struct i2c_rdwr_ioctl_data light_guide_plate_data;
light_guide_plate_data.msgs = (struct i2c_msg *)calloc(1, sizeof(struct i2c_msg));
if(!light_guide_plate_data.msgs)
{
perror("light_guide_plate_data.msgs calloc error:\n");
return;
}
//构造写入到adau1761单个寄存器中的消息
light_guide_plate_data.nmsgs = 1;
(light_guide_plate_data.msgs[0]).len = 2; //写入数据的长度为3
(light_guide_plate_data.msgs[0]).addr = chip_addr;
(light_guide_plate_data.msgs[0]).flags = 0;
(light_guide_plate_data.msgs[0]).buf = (unsigned char *)calloc(1,2);
(light_guide_plate_data.msgs[0]).buf[0] = reg;
(light_guide_plate_data.msgs[0]).buf[1] = val;
//使用ioctl写入数据
ioctl(i2c_fd, I2C_RDWR, (unsigned long)&light_guide_plate_data);
return;
}
//adau1761多字节写入函数
void burst_model_write(unsigned char chip_addr, int i2c_fd, unsigned short reg, unsigned char *data, unsigned int data_len)
{
int i;
struct i2c_rdwr_ioctl_data light_guide_plate_data;
light_guide_plate_data.msgs = (struct i2c_msg *)calloc(1, sizeof(struct i2c_msg));
if(!light_guide_plate_data.msgs)
{
perror("light_guide_plate_data.msgs calloc error:\n");
exit(-1);
}
light_guide_plate_data.nmsgs = 1;
(light_guide_plate_data.msgs[0]).len = data_len + 2; //写入数据的长度为3
(light_guide_plate_data.msgs[0]).addr = chip_addr;
(light_guide_plate_data.msgs[0]).flags = 0;
(light_guide_plate_data.msgs[0]).buf = (unsigned char *)calloc(1,data_len + 1);
(light_guide_plate_data.msgs[0]).buf[0] = reg;
for(i = 0; i < data_len; i++)
{
(light_guide_plate_data.msgs[0]).buf[i + 1] = data[i];
}
//使用ioctl写入数据
ioctl(i2c_fd, I2C_RDWR, (unsigned long)&light_guide_plate_data);
return;
}
//adau1761单字节读出函数
unsigned char single_world_read(unsigned char chip_addr, int i2c_fd, unsigned short reg)
{
struct i2c_rdwr_ioctl_data light_guide_plate_data;
light_guide_plate_data.msgs = (struct i2c_msg *)calloc(2, sizeof(struct i2c_msg));
if(!light_guide_plate_data.msgs)
{
perror("light_guide_plate_data.msgs calloc error:\n");
exit(-1);
}
//构造从adau1761单个寄存器读数据的消息
//先写偏移地址
light_guide_plate_data.nmsgs = 2;
(light_guide_plate_data.msgs[0]).len = 1;
(light_guide_plate_data.msgs[0]).addr = chip_addr;
(light_guide_plate_data.msgs[0]).flags = 0x0;
(light_guide_plate_data.msgs[0]).buf = (unsigned char *)calloc(1,1);
(light_guide_plate_data.msgs[0]).buf[0] = reg;
(light_guide_plate_data.msgs[1]).len = 1;
(light_guide_plate_data.msgs[1]).addr = chip_addr;
(light_guide_plate_data.msgs[1]).flags = I2C_M_RD;
(light_guide_plate_data.msgs[1]).buf = (unsigned char *)calloc(1,2);
//使用ioctl读取数据
ioctl(i2c_fd, I2C_RDWR, (unsigned long)&light_guide_plate_data);
printf("buf[0] = 0x%x\n",(light_guide_plate_data.msgs[1]).buf[0]);
return (light_guide_plate_data.msgs[1]).buf[0];
}
//adau1761多字节读出函数
unsigned char * burst_model_read(unsigned char chip_addr, int i2c_fd, unsigned short reg, unsigned int data_len)
{
struct i2c_rdwr_ioctl_data light_guide_plate_data;
light_guide_plate_data.msgs = (struct i2c_msg *)calloc(2, sizeof(struct i2c_msg));
if(!light_guide_plate_data.msgs)
{
perror("light_guide_plate_data.msgs calloc error:\n");
exit(-1);
}
//构造从adau1761单个寄存器读数据的消息
//先写偏移地址
light_guide_plate_data.nmsgs = 2;
(light_guide_plate_data.msgs[0]).len = 2;
(light_guide_plate_data.msgs[0]).addr = chip_addr;
(light_guide_plate_data.msgs[0]).flags = 0x0;
(light_guide_plate_data.msgs[0]).buf = (unsigned char *)calloc(1,1);
(light_guide_plate_data.msgs[0]).buf[0] = reg;
(light_guide_plate_data.msgs[1]).len = data_len;
(light_guide_plate_data.msgs[1]).addr = chip_addr;
(light_guide_plate_data.msgs[1]).flags = I2C_M_RD;
(light_guide_plate_data.msgs[1]).buf = (unsigned char *)calloc(1,data_len);
//使用ioctl读取数据
ioctl(i2c_fd, I2C_RDWR, (unsigned long)&light_guide_plate_data);
return (light_guide_plate_data.msgs[1]).buf;
}
int reset()
{
single_world_write(CHIP_ADDR1, i2c_fd, 0xff,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x00,0x01); //enable sd chip1
single_world_write(CHIP_ADDR1, i2c_fd, 0x01,0x77);
single_world_write(CHIP_ADDR1, i2c_fd, 0x02,0x07);
single_world_write(CHIP_ADDR1, i2c_fd, 0x04,0x00);
single_world_write(CHIP_ADDR2, i2c_fd, 0xff,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x00,0x01); //enable sd chip1
single_world_write(CHIP_ADDR2, i2c_fd, 0x01,0x77);
single_world_write(CHIP_ADDR2, i2c_fd, 0x02,0x07);
single_world_write(CHIP_ADDR2, i2c_fd, 0x04,0x00);
return 0;
}
/************************************************/
//设置LED 电流大小
//0= 20mA , 1 = 15mA, 2= 10mA, 3=5mA, 4= 40mA, 5= 35mA, 6=30mA,7=25mA
/*************************************************/
void Led_SetCurrent(unsigned char level)
{
if ( level > 7 ) return;
g_LedEffect |= level<<4;
single_world_write(CHIP_ADDR1, i2c_fd, SN3216_REG_LED_EFFECT, g_LedEffect);
single_world_write(CHIP_ADDR2, i2c_fd, SN3216_REG_LED_EFFECT, g_LedEffect);
}
/*****************正常工作(音箱本身喇叭不工作)-常亮白色********************
*i2c_fd:i2c文件操作描述符
*
***********************************************************************/
int normally_bright_white()
{
single_world_write(CHIP_ADDR1, i2c_fd, 0x03, 0x0); //pwm mode
single_world_write(CHIP_ADDR2, i2c_fd, 0x03, 0x0); //pwm mode
single_world_write(CHIP_ADDR1, i2c_fd, 0x07,0xff); //紫色
single_world_write(CHIP_ADDR1, i2c_fd, 0x08,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x09,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0a,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0b,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0c,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0d,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0e,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0f,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x07,0xff); //紫色
single_world_write(CHIP_ADDR2, i2c_fd, 0x08,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x09,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0a,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0b,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0c,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0d,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0e,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0f,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff);
ALOGD("normally_bright_white:i2c_cfd = %d\n", i2c_fd);
return 0;
}
/*****************待机-白色呼吸灯效果********************
*
******************************************************/
int standby_mode() //RGB单色呼吸
{
single_world_write(CHIP_ADDR1, i2c_fd, 0x03,0x70); //One shot mode
single_world_write(CHIP_ADDR1, i2c_fd, 0x06,0x10); //INTB OUT1
single_world_write(CHIP_ADDR1, i2c_fd, 0x04,0x80); //从模式
single_world_write(CHIP_ADDR1, i2c_fd, 0x1a,0x81); //T1~T3; T3=2T1=2*260*2ms,T2=260
single_world_write(CHIP_ADDR1, i2c_fd, 0x1b,0x81);
single_world_write(CHIP_ADDR1, i2c_fd, 0x1c,0x81);
single_world_write(CHIP_ADDR1, i2c_fd, 0x1d,0x01); //T4=2*260ms
single_world_write(CHIP_ADDR1, i2c_fd, 0x1e,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x1f,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x20,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x21,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x22,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x23,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x24,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x25,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x26,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x07,0xff); //雪白
single_world_write(CHIP_ADDR1, i2c_fd, 0x08,0xfa);
single_world_write(CHIP_ADDR1, i2c_fd, 0x09,0xfa);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0a,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0b,0xfa);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0c,0xfa);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0d,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0e,0xfa);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0f,0xfa);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x03,0x70); //One shot mode
single_world_write(CHIP_ADDR2, i2c_fd, 0x06,0x0); //INTB OUT1
single_world_write(CHIP_ADDR2, i2c_fd, 0x04,0x0); //主模式
single_world_write(CHIP_ADDR2, i2c_fd, 0x1a,0x81); //T1~T3; T3=2T1=2*260*2ms,T2=260
single_world_write(CHIP_ADDR2, i2c_fd, 0x1b,0x81);
single_world_write(CHIP_ADDR2, i2c_fd, 0x1c,0x81);
single_world_write(CHIP_ADDR2, i2c_fd, 0x1d,0x01); //T4=2*260ms
single_world_write(CHIP_ADDR2, i2c_fd, 0x1e,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x1f,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x20,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x21,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x22,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x23,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x24,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x25,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x26,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x07,0xff); //雪白
single_world_write(CHIP_ADDR2, i2c_fd, 0x08,0xfa);
single_world_write(CHIP_ADDR2, i2c_fd, 0x09,0xfa);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0a,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0b,0xfa);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0c,0xfa);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0d,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0e,0xfa);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0f,0xfa);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff);
ALOGD("standby_mode:i2c_cfd = %d\n", i2c_fd);
return 0;
}
/*****************正在开机-蓝色呼吸灯********************
*
*
****************************************************/
int boot_system_state() //RGB单色呼吸
{
single_world_write(CHIP_ADDR1, i2c_fd, 0x03,0x70); //One shot mode
single_world_write(CHIP_ADDR1, i2c_fd, 0x06,0x10); //INTB OUT1
single_world_write(CHIP_ADDR1, i2c_fd, 0x04,0x80); //从模式
single_world_write(CHIP_ADDR1, i2c_fd, 0x1a,0x81); //T1~T3; T3=2T1=2*260*2ms,T2=260
single_world_write(CHIP_ADDR1, i2c_fd, 0x1b,0x81);
single_world_write(CHIP_ADDR1, i2c_fd, 0x1c,0x81);
single_world_write(CHIP_ADDR1, i2c_fd, 0x1d,0x01); //T4=2*260ms
single_world_write(CHIP_ADDR1, i2c_fd, 0x1e,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x1f,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x20,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x21,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x22,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x23,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x24,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x25,0x01);
single_world_write(CHIP_ADDR1, i2c_fd, 0x26,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x07,0x0); //雪白
single_world_write(CHIP_ADDR1, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x09,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0a,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0b,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0c,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0d,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0e,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x0f,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x03,0x70); //One shot mode
single_world_write(CHIP_ADDR2, i2c_fd, 0x06,0x0); //INTB OUT1
single_world_write(CHIP_ADDR2, i2c_fd, 0x04,0x0); //主模式
single_world_write(CHIP_ADDR2, i2c_fd, 0x1a,0x81); //T1~T3; T3=2T1=2*260*2ms,T2=260
single_world_write(CHIP_ADDR2, i2c_fd, 0x1b,0x81);
single_world_write(CHIP_ADDR2, i2c_fd, 0x1c,0x81);
single_world_write(CHIP_ADDR2, i2c_fd, 0x1d,0x01); //T4=2*260ms
single_world_write(CHIP_ADDR2, i2c_fd, 0x1e,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x1f,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x20,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x21,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x22,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x23,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x24,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x25,0x01);
single_world_write(CHIP_ADDR2, i2c_fd, 0x26,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x07,0x0); //雪白
single_world_write(CHIP_ADDR2, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x09,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0a,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0b,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0c,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0d,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0e,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0f,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff);
ALOGD("boot_system_state:i2c_cfd = %d\n", i2c_fd);
return 0;
}
/*****************网络异常状态-常亮红色********************
*
*
****************************************************/
int network_anomaly_state()
{
single_world_write(CHIP_ADDR1, i2c_fd, 0x03, 0x0); //pwm mode
single_world_write(CHIP_ADDR2, i2c_fd, 0x03, 0x0); //pwm mode
single_world_write(CHIP_ADDR1, i2c_fd, 0x07,0xff); //红色
single_world_write(CHIP_ADDR1, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xa,0xff); //红色
single_world_write(CHIP_ADDR1, i2c_fd, 0xb,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xc,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xd,0xff); //红色
single_world_write(CHIP_ADDR1, i2c_fd, 0xe,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xf,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
single_world_write(CHIP_ADDR2, i2c_fd, 0x07,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0a,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0b,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0c,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0d,0xff); //
single_world_write(CHIP_ADDR2, i2c_fd, 0x0e,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0f,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
ALOGD("network_anomaly_state:i2c_cfd = %d\n", i2c_fd);
return 0;
}
/*****************程序系统异常状态-红色闪烁********************
* seconds:红色闪烁状态间隔时间
*
****************************************************/
int abnormal_state(unsigned int seconds)
{
single_world_write(CHIP_ADDR1, i2c_fd, 0x03, 0x0); //pwm mode
single_world_write(CHIP_ADDR2, i2c_fd, 0x03, 0x0); //pwm mode
while(1)
{
single_world_write(CHIP_ADDR1, i2c_fd, 0x07,0xff); //红色
single_world_write(CHIP_ADDR1, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xa,0xff); //红色
single_world_write(CHIP_ADDR1, i2c_fd, 0xb,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xc,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xd,0xff); //红色
single_world_write(CHIP_ADDR1, i2c_fd, 0xe,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xf,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
single_world_write(CHIP_ADDR2, i2c_fd, 0x07,0xff); //红色
single_world_write(CHIP_ADDR2, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0a,0xff); //红色
single_world_write(CHIP_ADDR2, i2c_fd, 0x0b,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0c,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0d,0xff); //红色
single_world_write(CHIP_ADDR2, i2c_fd, 0x0e,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0f,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
sleep(seconds);
single_world_write(CHIP_ADDR1, i2c_fd, 0x07,0x0); //黑色
single_world_write(CHIP_ADDR1, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xa,0x0); //黑色
single_world_write(CHIP_ADDR1, i2c_fd, 0xb,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xc,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xd,0x0); //黑色
single_world_write(CHIP_ADDR1, i2c_fd, 0xe,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xf,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
single_world_write(CHIP_ADDR2, i2c_fd, 0x07,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0a,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0b,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0c,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0d,0x0); //
single_world_write(CHIP_ADDR2, i2c_fd, 0x0e,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0f,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
sleep(seconds);
}
abnormal_state_thread = -1;
pthread_exit(0);
ALOGD("abnormal_state:i2c_cfd = %d\n", i2c_fd);
return 0;
}
/***************跟随音乐跳动状态**********************
*
*
****************************************************/
int audio_mode() //Audio mode
{
single_world_write(CHIP_ADDR1, i2c_fd, 0x03, 0x04); //PWM mode; AE AGC
single_world_write(CHIP_ADDR1, i2c_fd, 0x04, 0x6); //5mA, 18dB
single_world_write(CHIP_ADDR2, i2c_fd, 0x03, 0x04); //PWM mode; AE AGC
single_world_write(CHIP_ADDR2, i2c_fd, 0x04, 0x6); //5mA, 18dB
single_world_write(CHIP_ADDR1, i2c_fd, 0x07,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0x08,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0xa,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0xb,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0xc,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0xd,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0xe,0xff);
single_world_write(CHIP_ADDR1, i2c_fd, 0xf,0x0);
single_world_write(CHIP_ADDR1, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
single_world_write(CHIP_ADDR2, i2c_fd, 0x07,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x08,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x09,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0a,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0b,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0c,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0d,0x0);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0e,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x0f,0xff);
single_world_write(CHIP_ADDR2, i2c_fd, 0x10,0xff); //更新数据到各PWM寄存器里面
ALOGD("audio_mode:i2c_cfd = %d\n", i2c_fd);
return 0;
}
int sn3199_init()
{
//打开通用设备驱动文件
i2c_fd = open("/dev/i2c-1", O_RDWR);
if(i2c_fd < 0)
{
ALOGD("Open /dev/i2c-1 error:\n");
return -1;
}
ALOGD("sn3199_init:i2c_cfd = %d\n", i2c_fd);
return 0;
}
static struct sn3199_device_t sn3199_dev =
{
.sn3199_device =
{
.tag = HARDWARE_DEVICE_TAG,
.close = sn3199_close,
},
.set_light_state = set_light_state,
};
//logcat -s "SN3199_HAL"
//实现open函数
static int open_sn3199_hal(const struct hw_module_t* module, char const* id, struct hw_device_t** device)
{
ALOGD("open_sn3199 exec.....");
sn3199_init(); //获取i2c设备符
/* struct sn3199_device_t *dev = calloc(1, sizeof(struct sn3199_device_t));
dev->sn3199_device.tag = HARDWARE_DEVICE_TAG;
dev->sn3199_device.close = (int (*)(struct hw_device_t *))sn3199_close;
dev->set_light_state = set_light_state;
*device = (struct hw_device_t*)dev;*/
*device = &sn3199_dev;
return 0;
}
int set_light_state(struct sn3199_device_t *dev, int state)
{
ALOGD("set_light_state exec....");
g_Flag = 0;
reset();
switch (state) {
case 1:
ALOGD("standby_mode....");
standby_mode();
break;
case 2:
ALOGD("normally_bright_white....");
normally_bright_white();
break;
case 3:
ALOGD("abnormal_state");
pthread_create(&abnormal_state_thread, NULL, (void *)&abnormal_state, (void *)1);
g_Flag = 1;
//pthread_join(abnormal_state_thread, NULL);
break;
case 4:
ALOGD("audio_mode");
audio_mode();
break;
case 5:
ALOGD("network_anomaly_state");
network_anomaly_state();
break;
case 6:
ALOGD(" boot_system_state");
boot_system_state();
break;
default:
break;
}
return 0;
}
static int sn3199_close(struct sn3199_device_t *dev)
{
if(i2c_fd > 0)
{
close(i2c_fd);
i2c_cfd = -1;
}
if(dev)
free(dev);
g_Flag = -1;
return 0;
}
//定义HAL_MODULE_INFO_SYM,并对其进行初始化
static hw_module_methods_t sn3199_methods =
{
.open = open_sn3199_hal,
};
struct hw_module_t HAL_MODULE_INFO_SYM =
{
.tag = HARDWARE_MODULE_TAG,
.id = **SN3199_HARDWARE_MODULE_ID**, //该id起到了承上启下的作用,硬件服务层会匹配该id,一般这里使用宏定义(VIBRATOR_HARDWARE_MODULE_ID),不然可能会出错
.author = "yjd",
.methods = &sn3199_methods,
};
- sn3199_hal.h(相对android源码路径:hardware/libhardware/include/hardware/)
#ifndef _SN3199_HAL_H_
#define _SN3199_HAL_H_
#include <hardware/hardware.h>
#include <pthread.h>
#define SN3216_REG_LED_EFFECT 0x04
void single_world_write(unsigned char chip_addr, int i2c_fd, unsigned short reg, unsigned char val);
void burst_model_write(unsigned char chip_addr, int i2c_fd, unsigned short reg, unsigned char *data, unsigned int data_len);
unsigned char single_world_read(unsigned char chip_addr, int i2c_fd, unsigned short reg);
unsigned char * burst_model_read(unsigned char chip_addr, int i2c_fd, unsigned short reg, unsigned int data_len);
int reset();
int normally_bright_white();
int standby_mode();
int boot_system_state(); //RGB单色呼吸
int network_anomaly_state();
int abnormal_state(unsigned int seconds);
int audio_mode(); //Audio mode
static unsigned char g_Ledctrl1=0,g_Ledctrl2=0,g_LedEffect = 0;
static unsigned char g_Flag = 0;
pthread_t abnormal_state_thread = -1;
#define CHIP_ADDR1 0x64
#define CHIP_ADDR2 0x67
#define uchar unsigned char
#define uint unsigned int
#define SN3199_HARDWARE_MODULE_ID "sn3199"
//自定义一个对外的结构体
struct sn3199_device_t
{
struct hw_device_t sn3199_device;
int (*set_light_state)(struct sn3199_device_t *dev, int state);
};
static int sn3199_close(struct sn3199_device_t *dev);
int set_light_state(struct sn3199_device_t *dev, int state);
#endif
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE := sn3199.default #sn3199_hal_default.so
# HAL module implementation stored in
# hw/<VIBRATOR_HARDWARE_MODULE_ID>.default.so
LOCAL_MODULE_RELATIVE_PATH := hw #/system/lib/hw/
LOCAL_C_INCLUDES := hardware/libhardware
LOCAL_SRC_FILES := sn3199_hal.c
LOCAL_SHARED_LIBRARIES := liblog
LOCAL_MODULE_TAGS := optional
include $(BUILD_SHARED_LIBRARY)
以上就是hal的代码,通过mm命令最后生成sn3199.default.so
第三步:硬件访问服务程序设计(解决上层访问硬件冲突)
下面是具体的代码实现
- ISn3199Service.aidl(Android源码目录的相对路径:frameworks/base/core/java/android/os/)
package android.os;
/** {@hide} */
interface ISn3199Service
{
int sn3199Open(); //打开sn3199
int setLightState(int state); //设置sn3199灯光状态
}
该文件最后会生成实现Stub类方法的文件ISn3199Service.java(生成文件相对Android源码路径:out/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/os)
- Android.mk(相对Android源码相对路径:frameworks/base)
.
.
.
core/java/android/os/IVibratorService.aidl \
+ core/java/android/os/ISn3199Service.aidl
.
.
.
Sn3199Service.java(相对Android路径:frameworks/base/services/core/java/com/android/server/)
package com.android.server;
import android.util.Slog;
import android.os.ISn3199Service;
public class Sn3199Service extends ISn3199Service.Stub {
private static final String TAG = "Sn3199Service";
public Sn3199Service()
{
Slog.d(TAG, "Sn3199Service");
}
//打开sn3199
public int sn3199Open() throws android.os.RemoteException
{
return nativeSn3199Open();
}
//设置sn3199灯光状态
public int setLightState(int state) throws android.os.RemoteException
{
return nativeSetLightState(state);
}
//声明本地函数
public static native int nativeSn3199Open();
public static native int nativeSetLightState(int state);
}
服务层调用hal层通过JNI
- 将硬件服务注册到ServiceManager中去
SystemServer.java(相对Android源码路径:frameworks/base/services/java/com/android/server/)
......
VibratorService vibrator = null;
+Sn3199Service sn3199 = null;
IAlarmManager alarm = null;
.......
Slog.i(TAG, "Vibrator Service");
vibrator = new VibratorService(context);
ServiceManager.addService("vibrator", vibrator);
+Slog.i(TAG, "Sn3199 Service");
+sn3199 = new Sn3199Service(); //我们的构造函数是无参数构造函数,所以这里为空
+ServiceManager.addService("sn3199", sn3199);
实现jni调用
- com_android_server_Sn3199Service.cpp(相对Android源码目录:frameworks/base/services/core/jni/)
#define LOG_TAG "Sn3199Service"
#include "jni.h"
#include "JNIHelp.h"
#include "android_runtime/AndroidRuntime.h"
#include <utils/misc.h>
#include <utils/Log.h>
#include <hardware/sn3199_hal.h>
#include <stdio.h>
struct sn3199_device_t *sn3199_dev;
namespace android
{
//JNI调用
static jint sn3199Open(JNIEnv *env, jobject clazz)
{
hw_module_t* module;
hw_device_t* device;
jint err;
err = hw_get_module(SN3199_HARDWARE_MODULE_ID , (hw_module_t const**)&module); //获取到对应的hal中的modules对象,第一个参数为hal层中的id
if(err == 0)
{
ALOGD("module->methods->open");
module->methods->open(module, NULL, &device); //获取到hal中的device信息
sn3199_dev = (struct sn3199_device_t* )device;
return 0;
}
else
{
ALOGD("hw_get_module exec error");
}
return -1;
}
static jint setLightState(JNIEnv *env, jobject clazz, int state) //前面了两个参数是系统带的一定要有的,后面的是用户自定参数
{
sn3199_dev->set_light_state(sn3199_dev, state);
return 0;
}
static JNINativeMethod method_table[] = {
{ "nativeSn3199Open", "()I", (void*)sn3199Open }, //第二个参数()参数个数,I-返回值类型
{ "nativeSetLightState", "(I)I", (void*)setLightState }
};
int register_android_server_Sn3199Service(JNIEnv *env)
{
return jniRegisterNativeMethods(env, "com/android/server/Sn3199Service",
method_table, NELEM(method_table));
}
};
加载cpp文件到Android.mk中(相对Android源码目录:frameworks/base/services/core/jni)
$(LOCAL_REL_DIR)/com_android_server_VibratorService.cpp \
+$(LOCAL_REL_DIR)/com_android_server_Sn3199Service.cpp \
调用register_android_server_Sn3199Service函数
- onload.cpp(相对Android源码目录:frameworks/base/services/core/jni/)
.......
int register_android_server_VibratorService(JNIEnv* env);
//and by yjd
1. int register_android_server_Sn3199Service(JNIEnv *env); //定义
//end
.....
register_android_server_VibratorService(env);
//and by yjd
2. register_android_server_Sn3199Service(env); //调用
//end
register_android_server_SystemServer(env);
...
hal层问题编译总结:第一个是,自己编写的hal层源码怎么添加进Android的默认编译中去,也就是说在根目录执行make时,自己编写hal源码也会被编译。第二个问题是,编译完成后还要自动安装在指定的系统目录lib/hw下。刚开始时不太了解,总是需要使用mmm来进行编译安装,但是打包之后再编译这是不现实的。为此需要添加到默认中
解决方法:
在写好hardware/libhardware/modules/sn3199工程文件时,要将sn3199目录加到modules的Android.mk中,hardware_modules变量中添加sn3199文件夹的名字即可,这样在默认中就会自动编译这个sn3199的文件,这样虽然可以编译了,但是不会自动安装,如果在源码根目录下编译安装sn3199,还需修改device/s3graphics/zx2000/zx2000.mk这个文件中的PRODUCT_PACKAGES变量,在文件中添加PRODUCT_PACKAGES += sn3199.default代码即可
这样上图中的stub、Java、JNI都完成了(已经凌晨1点了,挺住写完再睡)
在framework/base/目录下执行mm命令进行编译
接下来就是编写APP进行测试了,测试之前要将刚编译框架层中的classes.jar(相对Android源码路径:out/target/common/obj/JAVA_LIBRARIES/framework_intermediates)拷贝出来供APP使用,直接上代码,APP只是测试用,所以就随便写了
- MainActivity.java
package com.example.yjd.sn3199interfacetest;
import android.os.Bundle;
import android.os.ISn3199Service;
import android.os.RemoteException;
import android.os.ServiceManager;
import android.support.v7.app.AppCompatActivity;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
public class MainActivity extends AppCompatActivity implements View.OnClickListener {
private ISn3199Service iSn3199Service = null;
private Button[] btnState = new Button[6];
Toast toast;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
iSn3199Service = ISn3199Service.Stub.asInterface(ServiceManager.getService("sn3199"));
if(null != iSn3199Service) {
try {
iSn3199Service.sn3199Open();
} catch (RemoteException e) {
e.printStackTrace();
}
}
btnState[0] = (Button) findViewById(R.id.state1);
btnState[1] = (Button) findViewById(R.id.state2);
btnState[2] = (Button) findViewById(R.id.state3);
btnState[3] = (Button) findViewById(R.id.state4);
btnState[4] = (Button) findViewById(R.id.state5);
btnState[5] = (Button) findViewById(R.id.state6);
for (int i = 0; i < 6; i++) {
btnState[i].setOnClickListener(this);
}
}
public void onClick(View v) {
switch (v.getId()) {
case R.id.state1: //待机-白色呼吸灯效果
try{
iSn3199Service.setLightState(1);
}catch(RemoteException e) {
e.printStackTrace();
}
toast = Toast.makeText(this, "待机-白色呼吸灯效果设置成功", Toast.LENGTH_SHORT);
toast.show();
break;
case R.id.state2: //正常工作(音箱本身喇叭不工作)-常亮白色
try{
iSn3199Service.setLightState(2);
}catch(RemoteException e)
{
e.printStackTrace();
}
toast = Toast.makeText(this, "待机-白色呼吸灯效果设置成功", Toast.LENGTH_SHORT);
toast.show();
break;
case R.id.state3: //程序系统异常状态-红色闪烁
try{
iSn3199Service.setLightState(3);
}catch(RemoteException e)
{
e.printStackTrace();
}
toast = Toast.makeText(this, "程序系统异常状态-红色闪烁设置成功", Toast.LENGTH_SHORT);
toast.show();
break;
case R.id.state4: //跟随音乐跳动状态
try{
iSn3199Service.setLightState(4);
}catch(RemoteException e)
{
e.printStackTrace();
}
toast = Toast.makeText(this, "跟随音乐跳动状态设置成功", Toast.LENGTH_SHORT);
toast.show();
break;
case R.id.state5: //网络异常状态-常亮红色
try{
iSn3199Service.setLightState(5);
}catch(RemoteException e)
{
e.printStackTrace();
}
toast = Toast.makeText(this, "网络异常状态-常亮红色设置成功", Toast.LENGTH_SHORT);
toast.show();
break;
case R.id.state6: //正在开机-蓝色呼吸灯
try{
iSn3199Service.setLightState(6);
}catch(RemoteException e)
{
e.printStackTrace();
}
toast = Toast.makeText(this, "正在开机-蓝色呼吸灯设置成功", Toast.LENGTH_SHORT);
toast.show();
break;
default:
break;
}
}
}
- activity_main.xml
<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.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="com.example.yjd.sn3199interfacetest.MainActivity">
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="State1"
android:id="@+id/state1"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="State2"
android:id="@+id/state2"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="State3"
android:id="@+id/state3"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="State4"
android:id="@+id/state4"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="State5"
android:id="@+id/state5"/>
<Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="State6"
android:id="@+id/state6"/>
</LinearLayout>
</android.support.constraint.ConstraintLayout>
编译的时候可能会遇到方法超过64K的错误,这里添加两行代码完美解决
OK,终于写完了,至于怎么添加classes.jar包到Android项目中应该就很简单了,还是贴张图吧
这里添加依赖选第3个选模块依赖:ModuleDependency
在此特别注意的时候,在调试底层代码的时候,多看main log, 用logcat -v time -b main 命令
如果有什么疑问可以加QQ:1308418494一起讨论学习,欢迎大神指点