日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > linux >内容正文

linux

linux驱动与dts匹配过程,自己编写从应用到DTS与驱动

發布時間:2023/12/10 linux 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 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与驱动的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。