版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)
文檔簡(jiǎn)介
1
[編寫(xiě)linux驅(qū)動(dòng)程序]1.1
一、編寫(xiě)驅(qū)動(dòng)核心程序1.2
二、配置Kconfig1.3
三、配置Makefile1.4
四、配置系統(tǒng)的autoconfig1.5
五、編譯2
[編寫(xiě)hal模塊]2.1
一、新建xxx.h文件2.2
二、新建xxx.c文件2.2.1
1、包含相關(guān)頭文件和定義相關(guān)結(jié)構(gòu)2.2.2
2、定義hello_device_open函數(shù)2.2.3
3、定義自定義的api函數(shù)2.3
三、在hello目錄下新建Android.mk文件2.4
四、編譯、重新打包Android系統(tǒng)鏡像system.img3
[編寫(xiě)jni]3.1
一、新建com_android_server_HelloService.cpp文件3.1.1
1、包括頭文件3.1.2
2、編寫(xiě)jni接口3.1.3
3、定義jni加載函數(shù),注冊(cè)jni方法表3.2
二、修改onload.cpp,使系統(tǒng)啟動(dòng)時(shí)自動(dòng)加載JNI方法調(diào)用表3.3
三、修改Android.mk文件,添加編譯路徑3.4
四、編譯和重新生成system.img4
[編寫(xiě)Framework接口]4.1
一、定義通信接口4.1.1
1、新增接口文件4.1.2
2、添加編譯路徑4.1.3
3、編譯接口文件4.2
二、建立java文件,編寫(xiě)Framework接口4.3
三、在ServerThread::run函數(shù)中增加加載代碼4.4
四、編譯、重新打包system.img5
[App訪問(wèn)][編寫(xiě)linux驅(qū)動(dòng)程序]編寫(xiě)驅(qū)動(dòng)核心程序
這里說(shuō)的驅(qū)動(dòng)核心程序是指運(yùn)行在內(nèi)核空間的,完全按linux驅(qū)動(dòng)格式編寫(xiě)的,基本上與android沒(méi)什么關(guān)系,一般包括xxx.h和xxx.c文件。
進(jìn)入到kernel/drivers目錄,新建snsled目錄,然后建立對(duì)應(yīng)的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_PWM 2325 //_IOW(SNSLED_IOC_MAGIC,2,int)#defineSNSLED_IOR_PWM 232 //_IOR(SNSLED_IOC_MAGIC,3,int)structsnsled_cntx{intr1;structsemaphoresem; structcdevcdev;};#endif//snsled.c#include<linux/module.h>#include<linux/moduleparam.h>#include<linux/init.h>#include<linux/kernel.h> /*printk()*/#include<linux/slab.h> /*kmalloc()*/#include<linux/fs.h> /*everything...*/#include<linux/errno.h> /*errorcodes*/#include<linux/types.h> /*size_t*/#include<linux/proc_fs.h>#include<linux/fcntl.h> /*O_ACCMODE*/#include<linux/seq_file.h>#include<linux/cdev.h>#include<asm/system.h> /*cli(),*_flags*/#include<asm/uaccess.h> /*copy_*_user*///#include<asm/semaphore.h>/*semaphore*/#include<linux/semaphore.h>#include<linux/device.h>/*class_create*/#include"snsled.h" /*localdefinitions*//*#include<linux/module.h>#include<linux/platform_device.h>#include<linux/delay.h>#include<linux/string.h>#include<linux/ctype.h>#include<linux/leds.h>#include<linux/leds-mt65xx.h>#include<linux/workqueue.h>#include<linux/wakelock.h>#include<linux/slab.h>#include<cust_leds.h>*/#ifdefined(CONFIG_ARCH_MT6573)#include<mach/mt6573_pwm.h>#include<mach/mt6573_gpio.h>#include<mach/pmu6573_sw.h>#elifdefined(CONFIG_ARCH_MT6516)#include<mach/mt6516_pwm.h>#include<mach/mt6516_gpio.h>#endif/*====macros====*/#defineBUF_SIZE(64)#defineSNS_LED_CONTROL_LINE GPIO99 //GPIO39#defineSNS_LED_CONTROL_LINE_GPIO_MODE GPIO_MODE_00 #defineSNS_LED_CONTROL_LINE_PWM_MODE GPIO_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){#if1printk(KERN_ALERT"Snsledread.\n");#elsechartmp_buf[512]={0};intlen=sprintf(tmp_buf,"snsledread.\n");if(copy_to_user(buf,tmp_buf,count)){//donothing }#endifreturn0;}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: #if0retval=__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;}//allocdevicemajorstaticintvircdex_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_major,0),"hello""%d",0);//dev=device_create(g_snsled_class,NULL,MKDEV(MYDRIVER_Major,0),NULL,DEVICE_NAME);if(IS_ERR(dev)){err=PTR_ERR(dev);printk(KERN_ALERT"Failedtocreatedevice.\n");gotoDEVICE_CREATE_ERR;}/*err=device_create_file(dev,attr);if(err<0){printk(KERN_ALERT"Failedtocreateattributefile.");gotoDEVICE_CREATE_FILE_ERR;}*/printk(KERN_ALERT"seemsok.\n");//zmk@@debugreturn0;DEVICE_CREATE_FILE_ERR:device_destroy(g_snsled_class,devt);DEVICE_CREATE_ERR:class_destroy(g_snsled_class);CLASS_CREATE_ERR:returnerr;}staticintsnsled_delete_devfiles(dev_tdevt){device_destroy(g_snsled_class,devt);class_destroy(g_snsled_class);//device_remove_file(dev,attr);return0;}staticintsnsled_read_proc(char*buf,char**start,off_toffset,intcount,int*eof,void*data){intlen=sprintf(buf,"snsledreadproc.\n");returnlen;}staticintsnsled_create_proc_file(void){structproc_dir_entry*entry=NULL;entry=create_proc_read_entry(SNSLED_PROC_NAME,0,NULL,snsled_read_proc,NULL);if(entry){return0;}else{return-1;}}staticintsnsled_delete_proc_file(void){remove_proc_entry(SNSLED_PROC_NAME,NULL);return0;}MODULE_LICENSE("GPL");staticintsnsled_init(void){interr=-1;dev_tdevt=0;//[1]allocnodenumbererr=vircdex_alloc_major();if(0>err){printk(KERN_ALERT"allocmajorfailed.\n");gotoALLOC_MAJOR_ERR;}devt=MKDEV(g_snsled_major,g_snsled_minor);//[2]deviceobjectinitg_snsled_ptr=kmalloc(sizeof(structsnsled_cntx),GFP_KERNEL);if(!g_snsled_ptr){err=-ENOMEM;printk(KERN_ALERT"kmallocfailed.\n");gotoKMALLOC_ERR;}memset(g_snsled_ptr,0,sizeof(structsnsled_cntx));//[3]setupdeviceerr=snsled_setup_dev(g_snsled_ptr);if(0>err){printk(KERN_ALERT"devicesetupfailed.\n");gotoDEVICE_SETUP_ERR;}//[4]createfilesindirectory"/dev/"and"/sys/"http:///err=snsled_create_devfiles(devt,attr);err=snsled_create_devfiles(devt);if(0>err){printk(KERN_ALERT"devfilescreatefailed.\n");gotoDEVFILES_CREATE_ERR;}//[5]createprocfileerr=snsled_create_proc_file();if(0>err){printk(KERN_ALERT"procfilecreatefailed.\n");gotoPROC_FILE_CREATE_ERR;}return0;PROC_FILE_CREATE_ERR:snsled_delete_devfiles(devt);DEVFILES_CREATE_ERR:snsled_unsetup_dev(g_snsled_ptr);DEVICE_SETUP_ERR:kfree(g_snsled_ptr);ALLOC_MAJOR_ERR:snsled_release_major();KMALLOC_ERR:returnerr;}staticvoidsnsled_exit(void){dev_tdevt=MKDEV(g_snsled_major,g_snsled_minor);snsled_delete_proc_file();snsled_delete_devfiles(devt);snsled_unsetup_dev(g_snsled_ptr);kfree(g_snsled_ptr);snsled_release_major();}module_init(snsled_init);module_exit(snsled_exit);二、配置Kconfig在snsled目錄中,新建Kconfig文件:configSNSLEDtristate"snsledDriver"defaultn#y?helpThisisthesnsleddriver.其中,tristate表示編譯選項(xiàng)HELLO支持在編譯內(nèi)核時(shí),hello模塊支持以模塊、內(nèi)建和不編譯三種編譯方法。
三、配置Makefile
1、在snsled目錄中,新建snsled文件夾對(duì)應(yīng)的Makefile:#obj-$(CONFIG_SNSLED)+=snsled.oobj-y+=snsled.o上面根據(jù)CONFIG_SNSLED的值確定是否編譯,y為編譯。2、修改snsled的父目錄drivers/下的Makefile,加入:obj-$(CONFIG_HELLO)+=snsled/這樣便能在編譯時(shí)編譯到snsled這個(gè)文件夾。
四、配置系統(tǒng)的autoconfig
打開(kāi)mediatek/config/bbk73_gb/autoconfig/kconfig/project,加入:CONFIG_SNSLED=y在這里定義變量CONFIG_SNSLED.ps:目前這里配置好像還不能snsled自動(dòng)編譯進(jìn)去,目前的操作是直接在用到CONFIG_SNSLED的地方用y替代。五、編譯./makeMtkbbk73_gbremakekernelbootimage[編寫(xiě)hal模塊]1新建xxx.h文件進(jìn)入"hardware/libhardware/include/hardware"目錄,新建vircdev.h文件:#ifndefANDROID_HELLO_INTERFACE_H#defineANDROID_HELLO_INTERFACE_H#include<hardware/hardware.h>__BEGIN_DECLS/*定義模塊ID*/#defineHELLO_HARDWARE_MODULE_ID"hello"/*硬件模塊結(jié)構(gòu)體*/structhello_module_t{ structhw_module_tcommon;};/*硬件接口結(jié)構(gòu)體*/structhello_device_t{ structhw_device_tcommon; intfd; int(*set_val)(structhello_device_t*dev,intval); int(*get_val)(structhello_device_t*dev,int*val);};__END_DECLS#endif這里按照Android硬件抽象層規(guī)范的要求,分別定義模塊ID、模塊結(jié)構(gòu)體hello_module_t以及硬件接口結(jié)構(gòu)體hello_device_t。在硬件接口結(jié)構(gòu)體中,fd表示設(shè)備文件描述符,對(duì)應(yīng)linux下我們經(jīng)常接觸到的設(shè)備文件"/dev/xxx",set_val和get_val為該HAL對(duì)上提供的函數(shù)接口。2新建xxx.c文件進(jìn)入到hardware/libhardware/modules目錄,新建hello目錄,并添加hello.c文件。hello.c的內(nèi)容較多,我們分段來(lái)看。1包含相關(guān)頭文件和定義相關(guān)結(jié)構(gòu)#defineLOG_TAG"HelloStub"#include<hardware/hardware.h>#include<hardware/hello.h>#include<fcntl.h>#include<errno.h>#include<cutils/log.h>#include<cutils/atomic.h>#defineDEVICE_NAME"/dev/hello"#defineMODULE_NAME"Hello"#defineMODULE_AUTHOR"shyluo@"/*設(shè)備打開(kāi)和關(guān)閉接口*/staticinthello_device_open(conststructhw_module_t*module,constchar*name,structhw_device_t**device);staticinthello_device_close(structhw_device_t*device);/*設(shè)備訪問(wèn)接口*/staticinthello_set_val(structhello_device_t*dev,intval);staticinthello_get_val(structhello_device_t*dev,int*val);/*模塊方法表*/staticstructhw_module_methods_thello_module_methods={ open:hello_device_open};/*模塊實(shí)例變量*/structhello_module_tHAL_MODULE_INFO_SYM={ common:{ tag:HARDWARE_MODULE_TAG, version_major:1, version_minor:0, id:HELLO_HARDWARE_MODULE_ID, name:MODULE_NAME, author:MODULE_AUTHOR, methods:&hello_module_methods, }這里,實(shí)例變量名必須為HAL_MODULE_INFO_SYM,tag也必須為HARDWARE_MODULE_TAG,這是Android硬件抽象層規(guī)范規(guī)定的。2定義hello_device_open函數(shù)staticinthello_device_open(conststructhw_module_t*module,constchar*name,structhw_device_t**device){ structhello_device_t*dev;dev=(structhello_device_t*)malloc(sizeof(structhello_device_t)); if(!dev){ LOGE("HelloStub:failedtoallocspace"); return-EFAULT; } memset(dev,0,sizeof(structhello_device_t)); dev->common.tag=HARDWARE_DEVICE_TAG; dev->common.version=0; dev->common.module=(hw_module_t*)module; dev->common.close=hello_device_close; dev->set_val=hello_set_val;dev->get_val=hello_get_val; if((dev->fd=open(DEVICE_NAME,O_RDWR))==-1){ LOGE("HelloStub:failedtoopen/dev/hello--%s.",strerror(errno));free(dev); return-EFAULT; } *device=&(dev->common); LOGI("HelloStub:open/dev/hellosuccessfully."); return0;}DEVICE_NAME定義為"/dev/hello"。由于設(shè)備文件是在內(nèi)核驅(qū)動(dòng)里面通過(guò)device_create創(chuàng)建的,而device_create創(chuàng)建的設(shè)備文件默認(rèn)只有root用戶可讀寫(xiě),而hello_device_open一般是由上層APP來(lái)調(diào)用的,這些APP一般不具有root權(quán)限,這時(shí)候就導(dǎo)致打開(kāi)設(shè)備文件失敗:HelloStub:failedtoopen/dev/hello--Permissiondenied.解決辦法是類似于Linux的udev規(guī)則,打開(kāi)Android源代碼工程目錄下,進(jìn)入到system/core/rootdir目錄,里面有一個(gè)名為ueventd.rc文件,往里面添加一行:/dev/hello0666rootroot3定義自定義的api函數(shù)這里定義hello_device_close、hello_set_val和hello_get_val這三個(gè)函數(shù):staticinthello_device_close(structhw_device_t*device){ structhello_device_t*hello_device=(structhello_device_t*)device; if(hello_device){ close(hello_device->fd); free(hello_device); } return0;}staticinthello_set_val(structhello_device_t*dev,intval){ LOGI("HelloStub:setvalue%dtodevice.",val); write(dev->fd,&val,sizeof(val)); return0;}staticinthello_get_val(structhello_device_t*dev,int*val){ if(!val){ LOGE("HelloStub:errorvalpointer"); return-EFAULT; } read(dev->fd,val,sizeof(*val)); LOGI("HelloStub:getvalue%dfromdevice",*val); return0;}三、在hello目錄下新建Android.mk文件LOCAL_PATH:=$(callmy-dir)include$(CLEAR_VARS)LOCAL_MODULE_TAGS:=optionalLOCAL_PRELINK_MODULE:=falseLOCAL_MODULE_PATH:=$(TARGET_OUT_SHARED_LIBRARIES)/hwLOCAL_SHARED_LIBRARIES:=liblogLOCAL_SRC_FILES:=hello.cLOCAL_MODULE:=hello.defaultinclude$(BUILD_SHARED_LIBRARY)注意,LOCAL_MODULE的定義規(guī)則,hello后面跟有default,hello.default能夠保證我們的模塊總能被硬象抽象層加載到。四、編譯、重新打包Android系統(tǒng)鏡像system.img$:~/Android$mmmhardware/libhardware/modules/hello編譯成功后,就可以在out/target/product/generic/system/lib/hw目錄下看到hello.default.so文件了。$:USER-NAME@MACHINE-NAME:~/Android$makesnod重新打包后,system.img就包含我們定義的硬件抽象層模塊hello.default了[編寫(xiě)jni]雖然上一節(jié)我們?cè)贏ndroid系統(tǒng)為我們自己的硬件增加了一個(gè)硬件抽象層模塊,但是現(xiàn)在Java應(yīng)用程序還不能訪問(wèn)到我們的硬件。我們還必須編寫(xiě)JNI方法和在Android的ApplicationFrameworks層增加API接口,才能讓上層Application訪問(wèn)我們的硬件。在這一節(jié)中,我們將首先完成jni接口的編寫(xiě)。一、新建com_android_server_HelloService.cpp文件進(jìn)入frameworks/base/services/jni目錄,新建com_android_server_HelloService.cpp文件:#defineLOG_TAG"HelloService"#include"jni.h"#include"JNIHelp.h"#include"android_runtime/AndroidRuntime.h"#include<utils/misc.h>#include<utils/Log.h>#include<hardware/hardware.h>#include<hardware/hello.h>#include<stdio.h>namespaceandroid{/*在硬件抽象層中定義的硬件訪問(wèn)結(jié)構(gòu)體,參考<hardware/hello.h>*/structhello_device_t*hello_device=NULL;/*通過(guò)硬件抽象層定義的硬件訪問(wèn)接口設(shè)置硬件寄存器val的值*/staticvoidhello_setVal(JNIEnv*env,jobjectclazz,jintvalue){intval=value;LOGI("HelloJNI:setvalue%dtodevice.",val);if(!hello_device){LOGI("HelloJNI:deviceisnotopen.");return;}hello_device->set_val(hello_device,val);}/*通過(guò)硬件抽象層定義的硬件訪問(wèn)接口讀取硬件寄存器val的值*/staticjinthello_getVal(JNIEnv*env,jobjectclazz){intval=0;if(!hello_device){LOGI("HelloJNI:deviceisnotopen.");returnval;}hello_device->get_val(hello_device,&val);LOGI("HelloJNI:getvalue%dfromdevice.",val);returnval;}/*通過(guò)硬件抽象層定義的硬件模塊打開(kāi)接口打開(kāi)硬件設(shè)備*/staticinlineinthello_device_open(consthw_module_t*module,structhello_device_t**device){returnmodule->methods->open(module,HELLO_HARDWARE_MODULE_ID,(structhw_device_t**)device);}/*通過(guò)硬件模塊ID來(lái)加載指定的硬件抽象層模塊并打開(kāi)硬件*/staticjbooleanhello_init(JNIEnv*env,jclassclazz){hello_module_t*module;LOGI("HelloJNI:initializing......");if(hw_get_module(HELLO_HARDWARE_MODULE_ID,(conststructhw_module_t**)&module)==0){LOGI("HelloJNI:helloStubfound.");if(hello_device_open(&(module->common),&hello_device)==0){LOGI("HelloJNI:hellodeviceisopen.");return0;}LOGE("HelloJNI:failedtoopenhellodevice.");return-1;}LOGE("HelloJNI:failedtogethellostubmodule.");return-1;}/*JNI方法表*/staticconstJNINativeMethodmethod_table[]={{"init_native","()Z",(void*)hello_init},{"setVal_native","(I)V",(void*)hello_setVal},{"getVal_native","()I",(void*)hello_getVal},};/*注冊(cè)JNI方法*/intregister_android_server_HelloService(JNIEnv*env){returnjniRegisterNativeMethods(env,"com/android/server/HelloService",method_table,NELEM(method_table));}};注意文件的命名方法,com_android_server前綴表示的是包名,表示硬件服務(wù)HelloService是放在frameworks/base/services/java目錄下的com/android/server目錄的,即存在一個(gè)命名為com.android.server.HelloService的類。這里,我們暫時(shí)略去HelloService類的描述,在下一篇文章中,我們將回到HelloService類來(lái)。簡(jiǎn)單地說(shuō),HelloService是一個(gè)提供Java接口的硬件訪問(wèn)服務(wù)類在這個(gè)cpp文件中,我們主要是做了以下事情1、包括頭文件(尤其是在hal層所定義的頭文件)#defineLOG_TAG"HelloService"#include"jni.h"#include"JNIHelp.h"#include"android_runtime/AndroidRuntime.h"#include<utils/misc.h>#include<utils/Log.h>#include<hardware/hardware.h>#include<hardware/hello.h>#include<stdio.h>2、編寫(xiě)jni接口通過(guò)對(duì)hal中函數(shù)的調(diào)用,編寫(xiě)jni接口(這里只是簡(jiǎn)單地進(jìn)行了一層包裝):注意,linuxdriver--hal--jni,jni與linuxdriver并無(wú)直接關(guān)系,即jni的函數(shù)接口與linuxdriver不一定完全一一對(duì)應(yīng),很簡(jiǎn)單的一個(gè)例子便是在linuxdriver中可能只有一個(gè)ioctl函數(shù),可是在hal層卻通過(guò)對(duì)ioctl的調(diào)用實(shí)現(xiàn)了get,set,exchange等多個(gè)功能./*通過(guò)硬件抽象層定義的硬件訪問(wèn)接口設(shè)置硬件寄存器val的值*/staticvoidhello_setVal(JNIEnv*env,jobjectclazz,jintvalue){intval=value;LOGI("HelloJNI:setvalue%dtodevice.",val);if(!hello_device){LOGI("HelloJNI:deviceisnotopen.");return;}hello_device->set_val(hello_device,val);}/*通過(guò)硬件抽象層定義的硬件訪問(wèn)接口讀取硬件寄存器val的值*/staticjinthello_getVal(JNIEnv*env,jobjectclazz){intval=0;if(!hello_device){LOGI("HelloJNI:devicei
溫馨提示
- 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。
最新文檔
- 武漢職業(yè)技術(shù)學(xué)院《土地統(tǒng)計(jì)與R語(yǔ)言》2023-2024學(xué)年第一學(xué)期期末試卷
- 武漢工貿(mào)職業(yè)學(xué)院《中級(jí)日語(yǔ)聽(tīng)說(shuō)》2023-2024學(xué)年第一學(xué)期期末試卷
- 新疆建設(shè)職業(yè)技術(shù)學(xué)院《環(huán)境微生物實(shí)驗(yàn)技術(shù)》2023-2024學(xué)年第一學(xué)期期末試卷
- 2024年跨境電商物流服務(wù)合同協(xié)議書(shū)
- 二零二五年度廠房安全檢查與整改合同模板3篇
- 2024我國(guó)電子商務(wù)平臺(tái)服務(wù)商合作協(xié)議依法簽訂3篇
- 2024物品寄售及電商合作運(yùn)營(yíng)合同范本3篇
- 二零二五版果園廢棄物資源化利用與環(huán)保合作協(xié)議3篇
- 2024年高級(jí)人工智能語(yǔ)音識(shí)別技術(shù)轉(zhuǎn)讓合同
- 二零二五年港灣云物聯(lián)網(wǎng)平臺(tái)接入服務(wù)協(xié)議3篇
- 高速公路初步設(shè)計(jì)匯報(bào)課件
- 航空油料計(jì)量統(tǒng)計(jì)員(初級(jí))理論考試復(fù)習(xí)題庫(kù)大全-上(單選題匯總)
- 申根簽證申請(qǐng)表模板
- 企業(yè)會(huì)計(jì)準(zhǔn)則、應(yīng)用指南及附錄2023年8月
- 2022年浙江省事業(yè)編制招聘考試《計(jì)算機(jī)專業(yè)基礎(chǔ)知識(shí)》真題試卷【1000題】
- 認(rèn)養(yǎng)一頭牛IPO上市招股書(shū)
- GB/T 3767-2016聲學(xué)聲壓法測(cè)定噪聲源聲功率級(jí)和聲能量級(jí)反射面上方近似自由場(chǎng)的工程法
- GB/T 23574-2009金屬切削機(jī)床油霧濃度的測(cè)量方法
- 動(dòng)物生理學(xué)-全套課件(上)
- 河北省衡水市各縣區(qū)鄉(xiāng)鎮(zhèn)行政村村莊村名居民村民委員會(huì)明細(xì)
- DB32-T 2665-2014機(jī)動(dòng)車維修費(fèi)用結(jié)算規(guī)范-(高清現(xiàn)行)
評(píng)論
0/150
提交評(píng)論