标签:
2012-08-07 14:56 2608人阅读 举报
分类:
android开发(5)
版权声明:本文为博主原创文章,未经博主允许不得转载。
在android开发和移植过程中,有时需要对某设备进行读写,但系统可能并未提供相应的服务。我们就需要自己开发硬件访问服务来控制设备。下面的例子是读写最简单的i2c设备eeprom的流程, i2c的驱动编写有两种方式,一种是利用系统提供的i2c-dev.c来实现一个i2c适配器的设备文件,然后通过在应用层操作I2C适配器来控制I2C设备;另一种是为I2C从设备独立编写一个设备驱动,不需要i2c-dev.c文件。由于前者比较简单通用性强,我们采用前者来展开。
根据android层次划分,我们照例对开发分为如下几步:
1. 添加HAL层接口模块访问设备
2. 使用JNI在应用程序框架层添加服务访问接口
3. 使用服务接口api开发应用程序
一. 添加HAL层接口模块访问设备
首先确认物理设备正常。根据开发板说明书获知设备挂载在/dev/i2c-1上,检测到该设备的存在,则通用设备驱动正常。
eeprom设备为at24c**系列,根据说明书获知设备从地址为0x50,准备工作完毕。
1. 编写hal层接口模块头文件iic.h
进入源码根目录下hardware/libhardware/include/hardware目录新建iic.h,代码如下:
-
#ifndef ANDROID_IIC_INTERFACE_H
-
#define ANDROID_IIC_INTERFACE_H
-
#include
-
-
__BEGIN_DECLS
-
-
-
#define IIC_HARDWARE_MODULE_ID "iic"
-
-
-
struct iic_module_t {
-
struct hw_module_t common;
-
};
-
-
-
struct iic_device_t {
-
struct hw_device_t common;
-
int fd;
-
int (*iic_write)(struct iic_device_t* dev, unsigned char* dataBuf, unsigned short slaveAddr, unsigned short subAddr, int len);
-
int (*iic_read)(struct iic_device_t* dev, unsigned char* dataBuf, unsigned short slaveAddr, int len);
-
};
-
-
__END_DECLS
-
-
#endif
这里定义了iic_write和iic_read两个接口,头文件按照hal规范编写。
2. 编写hal层接口模块文件
进入源码根目录下hardware/libhardware/modules目录新建iic目录,并在iic目录中添加iic.c,代码如下:
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
#include
-
"font-size:14px;">#define DEVICE_NAME "/dev/i2c-1"
-
#define MODULE_NAME "iic"
-
#define MODULE_AUTHOR "mfayz@sohu.com"
-
-
-
#define I2C_RETRIES 0x0701/* number of times a device address should be polled when not acknowledging */
-
#define I2C_TIMEOUT 0x0702/* set timeout in units of 10 ms */
-
#define I2C_RDWR 0x0707
-
-
-
-
struct i2c_msg
-
{
-
unsigned short addr;
-
unsigned short flags;
-
#define I2C_M_TEN 0x0010
-
#define I2C_M_RD 0x0001
-
unsigned short len;
-
unsigned char *buf;
-
};
-
-
-
struct i2c_rdwr_ioctl_data {
-
struct i2c_msg *msgs;
-
int nmsgs;
-
};
-
-
-
-
static int iic_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device);
-
static int iic_device_close(struct hw_device_t* device);
-
-
-
static int iic_write(struct iic_device_t* dev, unsigned char* dataBuf, unsigned short slaveAddr, unsigned short subAddr, int len);
-
static int iic_read(struct iic_device_t* dev, unsigned char* dataBuf, unsigned short slaveAddr, int len);
-
-
-
static struct hw_module_methods_t iic_module_methods = {
-
open: iic_device_open
-
};
-
-
-
struct i2c_rdwr_ioctl_data iic_data;
-
int ret;
-
-
-
-
struct iic_module_t HAL_MODULE_INFO_SYM = {
-
common: {
-
tag: HARDWARE_MODULE_TAG,
-
version_major: 1,
-
version_minor: 0,
-
id: IIC_HARDWARE_MODULE_ID,
-
name: MODULE_NAME,
-
author: MODULE_AUTHOR,
-
methods: &iic_module_methods,
-
}
-
};
-
-
-
static int iic_device_open(const struct hw_module_t* module, const char* name, struct hw_device_t** device){
-
struct iic_device_t* dev;
-
dev = (struct iic_device_t*)malloc(sizeof(struct iic_device_t));
-
if(!dev) {
-
LOGE("iic Stub: failed to alloc space");
-
return -EFAULT;
-
}else{
-
LOGE("hal: alloc space succ!");
-
}
-
-
memset(dev, 0, sizeof(struct iic_device_t));
-
dev->common.tag = HARDWARE_DEVICE_TAG;
-
dev->common.version = 0;
-
dev->common.module = (hw_module_t*)module;
-
dev->common.close = iic_device_close;
-
dev->iic_write = iic_write;
-
dev->iic_read = iic_read;
-
*device = &dev->common;
-
-
-
if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
-
LOGE("iic Stub hal: failed to open /dev/i2c-1 -- %s.", strerror(errno));
-
free(dev);
-
return -EFAULT;
-
}else{
-
LOGI("iic Stub hal: open /dev/i2c-1 successfully.");
-
iic_data.nmsgs=2;
-
iic_data.msgs=(struct i2c_msg*)malloc(iic_data.nmsgs*sizeof(struct i2c_msg));
-
-
-
if(!iic_data.msgs){
-
LOGE("malloc error");
-
close(dev->fd);
-
exit(1);
-
}
-
ioctl(dev->fd, I2C_TIMEOUT, 2);
-
ioctl(dev->fd, I2C_RETRIES, 1);
-
}
-
return 0;
-
}
-
-
-
static int iic_device_close(struct hw_device_t* device) {
-
struct iic_device_t* iic_device = (struct iic_device_t*)device;
-
-
if(iic_device) {
-
close(iic_device->fd);
-
free(iic_device);
-
}
-
-
return 0;
-
}
-
-
static int iic_write(struct iic_device_t* dev, unsigned char* dataBuf, unsigned short slaveAddr, unsigned short subAddr, int len) {
-
int count = 0;
-
unsigned char data[2];
-
unsigned char bytes;
-
-
-
LOGI("iic Stub hal: set value %s to device.", dataBuf);
-
iic_data.nmsgs=1;
-
(iic_data.msgs[0]).len=2;
-
(iic_data.msgs[0]).addr=slaveAddr;
-
(iic_data.msgs[0]).flags=0;
-
(iic_data.msgs[0]).buf=(unsigned char*)malloc(2);
-
while(count
-
bytes = 0;
-
data[bytes++] = subAddr;
-
data[bytes] = dataBuf[count];
-
LOGI("IIC write HAL: %x,%x", data[0],data[1]);
-
(iic_data.msgs[0]).buf=data;
-
ret=ioctl(dev->fd,I2C_RDWR,(unsigned long)&iic_data);
-
if(ret<0){
-
LOGI("IIC HAL ioctl error");
-
}
-
count++;
-
subAddr++;
-
usleep(3000);
-
}
-
LOGI("you have write %s into iic at %x address len: %d",dataBuf, subAddr, len);
-
-
return 0;
-
}
-
-
static int iic_read(struct iic_device_t* dev, unsigned char* dataBuf, unsigned short slaveAddr, int len){
-
int count = 0;
-
-
iic_data.nmsgs=1;
-
-
(iic_data.msgs[0]).len=1;
-
(iic_data.msgs[0]).addr=slaveAddr;
-
(iic_data.msgs[0]).flags=I2C_M_RD;
-
(iic_data.msgs[0]).buf=(unsigned char*)malloc(1);
-
while(count
-
(iic_data.msgs[0]).buf= dataBuf++;
-
if(ioctl(dev->fd,I2C_RDWR,(unsigned long)&iic_data)<0){
-
LOGE("ioctl read error");
-
}
-
LOGI("IIC read HAL: %x", dataBuf[count]);
-
count++;
-
}
-
-
return 0;
-
}
注意:需打开设备/dev/i2c-1权限,否则会碰到Pemission
Denied错误。从源码根目录下进入system/core/rootdir目录,打开ueventd.rc 添加一行:/dev/i2c-1
0666 root root (这里设备各开发板可能不同)
3. 在iic目录下编写android.mk进行编译
-
LOCAL_PATH := $(call my-dir)
-
include $(CLEAR_VARS)
-
LOCAL_MODULE_TAGS := optional
-
LOCAL_PRELINK_MODULE := false
-
LOCAL_MODULE_PATH := $(TARGET_OUT_SHARED_LIBRARIES)/hw
-
LOCAL_SRC_FILES := iic.c
-
LOCAL_MODULE := iic.default
-
include $(BUILD_SHARED_LIBRARY)
编译命令:mmm -B hardware/libhardware/module/iic 编译成功会得到iic.default.so,打包进img默认会被加载。
(待续)
阅读(1272) | 评论(0) | 转发(0) |