MTK Android添加驱动模块.docx
《MTK Android添加驱动模块.docx》由会员分享,可在线阅读,更多相关《MTK Android添加驱动模块.docx(31页珍藏版)》请在冰豆网上搜索。
![MTK Android添加驱动模块.docx](https://file1.bdocx.com/fileroot1/2022-11/27/ada7515b-6693-4013-8e59-51f3332a4eff/ada7515b-6693-4013-8e59-51f3332a4eff1.gif)
MTKAndroid添加驱动模块
∙1 [编写linux驱动程序]
1.1 一、编写驱动核心程序
1.2 二、配置Kconfig
1.3 三、配置Makefile
1.4 四、配置系统的autoconfig
1.5 五、编译
∙2 [编写hal模块]
2.1 一、新建xxx.h文件
2.2 二、新建xxx.c文件
2.2.1 1、包含相关头文件和定义相关结构
2.2.2 2、定义hello_device_open函数
2.2.3 3、定义自定义的api函数
2.3 三、在hello目录下新建Android.mk文件
2.4 四、编译、重新打包Android系统镜像system.img
3 [编写jni]
3.1 一、新建com_android_server_HelloService.cpp文件
3.1.1 1、包括头文件
3.1.2 2、编写jni接口
3.1.3 3、定义jni加载函数,注册jni方法表
3.2 二、修改onload.cpp,使系统启动时自动加载JNI方法调用表
3.3 三、修改Android.mk文件,添加编译路径
3.4 四、编译和重新生成system.img
∙4 [编写Framework接口]
4.1 一、定义通信接口
4.1.1 1、新增接口文件
4.1.2 2、添加编译路径
4.1.3 3、编译接口文件
4.2 二、建立java文件,编写Framework接口
4.3 三、在ServerThread:
:
run函数中增加加载代码
4.4 四、编译、重新打包system.img
5 [App访问]
[编写linux驱动程序]
编写驱动核心程序
这里说的驱动核心程序是指运行在内核空间的,完全按linux驱动格式编写的,基本上与android没什么关系,一般包括xxx.h和xxx.c文件。
进入到kernel/drivers目录,新建snsled目录,然后建立对应的snsled.h和snsled.c文件:
//snsled.h
#ifndef_SNSLED_H_
#define_SNSLED_H_
#defineSNSLED_NUM
(1)
#defineSNSLED_CLASS_NAME"snsled"
#defineSNSLED_DEVICE_NAME"snsled"
#defineSNSLED_NODE_NAME"snsled"
#defineSNSLED_PROC_NAME"snsled"
#defineSNSLED_IOC_MAGIC'k'
#defineSNSLED_IO_ON2323//_IO(SNSLED_IOC_MAGIC,0)
#defineSNSLED_IO_OFF2324//_IO(SNSLED_IOC_MAGIC,1)
#defineSNSLED_IOW_PWM2325//_IOW(SNSLED_IOC_MAGIC,2,int)
#defineSNSLED_IOR_PWM232//_IOR(SNSLED_IOC_MAGIC,3,int)
structsnsled_cntx{
intr1;
structsemaphoresem;
structcdevcdev;
};
#endif
//snsled.c
#include
#include
#include
#include/*printk()*/
#include/*kmalloc()*/
#include/*everything...*/
#include/*errorcodes*/
#include/*size_t*/
#include
#include/*O_ACCMODE*/
#include
#include
#include/*cli(),*_flags*/
#include/*copy_*_user*/
//#include/*semaphore*/
#include
#include/*class_create*/
#include"snsled.h"/*localdefinitions*/
/*
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include*/
#ifdefined(CONFIG_ARCH_MT6573)
#include
#include
#include
#elifdefined(CONFIG_ARCH_MT6516)
#include
#include
#endif
/*====macros====*/
#defineBUF_SIZE(64)
#defineSNS_LED_CONTROL_LINEGPIO99//GPIO39
#defineSNS_LED_CONTROL_LINE_GPIO_MODEGPIO_MODE_00
#defineSNS_LED_CONTROL_LINE_PWM_MODEGPIO_MODE_01
/*====declares====*/
ssize_tsnsled_read(structfile*filp,char__user*buf,size_tcount,loff_t*f_pos);
ssize_tsnsled_write(structfile*filp,constchar__user*buf,size_tcount,loff_t*f_pos);
longsnsled_unlocked_ioctl(structfile*filp,unsignedintcmd,unsignedlongarg);
intsnsled_open(structinode*inode,structfile*filp);
intsnsled_release(structinode*inode,structfile*filp);
intsnsled_turn_on(void);
intsnsled_turn_off(void);
intsnsled_set_pwm(intarg);
/*====global====*/
staticintg_snsled_major=0;
staticintg_snsled_minor=0;
structsnsled_cntx*g_snsled_ptr=NULL;
structclass*g_snsled_class=0;
staticstructfile_operationsg_snsled_fops={
.owner=THIS_MODULE,
.read=snsled_read,
.write=snsled_write,
.unlocked_ioctl=snsled_unlocked_ioctl,
.open=snsled_open,
.release=snsled_release,
};
/*====implements====*/
ssize_tsnsled_read(structfile*filp,char__user*buf,size_tcount,loff_t*f_pos){
#if1
printk(KERN_ALERT"Snsledread.\n");
#else
chartmp_buf[512]={0};
intlen=sprintf(tmp_buf,"snsledread.\n");
if(copy_to_user(buf,tmp_buf,count)){
//donothing
}
#endif
return0;
}
ssize_tsnsled_write(structfile*filp,constchar__user*buf,size_tcount,loff_t*f_pos){
printk(KERN_ALERT"Snsledwrite.\n");
returncount;
}
longsnsled_unlocked_ioctl(structfile*filp,unsignedintcmd,unsignedlongarg){
interr=0;
longretval=0;
printk(KERN_ALERT"Snsledioctl:
cmd=%d,arg=%d.\n",cmd,arg);
/*
//extractthetypeandnumberbitfields,anddon'tdecode
//wrongcmds:
returnENOTTY(inappropriateioctl)beforeaccess_ok()
if(_IOC_TYPE(cmd)!
=SNSLED_IOC_MAGIC)return-ENOTTY;
//if(_IOC_NR(cmd)>SNSLED_IOC_MAXNR)return-ENOTTY;
//toverify*argisinuserspace
if(_IOC_DIR(cmd)&_IOC_READ)
err=!
access_ok(VERIFY_WRITE,(void__user*)arg,_IOC_SIZE(cmd));
elseif(_IOC_DIR(cmd)&_IOC_WRITE)
err=!
access_ok(VERIFY_READ,(void__user*)arg,_IOC_SIZE(cmd));
if(err)return-EFAULT;
*/
switch(cmd)
{
caseSNSLED_IO_ON:
printk(KERN_ALERT"Snsledioctl:
on.\n");
//if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ONE)){printk("Snsledsetgpiofailed!
!
\n");}
snsled_turn_on();
break;
caseSNSLED_IO_OFF:
printk(KERN_ALERT"Snsledioctl:
off.\n");
//if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)){printk("Snsledsetgpiofailed!
!
\n");}
snsled_turn_off();
break;
caseSNSLED_IOW_PWM:
printk(KERN_ALERT"Snsledioctl:
setpwm,arg=%d.\n",arg);
//retval=__get_user(g_snsled_ptr->r1,(int__user*)arg);
snsled_set_pwm((int__user*)arg);
break;
caseSNSLED_IOR_PWM:
#if0
retval=__put_user(g_snsled_ptr->r1,(int__user*)arg);
printk(KERN_ALERT"Snsledioctl:
readr1:
%i.\n",g_snsled_ptr->r1);
#endif
printk(KERN_ALERT"Snsledioctl:
readpwm--notconfiguredyet.\n");
break;
default:
printk(KERN_ALERT"Snsledioctl:
yougotthewrongcommand.\n");
break;
}
returnretval;
}
intsnsled_open(structinode*inode,structfile*filp){
printk(KERN_ALERT"Snsled:
snsled_open.\n");
#if0
if(mt_set_gpio_mode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_GPIO_MODE)){printk("Snsledsetgpiomodefailed!
!
\n");}
if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)){printk("Snsledsetgpiodirfailed!
!
\n");}
if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ONE)){printk("Snsledsetgpiofailed!
!
\n");}
#endif
return0;
}
intsnsled_release(structinode*inode,structfile*filp){
printk(KERN_ALERT"Snsled:
snsled_release.\n");
#if0
if(mt_set_gpio_mode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_GPIO_MODE)){printk("Snsledsetgpiomodefailed!
!
\n");}
if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)){printk("Snsledsetgpiodirfailed!
!
\n");}
if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)){printk("Snsledsetgpiofailed!
!
\n");}
#endif
return0;
}
intsnsled_turn_on(void){
printk(KERN_ALERT"Snsled:
snsled_turn_on.\n");
if(mt_set_gpio_mode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_PWM_MODE)){printk("Snsledsetgpiomodefailed!
!
\n");}
if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)){printk("Snsledsetgpiodirfailed!
!
\n");}
if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)){printk("Snsledsetgpiofailed!
!
\n");}
return0;
}
intsnsled_turn_off(void){
printk(KERN_ALERT"Snsled:
snsled_turn_off.\n");
if(mt_set_gpio_mode(SNS_LED_CONTROL_LINE,SNS_LED_CONTROL_LINE_GPIO_MODE)){printk("Snsledsetgpiomodefailed!
!
\n");}
if(mt_set_gpio_dir(SNS_LED_CONTROL_LINE,GPIO_DIR_OUT)){printk("Snsledsetgpiodirfailed!
!
\n");}
if(mt_set_gpio_out(SNS_LED_CONTROL_LINE,GPIO_OUT_ZERO)){printk("Snsledsetgpiofailed!
!
\n");}
return0;
}
//foroldmode
/**
struct_PWM_OLDMODE_REGS{
U16IDLE_VALUE;//0
U16GUARD_VALUE;//0
U16GDURATION;//~
U16WAVE_NUM;//0
U16DATA_WIDTH;//highlevel,13bits,0~8191
U16THRESH;//t
}PWM_MODE_OLD_REGS;
**/
intsnsled_set_pwm(intarg){
structpwm_spec_configpwm_setting;
pwm_setting.pwm_no=PWM1;
printk(KERN_ALERT"Snsled:
snsled_openbegin.\n");
pwm_setting.mode=PWM_MODE_OLD;
pwm_setting.clk_div=CLK_DIV16;//CLK_DIV128;
pwm_setting.clk_src=PWM_CLK_OLD_MODE_32K;
pwm_setting.PWM_MODE_OLD_REGS.IDLE_VALUE=0;
pwm_setting.PWM_MODE_OLD_REGS.GUARD_VALUE=0;
pwm_setting.PWM_MODE_OLD_REGS.GDURATION=8100;
pwm_setting.PWM_MODE_OLD_REGS.WAVE_NUM=0;
pwm_setting.PWM_MODE_OLD_REGS.DATA_WIDTH=8100;
pwm_setting.PWM_MODE_OLD_REGS.THRESH=8100;
pwm_set_spec_config(&pwm_setting);
printk(KERN_ALERT"Snsled:
snsled_opendone.\n");
return0;
}
//allocdevicemajor
staticintvircdex_alloc_major(void){
dev_tdevt=0;
intresult=0;
result=alloc_chrdev_region(&devt,g_snsled_minor,SNSLED_NUM,SNSLED_NODE_NAME);
g_snsled_major=MAJOR(devt);
returnresult;
}
staticintsnsled_release_major(void){
dev_tdevt=MKDEV(g_snsled_major,g_snsled_minor);
unregister_chrdev_region(devt,1);
return0;
}
staticintsnsled_setup_dev(structsnsled_cntx*dev){
interr,devno=MKDEV(g_snsled_major,g_snsled_minor);
cdev_init(&(dev->cdev),&g_snsled_fops);
dev->cdev.owner=THIS_MODULE;
err=cdev_add(&dev->cdev,devno,1);
if(err){
returnerr;
}
//init_MUTEX(&(dev->sem));
sema_init(&(dev->sem),1);
return0;
}
staticintsnsled_unsetup_dev(structsnsled_cntx*dev){
cdev_del(&(dev->cdev));
return0;
}
staticintsnsled_create_devfiles(dev_tdevt){//,conststructdevice_attribute*attr){
interr=-1;
structdevice*dev=NULL;
g_snsled_class=class_create(THIS_MODULE,SNSLED_CLASS_NAME);
if(IS_ERR(g_snsled_class)){
err=PTR_ERR(g_snsled_class);
printk(KERN_ALERT"Failedtocreateclass.\n");
gotoCLASS_CREATE_ERR;
}
dev=device_create(g_snsled_class,NULL,devt,NULL,SNSLED_DEVICE_NAME);
//dev=device_create(hello_class,NULL,dev,"%s",HELLO_DEVICE_FILE_NAME);
//device_create(my_class,NULL,MKDEV(hello_m