linux驱动与dts匹配过程,自己编写从应用到DTS与驱动
这里的思路依然是从应用到drivers编写,只是贴出来重点部分。
import android.app.InoGpioManager;
((InoGpioManager) context.getSystemService(Context.INOGPIO_SERVICE)).ioctl(cmd,val);
InoGpioManager.java的编写:
public class InoGpioManager
{
private final IInoGpioManager mService;
InoGpioManager(IInoGpioManager service, Context ctx)
{
mService = sevice;
}
......
然后这里定义常用的API即可,
}
IInoGpioManager.aidl
package android.app;
interface IInoGpioManager{
int write_val(in int[] val,int size);
int[] read_val(int size);
int ioctl_val(int cmd,int val);
}
在这里需要把文件添加到Framework/base/Android.mk
LOCAL_SRC_FILES +=
core/java/android/app/IInoGpioManager.aidl \
一定要一次添加正确,防止出问题,后期找文件删除
这里啰嗦一句,
aidl_files := \
这里添加的都是类似这种文件
parcelable AlarmManager.AlarmClockInfo;
这种的aidl文件
SystemServiceRegistry.java里如下注册
registerService(Context.INOGPIO_SERVICE, InoGpioManager.class,
new CachedServiceFetcher() {
@Override
public InoGpioManager createService(ContextImpl ctx) {
IBinder b = ServiceManager.getService(Context.INOGPIO_SERVICE);
IInoGpioManager service = IInoGpioManager.Stub.asInterface(b);
return new InoGpioManager(service, ctx);
}});
此时此刻进入到
InoGpioService.java
这里多说一句,如果按照老罗的写法,此时此刻应该是
public class InoGpioService extends IInoGpioManager.stub
但是呢他的aidl文件实在Android.os下,我们这里的写的是Android.app下,最后应用也不一样
public class InoGpioService extends SystemService
{
这里的写法更简单,一个构造函数用来初始化init
再加几个API,不在啰嗦
}
这里需要在systemserver.java中进行注册
traceBeginAndSlog("StartInoGpioService");
mSystemServiceManager.startService(InoGpioService.class);
Trace.traceEnd(Trace.TRACE_TAG_SYSTEM_SERVER);
使用这种时,可以在onStart里加入
publishBinderService(Context.ALARM_SERVICE, mService);
public void onStart()
{
final IBinder mService = new IInoGpioManager.Stub();
publishBinderService(Context.INOGPIO_SERVICE,mService);
}
这次就栽在这里。
/*try {
Slog.i(TAG,"InoGpioService +1");
ServiceManager.addService(Context.INOGPIO_SERVICE,new InoGpioService());
Slog.i(TAG,"InoGpioService +2 ");
} catch (Throwable e) {
Slog.e(TAG,"InoGpioService new error",e);
}*/
这里的两种方式都是可以的,
两种方式的差异如下:
public class InoGpioService extends SystemService {
这里采用的是匿名内部类,函数接口都是定义在匿名内部类的内部,
private final IBinder mb = new IInoGpioManager.Stub() {
这里只能是函数,不能是单个句子。
//public class InoGpioService extends IInoGpioManager.Stub {
这种方式的API都是直接定义,不需要定义在匿名匿名内部类的。
然而INOGPIO_SERVICE这个的定义在Context.java中
此时此刻要修改SELinux的权限问题了
这里的inogpio是service的context的定义。
./app.te:allow untrusted_app inogpio_service:service_manager find;
./service_contexts:inogpio u:object_r:inogpio_service:s0
./service.te:type inogpio_service, service_manager_type;
./system_app.te:allow system_app inogpio_service:service_manager find;
./system_server.te:allow system_server inogpio_service:service_manager find;
./system_server.te:allow system_server inogpio_service:service_manager add;
而后进入到JNI的C++世界,这里依然简单,
register_android_server_InoGpioService
这个再onload.cpp里添加
在当前目录的Android.mk也要添加
static const JNINativeMethod method_table[] = {
{ "init_native" , "()Z" , (void*)init_native},
{ "writeval_native" , "([II)I" , (void*)writeval_native},
{ "readval_native" , "(I)[I" , (void*)readval_native},
{ "ioctlval_native" , "(II)I" ,(void*)ioctlval_native},
};
static jboolean init_native(JNIEnv *env,jobject clazz)
struct innopro_gpio_module_t *module;
if((hw_get_module(INOGPIO_HARDWARE_MODULE_ID,(const struct hw_module_t **)&module) == 0)){
if(device_open(&(module->common),&gpio_device) == 0){
ALOGI("open the device success");
return 0;
}
这里只是写了一个init的接口,其他的接口类似
还有就是进入到hardware层,但是hardware层可以不写,直接在JNI里实现open read write ioctl
还是写一下的吧,权当练手
#define INOGPIO_HARDWARE_MODULE_ID "inogpio"
struct inogpio_module_t{
struct hw_module_t common;
};
struct inogpio_device_t{
struct hw_device_t common;
int fd;
int (*read_val)(struct inogpio_device_t *dev, int *val,int size);
int (*write_val)(struct inogpio_device_t *dev, int *val,int size);
int (*ioctl_val)(struct inogpio_device_t *dev,int cmd, int val);
};
struct inogpio_module_t HAL_MODULE_INFO_SYM={
.common = {
.tag = HARDWARE_MODULE_TAG,
.version_major = 1,
.version_minor = 0,
.id = INOGPIO_HARDWARE_MODULE_ID,
.name = "innopro gpio Module",
.author = "zwh",
.methods = &inogpio_module_methods,
},
};
static struct hw_module_methods_t inogpio_module_methods = {
.open = open_inogpio,
};
static int open_inogpio(const struct hw_module_t *module, char const *name, struct hw_device_t **device)
{
struct inogpio_device_t *dev = malloc(sizeof(struct inogpio_device_t));
ALOGI("name ++ ++ = %s",name);
if(dev == NULL){
ALOGE("fail to malloc the device space");
return -1;
}
memset(dev,0,sizeof(struct innogpio_device_t));
dev->common.tag = HARDWARE_DEVICE_TAG;
dev->common.version = 0;
dev->common.module = (struct hw_module_t *)module;
dev->common.close = close_inogpio;
dev->read_val = read_val;
dev->write_val = write_val;
dev->ioctl_val = ioctl_val;
dev->fd = open(DEV_NAME,O_RDWR);
if(dev->fd == -1){
ALOGE("open the /dev/innopro_gpio fail");
free(dev);
return -1;
}
*device = &(dev->common);
ALOGI("innopro_device open successfuly");
return 0;
}
类似这种风格,其他的按照ioctl 等操作即可
进入到kernel的世界
static const struct of_device_id gpio_dt_match[] = {
{ .compatible = "amlogic, innopro_gpio"},
{},
};
设备树在dts里的定义
tatic struct platform_driver gpio_driver = {
.driver = {
.name = "innopro_gpio",
.owner = THIS_MODULE,
.of_match_table = gpio_dt_match,
},
.probe = gpio_probe,
#ifdef CONFIG_PM
.suspend = gpio_suspend,
.resume = gpio_resume,
#endif
.shutdown = gpio_shutdown,
};
static __init int innopro_init(void)
ret = platform_driver_register(&gpio_driver);
static int gpio_probe(struct platform_device *pdev)
{
int ret = -1;
pr_info("probe\n");
aml_gpio_dt_parse(pdev);
gpio_dev.cdev_.owner = THIS_MODULE;
cdev_init(&(gpio_dev.cdev_), &gpio_ops);
alloc_chrdev_region(&(gpio_dev.devno), 0, 1,
gpio_dev.dev_name);
ret = cdev_add(&(gpio_dev.cdev_), gpio_dev.devno, 1);
if (ret) {
pr_info("cdev_add fail\n");
return -EINVAL;
}
if (IS_ERR(gpio_dev.class_)) {
pr_info("Create class error\n");
return -1;
}
device_create(gpio_dev.class_, NULL, gpio_dev.devno,
NULL, gpio_dev.dev_name);
return 0;
}
设备树的产生还与那句fuck the ARM Linux 有关
这里的ioctl和read write的操作都是一个寄存器的操作。
不再啰嗦
进入到设备树看看
innopro_gpio{
compatible = "amlogic, innopro_gpio";
dev_name = "innopro_gpio";
status = "okay";
ao6_pins = ;
ao6_name = "GPIOAO_6";
ao6_value = <1 1="">;
ao9_pins = ;
ao9_name = "GPIOAO_9";
ao9_value = <0 1="">;
};
如此而已,这里只是啰嗦大致的写的流程,代码细节不做啰嗦。细节都跑通了,其他也就容易的多了。
这里嘟囔几句曾经遇到而且反复犯的错误,
问题一:uboot的编程,
编译方式:在uboot的目录下,./mk gxl_p212_v1
生成目录:/uboot/fip
那么问题来了,为什么打包成aml*.img时,不能自动更新呢?那就是出在不能自动拷贝了,所以需要自动拷贝下,如下目录out/target/product/p212/upgrade
问题二:修改完或者加入hardware时,并不能自动编译,需要先mmm hardware时才能继续打包
问题三:aidl问题,
aidl开始放错问题,需要把生成的out/target/common/obj/JAVA_LIBRARIES/android_stubs_current_intermediates/src/android/app
类似目录的文件删掉,然后继续打包,否则也会打包进去,我觉得这里非常不智能,没办法做到删除不相干文件。
问题四:函数的public,默认,private,protect问题
private 只能被类内使用,protect子类访问,default在包内使用,public都可以使用。
linux驱动与dts匹配过程,自己编写从应用到DTS与驱动相关推荐
- Linux设备驱动和设备匹配过程
Linux设备驱动和设备匹配过程 1. 设备驱动匹配简述 2. 重点结构体介绍 2.1 `struct device` 2.2 `struct platform_device` 2.3 `struct ...
- MTK 平台的Irq 中断号,dts匹配过程
MTK一直以傻瓜化,工具化出名,导致了许多代码逻辑的缺失:所以很多做 MTK平台的人,对很多东西都不甚了解,一知半解.最近我们调试一个驱动,在添加 irq时,就找不到代码的逻辑关联,现把关键的过程记录 ...
- 高通平台msm8953 Linux DTS(Device Tree Source)设备树详解之二(DTS设备树匹配过程)
本系列导航: 高通平台8953 Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇) 高通平台8953 Linux DTS(Device Tree Source ...
- linux spi主机控制器pl022驱动注册以及匹配设备过程
最近看海思的spi比较多,海思3519的spi ip使用的时ARM提供的pl022,这里对pl022驱动注册和匹配设备树中的设备这个过程捋一下. pl022是ARM提供的片内外设,很多厂商都用了这个i ...
- MTK驱动(53)---平台DTS文件匹配过程
MTK平台DTS文件匹配过程 1. lk中platform paramter lk阶段会从boot image 解析出dtb数据,然后通过atag方式将dtb数据传递给了内核. 在mtk平台lk ...
- <Linux开发>--驱动开发-- 字符设备驱动(3) 过程详细记录
<Linux开发>–驱动开发-- 字符设备驱动(3) 过程详细记录 驱动开发是建立再系统之上的,前面作者也记录了系统移植的过程记录,如果有兴趣,可进入博主的主页查看相关文章,这里就不添加链 ...
- Linux 字符设备驱动开发基础(一)—— 编写简单 LED 设备驱动
现在,我们来编写自己第一个字符设备驱动 -- 点亮LED.(不完善,后面再完善) 硬件平台:Exynos4412(FS4412) 编写驱动分下面几步: a -- 查看原理图.数据手册,了解设备的操作方 ...
- linux驱动编写(platform总线和网卡驱动)
[ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 对于linux驱动来说,一般的架构还是按照bus-host-device的形式来进行的.比如就拿 ...
- dts 编译过程_linux设备树dts移植详解
[转] 摘 要:设备树的引入减少了内核为支持新硬件而需要的改变,提高代码重用,加速了Linux 支持包的开发,使得单个内核镜像能支持多个系统.作为U-Boot 和Linux 内核之间的动态 接口,本文 ...
最新文章
- 要不是这本书及时出现,本周真撑不下去…
- Jmeter创建一个点对点的 JMS 测试计划
- swagger配置分组
- 戴帽子对眼睛是否有好处
- 发布你的程序包到Nuget
- 寻宝处理器的引人入胜之旅——《大话处理器》新书出炉
- PAT乙级(1033 旧键盘打字)
- Max 缩放代码 获取2点直接的距离
- xcode ios 模拟器安装运行
- 软件构建中的设计(二)
- 【调剂】上海海洋大学大数据和遥感方向接收硕士调剂
- java 坑爹的黑店,大土地神系统
- java基础 io流 字节流 字符流 节点流 包装流 转换流 缓冲流 对象流 打印流 Properties类
- 达梦数据库 年月周查询
- WPF中MaterialDesignThemes前端框架的使用(超详细图解步骤)
- 关于innerHTML的用法,以及数据覆盖问题
- 计算机学习计划表作文,计算机学习计划作文三篇范本
- 51Nod1011 最大公约数GCD(C语言)
- 美工效果图大小 html,六、DIV CSS实战之布局美工图分析与切图
- 值得一看的35个Redis常用问题总结
热门文章
- java 数字信号_数字信号处理理论及C++和Java实现 数字信号处理理论算法与实现...
- python随机数模块_python 随机数模块 -- random
- 慕课乐学python单元测试答案_中国大学慕课第三章单元测试答案_乐学软件工程免费答案...
- MyBatis笔记——配置文件完成增删改查
- 通过VisualSVN的POST-COMMIT钩子自动部署代码
- 【转】dcmtk程序包综述(1)!!!!!!
- 【转】逆变与协变详解
- 【MOSS】快速调试Sharepoint站点
- 通用usb集线器驱动_多口充电、高速传输——ORICO晶锐系列7口集线器测评
- Hexo博客:您备案的网站未指向阿里云国内节点(不含香港)服务器,备案号可能被取消接入