RK3288 android7.1.2 HAL层添加I2C read/write interface,给java 层调用(可根据slave device 更改时序)(进阶篇一)

准备工作如下:

确认物理设备是否已经正常连接,请根据https://blog.csdn.net/Chhjnavy/article/details/95215479 该篇文章查看设备名称,android6.0.1 i2c_detect 可以用,但是android7.1.2  i2c_detect 本人测试无法使用,但是可以看到i2c设备名称如下:

本人案例是按照设备名为:i2c-1 进行硬件连接的。

还需要注意在打开i2c-1设备时,可能会遇到Pemission Denied错误,如若遇到,请从源码根目录下进入system/ core/rootdir目录,打开ueventd.rc 添加一行:/dev/i2c-1 0666 root root   ,每个开发板可能书写格式有所不同,请参考改文件内别的设备书写格式!

以下是在android7.1.2 源码目录下添加HAL层i2c 模块的详细步骤:

1.编写HAL层i2c模块的头文件iic.h

在源码根目录下:hardware/libhardware/include/hardware 新建iic.h文件

#ifndef _HARDWARE_IIC_H
#define _HARDWARE_IIC_H


#include <stdint.h>
#include <strings.h>
#include <sys/cdefs.h>
#include <sys/types.h>

#include <hardware/hardware.h>

__BEGIN_DECLS

#define IIC_HARDWARE_MODULE_ID "iic"
#define DEVICE_NAME "/dev/i2c-1"

#define I2C_RETRIES 0x0701
#define I2C_TIMEOUT 0x0702
#define I2C_RDWR	0x0707  
#define I2C_M_TEN 	0x0010  
#define I2C_M_RD 	0x0001


struct iic_module_t {

    struct hw_module_t common;

};

typedef struct iic_device {

    struct hw_device_t common;
	int fd;
	int (*iic_write)(struct iic_device *dev, unsigned int slaveAddr, unsigned int regAddr, unsigned char dataBuf);
    int (*iic_read)(struct iic_device *dev, unsigned int slaveAddr, unsigned int regAddr, unsigned char *dataBuf);

} iic_device_t;


static inline int iic_open(const struct hw_module_t* module,
        iic_device_t** dev) {
    return module->methods->open(module, IIC_HARDWARE_MODULE_ID,
        (struct hw_device_t**) dev);
}

static inline int iic_close(iic_device_t* dev) {
    return dev->common.close(&dev->common);
}

__END_DECLS

#endif


2.编写HAL层i2c模块的iic.c 

在源码目录下:hardware/libhardware/modules 新建iic目录,在该目录下新建iic.c 和 Android.mk 文件

#include <hardware/iic.h>
#include <hardware/hardware.h>

#include <cutils/atomic.h>   
#include <linux/i2c.h>  
#include <linux/i2c-dev.h>  
#include <stdlib.h>  
#include <linux/types.h>   
#include <sys/types.h>  
#include <sys/ioctl.h> 

#include <cutils/log.h>
#include <malloc.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <errno.h>
#include <math.h>
#include <string.h>

struct i2c_rdwr_ioctl_data iic_data;
int ret;

static int t613_iic_write(iic_device_t *dev __unused, unsigned int slaveAddr, unsigned int regAddr, unsigned char dataBuf) {

	iic_data.nmsgs=1;
	(iic_data.msgs[0]).len = 3;
	(iic_data.msgs[0]).addr = slaveAddr>>1;
	(iic_data.msgs[0]).flags = 0; //write
	(iic_data.msgs[0]).buf = (unsigned char*)malloc(3);
	(iic_data.msgs[0]).buf[0] = (unsigned char)(regAddr>>8);
	(iic_data.msgs[0]).buf[1] = (unsigned char)(regAddr);
	(iic_data.msgs[0]).buf[2] = dataBuf;

	ALOGE("IIC write HAL: From register %06x write ",regAddr);
	ALOGE("%04x ",(iic_data.msgs[0]).buf[2]);

	ret=ioctl(dev->fd,I2C_RDWR,(unsigned long)&iic_data);
	if(ret<0) ALOGE("IIC HAL write ioctl error.");
	
	usleep(3000);
	return 0;
}


static int t613_iic_read(iic_device_t *dev __unused,  unsigned int slaveAddr, unsigned int regAddr, unsigned char *dataBuf) {   

	iic_data.nmsgs = 2;
	(iic_data.msgs[0]).addr  = slaveAddr >>1;
	(iic_data.msgs[0]).flags = 0 ;
	(iic_data.msgs[0]).len = 2;
	(iic_data.msgs[0]).buf = (unsigned char*)malloc(2);
	(iic_data.msgs[0]).buf[0] = (unsigned char)(regAddr>>8);
	(iic_data.msgs[0]).buf[1] = (unsigned char)(regAddr);

	(iic_data.msgs[1]).addr  = slaveAddr >>1;
	(iic_data.msgs[1]).flags = I2C_M_RD;
	(iic_data.msgs[1]).len = 1;
	(iic_data.msgs[1]).buf=(unsigned char*)malloc(1);
	(iic_data.msgs[1]).buf = dataBuf;

	ALOGE("IIC read HAL: From register %06x read ",regAddr);
	ALOGE("%04x ",(iic_data.msgs[1]).buf[0]);

	ret=ioctl(dev->fd,I2C_RDWR,(unsigned long)&iic_data); 
	if(ret<0) ALOGE("IIC HAL read ioctl error.");

	usleep(3000);
	return 0;
}


static int iic_device_close(hw_device_t *dev) {
    free(dev);
    return 0;
}

static int iic_device_open(const hw_module_t* module, const char* name,
        hw_device_t** device) {
    if (strcmp(name, IIC_HARDWARE_MODULE_ID) == 0) {
        iic_device_t *dev = calloc(1, sizeof(iic_device_t));

        dev->common.tag = HARDWARE_DEVICE_TAG;
        dev->common.version = 0x00010000; // [31:16] major, [15:0] minor
        dev->common.module = (struct hw_module_t*) module;
        dev->common.close = iic_device_close;

		dev->iic_write = t613_iic_write;
		dev->iic_read = t613_iic_read;
		
        *device = &dev->common;

		if((dev->fd = open(DEVICE_NAME, O_RDWR)) == -1) {
			ALOGE("iic Stub hal: failed to open /dev/i2c-1 --");  
			free(dev);	  
			return -EFAULT;    
		}else{		
			ALOGI("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){
	        	ALOGE("malloc error.");
				close(dev->fd);  
	        	exit(1);  
	    	}
			ioctl(dev->fd, I2C_TIMEOUT, 2);  
	    	ioctl(dev->fd, I2C_RETRIES, 1);
		}
        return 0;
    } else {
        return -EINVAL;
    }
}


/*===========================================================================*/
/* Default iic HW module interface definition                           */
/*===========================================================================*/

static struct hw_module_methods_t iic_module_methods = {
  .open = iic_device_open,
};

struct iic_module_t HAL_MODULE_INFO_SYM = {
  .common = {
	  .tag = HARDWARE_MODULE_TAG,
	  .module_api_version = 0x0100, // [15:8] major, [7:0] minor (1.0)
	  .hal_api_version = 0x00, // 0 is only valid value
	  .id = IIC_HARDWARE_MODULE_ID,
	  .name = "Default IIC HW HAL",
	  .author = "https://chhjnavy.github.io/",
	  .methods = &iic_module_methods,
  },
};

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE := iic.default
LOCAL_MODULE_RELATIVE_PATH := hw
LOCAL_SRC_FILES := iic.c
LOCAL_SHARED_LIBRARIES := liblog libcutils
LOCAL_MODULE_TAGS := optional

include $(BUILD_SHARED_LIBRARY)

在源码根目录下:hardware/libhardware/modules 修改Android.mk 添加iic 文件夹名

hardware_modules := gralloc hwcomposer audio nfc nfc-nci local_time \
	power usbaudio audio_remote_submix camera usbcamera consumerir sensors vibrator \
	tv_input fingerprint input vehicle thermal vr iic
include $(call all-named-subdir-makefiles,$(hardware_modules))

在源码根目录下执行:mmm hardware/libhardware/modules/iic/   会对iic 模块进行编译

在源码根目录下产生 out/target/product/rk3288/obj/lib/iic.default.so.toc 

3.编写在JNI (Java Native Interface)提供java层与C/C++交互的接口

在源码根目录下:frameworks/base/services/core/jni

    1) 新建com_android_server_IICService.cpp,然后需要让Android启动时加载此jni模块
    2) 在同目录下修改onload.cpp: 在namespace android中添加一行: int register_android_server_IICService(JNIEnv *env);
    3) 在JNI_onLoad方法中添加一行:  register_android_server_IICService(env);
    4) 在同目录下修改Android.mk: LOCAL_SRC_FILES增加一行: $(LOCAL_REL_DIR)/com_android_server_IICService.cpp \

#include "jni.h"    
#include "JNIHelp.h"    
#include "android_runtime/AndroidRuntime.h"    
#include <utils/misc.h>    
#include <cutils/log.h>    
#include <hardware/hardware.h>    
#include <hardware/iic.h>    
#include <stdio.h>  
  
namespace android    
{    

	struct iic_device *iic_dev = NULL;

    static void iic_setVal(JNIEnv* env, jobject clazz, jint slaveAddr, jint regAddr, jint databuf) {

		if(!iic_dev) {
			ALOGE("iic JNI: device is not open.");    
		}
		iic_dev->iic_write(iic_dev,slaveAddr,regAddr,databuf);
    }

    static jint iic_getVal(JNIEnv* env, jobject clazz,jint slaveAddr, jint regAddr) {

		unsigned char data[1] = {0};
    	iic_dev->iic_read(iic_dev,slaveAddr,regAddr,data);

		if(!iic_dev) {
            ALOGE("iic JNI: device is not open.");
		} 
		return data[0];
    }

	
    /*通过硬件模块ID来加载指定的硬件抽象层模块并打开硬件*/    
    static jboolean iic_init(JNIEnv* env, jclass clazz) {
    
 		iic_module_t *module;
		int err;
		err = hw_get_module(IIC_HARDWARE_MODULE_ID,(const struct hw_module_t**)&module);
		if (err != 0) {
			ALOGE("Error acquiring iic hardware module: %d", err);
			return 0;
		}

		err = iic_open(&(module->common), &iic_dev);
		if (err != 0) {
			ALOGE("Error opening iic hardware module: %d", err);
			return 0;
		}  
        ALOGE("iic device is opening...");    
        return 1;         
    }
        /*JNI方法表*/    
    static const JNINativeMethod method_table[] = {    
        {"init_native", "()Z", (void*)iic_init},
        {"setVal_native", "(III)V", (void*)iic_setVal},
        {"getVal_native", "(II)I", (void*)iic_getVal},
    };
    /*注册JNI方法*/    
    int register_android_server_IICService(JNIEnv *env) {    
            return jniRegisterNativeMethods(env, "com/android/server/IICService", method_table, NELEM(method_table));    
    } 
};

 在源码根目录下执行:mmm frameworks/base/services/core/jni   对该模块进行编译

4.编写跨进程访问服务AIDL(Android Interface Definition Language)

在源码根目录下:frameworks/base/core/java/android/os

    1)新建IIICService.aidl 文件

    2)修改frameworks/base下的Android.mk编译文件,在LOCAL_SRC_FILES中增加 core/java/android/os/IIICService.aidl \

package android.os;  
interface IIICService { 
    void setVal(int slaveAddr, int regAddr, int databuf);
    int getVal(int slaveAddr, int regAddr);
}

在源码根目录下执行:mmm frameworks/base   对该模块进行编译

5.编写AIDL(Android Interface Definition Language)具体实现的方法类

在源码根目录下:frameworks/base/services/core/java/com/android/server

    1)新建IICService.java文件

package com.android.server;    
import android.content.Context;    
import android.os.IIICService;    
import android.util.Slog;    
public class IICService extends IIICService.Stub {    
    private static final String TAG = "IICService";
    IICService() {    
        init_native();    
    }
    public void setVal(int slaveAddr, int regAddr, int databuf) {    
        setVal_native(slaveAddr, regAddr, databuf);   
    }       
    public int getVal(int slaveAddr, int regAddr) {   
        return getVal_native(slaveAddr, regAddr);
    }

    private static native boolean init_native();
    private static native void setVal_native(int slaveAddr, int regAddr, int databuf);
    private static native int getVal_native(int slaveAddr, int regAddr);
};

    2)修改frameworks/base/services/java/com/android/server下的SystemServer.java 在private void startOtherServices() 添加

try{

    Slog.i(TAG, "IIC SERVICE");
    ServiceManager.addService("iic", new IICService());
}catch(Throwable e){
    Slog.e(TAG, "Failure starting IIC Service", e);
}

在源码根目录下执行:mmm frameworks/base/services   对该模块进行编译

 6.编写app 用来测试iic 是否通讯正常

在源码根目录下:packages/apps/T613

主程序如下:

完整code 请到:https://download.csdn.net/download/chhjnavy/11389018 下载

package com.example.t613;

import android.support.v7.app.ActionBarActivity;
import android.os.ServiceManager;
import android.os.IIICService;
import android.os.Bundle;
import android.os.RemoteException;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.view.View.OnClickListener;
import android.widget.Button;
import android.widget.EditText;


public class MainActivity extends ActionBarActivity implements OnClickListener{
	
	private final static String LOG_TAG = "com.example.t613";
	private EditText valueText = null;
	private Button button_read = null;
	private Button button_write = null;
	private Button button_clear = null;
	
	private IIICService iicService = null;
	
	int len = 1;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        iicService = IIICService.Stub.asInterface(ServiceManager.getService("iic"));
        
        valueText = (EditText)findViewById(R.id.edit_value);
        
        button_read = (Button)findViewById(R.id.button_read);
        button_read.setOnClickListener(this);
        button_write = (Button)findViewById(R.id.button_write);
        button_write.setOnClickListener(this);
        button_clear = (Button)findViewById(R.id.button_clear);
        button_clear.setOnClickListener(this);
        
        
        Log.i(LOG_TAG, "Activity Created");
		
		String text = "94";
		valueText.setText(text);
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

	@Override
	public void onClick(View v) {
		if(v.equals(button_read)) {
			try {
				int val2 = iicService.getVal(0x60,0x2480);
				valueText.setText(String.valueOf(val2));
			} catch (RemoteException e) {
				Log.e(LOG_TAG, "Remote Exception while reading value from device.");
			}
		}else if(v.equals(button_write)) {
			try {
				String val = valueText.getText().toString();

				iicService.setVal(0x60,0x2471,0x41);
				iicService.setVal(0x60,0x2480,Integer.valueOf(val));
			} catch (RemoteException e) {
				Log.e(LOG_TAG, "Remote Exception while writing value to device.");
			}
		}else if(v.equals(button_clear)) {
			String text = "";
			valueText.setText(text);
		}
		
	}
}

 为app编写Android.mk

LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

appcompat_dir := ../../../$(SUPPORT_LIBRARY_ROOT)/v7/appcompat/res
gridlayout_dir := ../../../$(SUPPORT_LIBRARY_ROOT)/v7/gridlayout/res
bitmap_dir := ../../../frameworks/opt/bitmap/res
res_dir := res $(appcompat_dir) $(gridlayout_dir) $(bitmap_dir)

LOCAL_MODULE_TAGS := optional

LOCAL_SRC_FILES := $(call all-subdir-java-files)
LOCAL_RESOURCE_DIR := $(addprefix $(LOCAL_PATH)/, $(res_dir))
#LOCAL_RESOURCE_DIR := $(LOCAL_PATH)
LOCAL_PACKAGE_NAME := T613
LOCAL_CERTIFICATE := platform
#LOCAL_PRIVATE_PLATFORM_APIS = true
#LOCAL_SDK_VERSION := current

LOCAL_STATIC_JAVA_LIBRARIES := android-support-v4
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-appcompat
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v7-gridlayout
LOCAL_STATIC_JAVA_LIBRARIES += android-support-v13

#LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/appcompat/res
#LOCAL_RESOURCE_DIR += prebuilts/sdk/current/support/v7/gridlayout/res

LOCAL_AAPT_FLAGS := --auto-add-overlay
LOCAL_AAPT_FLAGS += --extra-packages android.support.v7.appcompat:android.support.v7.gridlayout

include $(BUILD_PACKAGE)
include $(call all-makefiles-under,$(LOCAL_PATH))

在源码根目录下执行:mmm packages/apps/T613   对该模块进行编译

7.在源码根目录下执行:make snod  将添加的模块都加载到img中

8.在源码根目录下执行:./mkimage.sh  更新目录rockdev/Image-rk3288 的文件

9.在源码根目录下执行:cd RKTools/linux/Linux_Pack_Firmware/rockdev  进入该目录执行:

./collectImages.sh && ./mkupdate.sh   产生新的update.img 

10.在windows 下打开 SpiImageTools.exe 加在update.img,会在当前文件夹下产生bin 档(该工具在源码目录下 RKTools\windows)

11.打开Win32diskImager.exe 将bin 档烧写到SD卡中,然后上电启动RK3288

 

步骤7~11详细请参考:https://blog.csdn.net/Chhjnavy/article/details/95043440

 

  • 5
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
Android 7.1.2(也被称为Nougat)是Android操作系统的一个版本,它的源代码是公开可用的。源码包含了构建和运行Android操作系统所需的所有代码文件和资源。 Android操作系统是一个基于Linux内核的开源平台,用于移动设备和嵌入式系统。它提供了一个统一的操作系统环境,使开发者能够轻松地构建和定制自己的Android设备Android 7.1.2源码提供了一套开发工具和框架,使开发者能够创建功能丰富、稳定和安全的应用程序。该版本中引入了一些新的功能和改进,例如通知栏的增强、多任务处理的改进、Doze模式的优化等,以提供更好的用户体验。 通过查看源代码,开发者可以深入了解Android操作系统的内部工作原理,并理解其中的各个组件和模块是如何相互协作的。例如,开发者可以研究Android的用户界面框架、应用程序生命周期管理、通信和存储机制等。 修复和优化Android 7.1.2源码也是可能的,因为它是开源的。开发者可以根据自己的需求和想法对操作系统进行修改,并参与到Android社区中,与其他开发者分享和贡献代码。 总之,Android 7.1.2源码为开发者提供了一个定制和构建Android应用的平台。通过深入了解源码,开发者能够创建出更加出色和创新的应用程序,同时也有机会参与到Android开源社区中,为整个生态系统的发展做出贡献。
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值