Android驱动模型(kernel-hal-framework-app)
来源:互联网 发布:网络安全技术一般包括 编辑:程序博客网 时间:2024/06/06 18:29
读书的时候有写博客的习惯,后面就再也没写过了,发现很多知识点整理在电脑上容易丢失,也不能共享,所以今天又拿起笔开始写博客了,这篇文章的内容是基于兆芯平台的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/)
#ifndef _SN3199_HAL_H_#define _SN3199_HAL_H_#include <hardware/hardware.h>#include <pthread.h>#define SN3216_REG_LED_EFFECT 0x04void 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 modestatic 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
- Anddroid.mk
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.soLOCAL_MODULE_RELATIVE_PATH := hw #/system/lib/hw/LOCAL_C_INCLUDES := hardware/libhardwareLOCAL_SRC_FILES := sn3199_hal.cLOCAL_SHARED_LIBRARIES := liblogLOCAL_MODULE_TAGS := optionalinclude $(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); //调用 //endregister_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一起讨论学习,欢迎大神指点
- Android驱动模型(kernel-hal-framework-app)
- android驱动初探(kernel->hal->jni->service->app)
- app应用--->framework层---->hal硬件抽象层---->kernel driver
- Android—GSensor驱动与HAL/Framework
- Android HAL层与Linux Kernel层驱动开发简介
- Android5.0编写hello从APP->framework->jni->hal->驱动的BUG
- Android HAL驱动开发
- Android平台添加外设的架构流程(kernel->HAL->JNI->API->APP)之学习提高篇
- Android平台添加外设的架构流程(kernel->HAL->JNI->API->APP)之学习提高篇
- led分析(app->framework->jni->hal)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Android之 看“马达”如何贯通Android系统 (从硬件设计 --> 驱动 --> HAL --> JNI --> Framework --> Application)
- Ubuntu 16.04 系统快捷键推荐设置
- Go语言switch语句
- Catalan数
- linux1
- Visual Studio 2010 + MPI + 环境搭建
- Android驱动模型(kernel-hal-framework-app)
- 6.3 代理的部署位置
- VTK图像操作之灰度映射
- Java字节码指令
- 6.4 客户端的代理设置
- 10.21刷题记录
- 经典书籍
- bzoj1978 [BeiJing2010]取数游戏 game DP
- Java复习题