这里的思路依然是从应用到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与驱动相关推荐

  1. Linux设备驱动和设备匹配过程

    Linux设备驱动和设备匹配过程 1. 设备驱动匹配简述 2. 重点结构体介绍 2.1 `struct device` 2.2 `struct platform_device` 2.3 `struct ...

  2. MTK 平台的Irq 中断号,dts匹配过程

    MTK一直以傻瓜化,工具化出名,导致了许多代码逻辑的缺失:所以很多做 MTK平台的人,对很多东西都不甚了解,一知半解.最近我们调试一个驱动,在添加 irq时,就找不到代码的逻辑关联,现把关键的过程记录 ...

  3. 高通平台msm8953 Linux DTS(Device Tree Source)设备树详解之二(DTS设备树匹配过程)

    本系列导航: 高通平台8953  Linux DTS(Device Tree Source)设备树详解之一(背景基础知识篇) 高通平台8953 Linux DTS(Device Tree Source ...

  4. linux spi主机控制器pl022驱动注册以及匹配设备过程

    最近看海思的spi比较多,海思3519的spi ip使用的时ARM提供的pl022,这里对pl022驱动注册和匹配设备树中的设备这个过程捋一下. pl022是ARM提供的片内外设,很多厂商都用了这个i ...

  5. MTK驱动(53)---平台DTS文件匹配过程

    MTK平台DTS文件匹配过程 1. lk中platform paramter lk阶段会从boot image 解析出dtb数据,然后通过atag方式将dtb数据传递给了内核.    在mtk平台lk ...

  6. <Linux开发>--驱动开发-- 字符设备驱动(3) 过程详细记录

    <Linux开发>–驱动开发-- 字符设备驱动(3) 过程详细记录 驱动开发是建立再系统之上的,前面作者也记录了系统移植的过程记录,如果有兴趣,可进入博主的主页查看相关文章,这里就不添加链 ...

  7. Linux 字符设备驱动开发基础(一)—— 编写简单 LED 设备驱动

    现在,我们来编写自己第一个字符设备驱动 -- 点亮LED.(不完善,后面再完善) 硬件平台:Exynos4412(FS4412) 编写驱动分下面几步: a -- 查看原理图.数据手册,了解设备的操作方 ...

  8. linux驱动编写(platform总线和网卡驱动)

    [ 声明:版权所有,欢迎转载,请勿用于商业用途. 联系信箱:feixiaoxing @163.com] 对于linux驱动来说,一般的架构还是按照bus-host-device的形式来进行的.比如就拿 ...

  9. dts 编译过程_linux设备树dts移植详解

    [转] 摘 要:设备树的引入减少了内核为支持新硬件而需要的改变,提高代码重用,加速了Linux 支持包的开发,使得单个内核镜像能支持多个系统.作为U-Boot 和Linux 内核之间的动态 接口,本文 ...

最新文章

  1. 要不是这本书及时出现,本周真撑不下去…
  2. Jmeter创建一个点对点的 JMS 测试计划
  3. swagger配置分组
  4. 戴帽子对眼睛是否有好处
  5. 发布你的程序包到Nuget
  6. 寻宝处理器的引人入胜之旅——《大话处理器》新书出炉
  7. PAT乙级(1033 旧键盘打字)
  8. Max 缩放代码 获取2点直接的距离
  9. xcode ios 模拟器安装运行
  10. 软件构建中的设计(二)
  11. 【调剂】上海海洋大学大数据和遥感方向接收硕士调剂
  12. java 坑爹的黑店,大土地神系统
  13. java基础 io流 字节流 字符流 节点流 包装流 转换流 缓冲流 对象流 打印流 Properties类
  14. 达梦数据库 年月周查询
  15. WPF中MaterialDesignThemes前端框架的使用(超详细图解步骤)
  16. 关于innerHTML的用法,以及数据覆盖问题
  17. 计算机学习计划表作文,计算机学习计划作文三篇范本
  18. 51Nod1011 最大公约数GCD(C语言)
  19. 美工效果图大小 html,六、DIV CSS实战之布局美工图分析与切图
  20. 值得一看的35个Redis常用问题总结

热门文章

  1. java 数字信号_数字信号处理理论及C++和Java实现 数字信号处理理论算法与实现...
  2. python随机数模块_python 随机数模块 -- random
  3. 慕课乐学python单元测试答案_中国大学慕课第三章单元测试答案_乐学软件工程免费答案...
  4. MyBatis笔记——配置文件完成增删改查
  5. 通过VisualSVN的POST-COMMIT钩子自动部署代码
  6. 【转】dcmtk程序包综述(1)!!!!!!
  7. 【转】逆变与协变详解
  8. 【MOSS】快速调试Sharepoint站点
  9. 通用usb集线器驱动_多口充电、高速传输——ORICO晶锐系列7口集线器测评
  10. Hexo博客:您备案的网站未指向阿里云国内节点(不含香港)服务器,备案号可能被取消接入