




版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)
文檔簡介
1、Android震動系統(tǒng)開發(fā)全過程5一、前言本人剛學(xué)習(xí)安卓驅(qū)動開發(fā),水平不能說菜,是根本沒有水平,在這里把學(xué)習(xí)過程貼出來,跟大家一起學(xué)習(xí)交流,還望大家多多指正,轉(zhuǎn)載的請標明出處。二、android驅(qū)動介紹安卓總體架構(gòu)是在Linux內(nèi)核基礎(chǔ)上,增加硬件抽象層(HAL),運行庫,java虛擬機,程序框架等組成的,具體如下圖。HardwareAbstractionLayerqpcnGL|E5IlfAl-_-7HanicrCartLibniriflt賦酈林IAPPLICATICNS毗Zr1Gimli忖盧ClockAPPLIEATIDNRRAMEWORKActMty-ManagerManasrLinuxK
2、ernei_Drivr?ButfactliDriverU5R口抽刖W(wǎng)iA口聽比九udi臼焙MlPp羽fCalendarPacoAlbumAin尺口F匚)RLINTIN1Ej.;LIBRARIES銘曠觀;廠履贏安卓的應(yīng)用程序是從applicationframework層架構(gòu)上建立的。所有APK應(yīng)用程序都是通過framework層來運行的。applicationframework是google寫好的,除非自己深度定制,一般是不會更改這個層的。對于驅(qū)動開發(fā)來講,我們要做的就是讓framework層能認識并操作我們的硬件設(shè)備就0K了。因此我們關(guān)心主要有3個層面:linuxKernel層HAL層JNI層
3、linuxKernel:是google在linux內(nèi)核基礎(chǔ)上,專門為移動設(shè)備優(yōu)化后的內(nèi)核,增加修改一些東西,擔(dān)修改的不多,對于內(nèi)核驅(qū)動來講,基本沒有修改,做過linux驅(qū)動開發(fā)的人應(yīng)該很容易理解。HAL,硬件抽象層:簡單來說,就是對Linux內(nèi)核驅(qū)動程序的封裝,向上提供接口,屏蔽低層的實現(xiàn)細節(jié)。也就是說,把對硬件的支持分成了兩層,一層放在用戶空間(UserSpace),一層放在內(nèi)核空間(KernelSpace),其中,硬件抽象層運行在用戶空間。用戶空間不屬于內(nèi)核不必遵守GPL協(xié)議,各個廠商可以把與自己硬件設(shè)備相關(guān),具有商業(yè)機密的一些代碼放在HAL層。JNI層:提供java和底層C、C+的動態(tài)鏈
4、接庫的接口。我理解的是JNI就是一個代理,可以把C和C+生成的接口函數(shù)翻譯成Java可用,提供給framework層。三、振動系統(tǒng)開發(fā)過程1.硬件平臺CPU:IMX6Q4核1GRAM:1GFLASH:8G板載這次開發(fā)用的代碼都是google和飛思卡爾提供的具體的就不再說明了,因為每個平臺代碼都有所不同,而且買開發(fā)板時候都會帶相應(yīng)的資料。震動系統(tǒng)是android里面比較簡單的一個系統(tǒng),我采用的是從高層到底層的學(xué)習(xí)方式。因為我們的驅(qū)動最終是給應(yīng)用程序用的,從application的需求分析JNI,然后分析HAL最后在我們寫linuxkernel驅(qū)動時候,很容易理解為什么要這么寫。好了開始正式分析。
5、Application層:通過google我找到關(guān)于APK訪問震動的如下說明:A、通過系統(tǒng)服務(wù)獲得手機震動服務(wù),Vibratorvibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);B、得到震動服務(wù)后檢測vibrator是否存在:vibrator.hasVibrator();檢測當(dāng)前硬件是否有vibrator,如果有返回true,如果沒有返回false。C、根據(jù)實際需要進行適當(dāng)?shù)恼{(diào)用,vibrator.vibrate(longmilliseconds);開始啟動vibrator持續(xù)milliseconds毫秒。vibrator.vibrat
6、e(longpattern,intrepeat);以pattern方式重復(fù)repeat次啟動vibrator。(pattern的形式為newIongarg1,arg2,arg3,arg4.,其中以兩個一組的如arg1和arg2為一組、arg3和arg4為一組,每一組的前一個代表等待多少毫秒啟動vibrator,后一個代表vibrator持續(xù)多少毫秒停止,之后往復(fù)即可。Repeat表示重復(fù)次數(shù),當(dāng)其為-1時,表示不重復(fù)只以pattern的方式運行一次)。D、vibrator.cancel();Vibrator停止。從上面的說明,可以看出應(yīng)用程序調(diào)用震動系統(tǒng),是調(diào)用一個叫VIBRATOR_SERV
7、ICE的服務(wù),這個服務(wù)有3個函數(shù),分別是hasVibrator(),r.vibrate,.cancel();當(dāng)然這個三個函數(shù)可能在framework層進行的另一層的封裝,我沒有去深究。但可以推測出JNI層要做的是與注冊VIBRATOR_SERVICE服務(wù)和實現(xiàn)這三個函數(shù)相關(guān)的.HAL層:這一層我找到了具體的代碼我們會好分析很多,其代碼是:androidframeworksbaseservicesjnicom_android_server_VibratorService.cpp#defineLOG_TAGVibratorService#includejni.h#includeJNIHelp.h#
8、includeandroid_runtime/AndroidRuntime.h#include#include#include#includenamespaceandroidstaticjbooleanvibratorExists(JNIEnv*env,jobjectclazz)/判斷振動器是否存在returnvibrator_exists()0?JNI_TRUE:JNI_FALSE;staticvoidvibratorOn(JNIEnv*env,jobjectclazz,jlongtimeout_ms)/打開振動器/LOGI(vibratorOnn);vibrator_on(timeout_
9、ms);staticvoidvibratorOff(JNIEnv*env,jobjectclazz)/關(guān)閉振動器/LOGI(vibratorOffn);vibrator_off();staticJNINativeMethodmethod_table=vibratorExists,()Z,(void*)vibratorExists,vibratorOn,(J)V,(void*)vibratorOn,vibratorOff,()V,(void*)vibratorOff;intregister_android_server_VibratorService(JNIEnv*env)注冊vibrator服
10、.務(wù)returnjniRegisterNativeMethods(env,com/android/server/VibratorService,method_table,NELEM(method_table);從上面代碼可以看出,JNI做了兩件事:其一注冊vibrator服務(wù),其二,實現(xiàn)了vibratorExists,vibratorOn,vibratorOff三個服務(wù)函數(shù)。進而我們可以分析出HAL層主要的就是實現(xiàn)次代碼里調(diào)用的三個函數(shù)vibrator_exists(),vibrator_on(timeout_ms),vibrator_off()。HAL層:經(jīng)過各種查找我們找到了vibrato
11、r的hal層代碼:android40hardwarelibhardware_legacyvibratorvibrator.c#include#includeqemu.h#include#include#include#include#defineTHE_DEVICE/sys/class/timed_output/vibrator/enableintvibrator_exists()/判斷振動器是否存在intfd;#ifdefQEMU_HARDWARE/模擬器情況下實現(xiàn)此功能if(qemu_check()return1;#endiffd=open(THE_DEVICE,O_RDWR);if(fd
12、0)return0;close(fd);return1;staticintsendit(inttimeout_ms)打開振動器timeout_ms毫秒intnwr,ret,fd;charvalue20;#ifdefQEMU_HARDWARE/模擬器情況下實現(xiàn)次功能if(qemu_check()returnqemu_control_command(vibrator:%d,timeout_ms);#endiffd=open(THE_DEVICE,O_RDWR);if(fd0)returnerrno;nwr=sprintf(value,%dn,timeout_ms);ret=write(fd,val
13、ue,nwr);close(fd);return(ret=nwr)?0:-1;intvibrator_on(inttimeout_ms)/*constanton,uptomaximumallowedtime*/returnsendit(timeout_ms);intvibrator_off()/關(guān)閉振動器就是設(shè)置振動器打開時間為0returnsendit(0);分析上面代碼可以看出,HAL訪問這個設(shè)備是打開/sys/class/timed_output/vibrator/enable,這個設(shè)備文件,然后向文件中寫入打開時間來完成設(shè)備操作的。因此很容易我們可以推斷出,linuxkernel層是要
14、生成這個設(shè)備文件然后,實現(xiàn)相應(yīng)的函數(shù)。Linuxkernel層:通過上面分析我們大概了解了內(nèi)核驅(qū)動所要實現(xiàn)的功能。通過各種參考資料,我查到了這個設(shè)備驅(qū)動是通過timed_output框架來實現(xiàn)的,有框架在又簡單了不少,我們找到timed_output框架實現(xiàn)的函數(shù)在:kerneldriversstagingandroidtimed_output.c#include#include#include#include#include#includetimed_output.hstaticstructclass*timed_output_class;staticatomic_tdevice_count
15、;staticssize_tenable_show(structdevice*dev,structdevice_attribute*attr,char*buf)structtimed_output_dev*tdev=dev_get_drvdata(dev);intremaining=tdev-get_time(tdev);returnsprintf(buf,%dn,remaining);staticssize_tenable_store(structdevice*dev,structdevice_attribute*attr,constchar*buf,size_tsize)structtim
16、ed_output_dev*tdev=dev_get_drvdata(dev);intvalue;if(sscanf(buf,%d,&value)!=1)return-EINVAL;tdev-enable(tdev,value);returnsize;staticDEVICE_ATTR(enable,S_IRUGO|S_IWUSR,enable_show,enable_store);staticintcreate_timed_output_class(void)if(!timed_output_class)timed_output_class=class_create(THIS_MODULE,
17、timed_output);if(IS_ERR(timed_output_class)returnPTR_ERR(timed_output_class);atomic_set(&device_count,0);return0;inttimed_output_dev_register(structtimed_output_dev*tdev)intret;if(!tdev|!tdev-name|!tdev-enable|!tdev-get_time)return-EINVAL;ret=create_timed_output_class();if(retindex=atomic_inc_return
18、(&device_count);tdev-dev=device_create(timed_output_class,NULL,MKDEV(0,tdev-index),NULL,tdev-name);if(IS_ERR(tdev-dev)returnPTR_ERR(tdev-dev);ret=device_create_file(tdev-dev,&dev_attr_enable);if(retdev,tdev);tdev-state=0;return0;err_create_file:device_destroy(timed_output_class,MKDEV(0,tdev-index);p
19、rintk(KERN_ERRtimed_output:Failedtoregisterdriver%sn,tdev-name);returnret;EXPORT_SYMBOL_GPL(timed_output_dev_register);voidtimed_output_dev_unregister(structtimed_output_dev*tdev)device_remove_file(tdev-dev,&dev_attr_enable);device_destroy(timed_output_class,MKDEV(0,tdev-index);dev_set_drvdata(tdev-
20、dev,NULL);EXPORT_SYMBOL_GPL(timed_output_dev_unregister);staticint_inittimed_output_init(void)returncreate_timed_output_class();staticvoid_exittimed_output_exit(void)class_destroy(timed_output_class);module_init(timed_output_init);module_exit(timed_output_exit);MODULE_AUTHOR(MikeLockwood);MODULE_DES
21、CRIPTION(timedoutputclassdriver);MODULE_LICENSE(GPL);kerneldriversstagingandroidtimed_output.h#ifndef_LINUX_TIMED_OUTPUT_H#define_LINUX_TIMED_OUTPUT_Hstructtimed_output_devconstchar*name;/*enabletheoutputandsetthetimer*/void(*enable)(structtimed_output_dev*sdev,inttimeout);/*returnsthecurrentnumbero
22、fmillisecondsremainingonthetimer*/int(*get_time)(structtimed_output_dev*sdev);/*privatedata*/structdevice*dev;intindex;intstate;externinttimed_output_dev_register(structtimed_output_dev*dev);externvoidtimed_output_dev_unregister(structtimed_output_dev*dev);#endif分析上面代碼可以看出,我們的驅(qū)動是要實現(xiàn)timed_output_dev結(jié)
23、構(gòu)體,然后注冊這個結(jié)構(gòu)體就行了。下面我們開始真正動手。由于本人水平有限,參考了samung個公開kernel的代碼里的馬達驅(qū)動。寫出了自己的驅(qū)動:本人硬件的馬達通過P4.17腳控制高打開低關(guān)閉kernel_imxdriversvibratorvibrator.c#include#include#include#include#include#include#include#include#include#include#include#defineIMX_GPIO_NR(bank,nr)(bank)-1)*32+(nr)/IO定義#defineSABRESD_VIBRATOR_CTLIMX_G
24、PI0_NR(4,17)電機通過P4.17腳控制高打開低關(guān)閉#defineMAX_TIMEOUT10000/*10s*/最長可打開10sstaticstructvibratorstructwake_lockwklock;/wake_lock防止震動過程中系統(tǒng)休眠,線程不釋放此設(shè)備,造成不必要錯誤structhrtimertimer;/高精度定時器structmutexlock;/互斥鎖,防止多線程同時訪問這個設(shè)備.structwork_structwork;/設(shè)備操作隊列,用于一次操作完成和下一次開始同步用(三星這么用的,具體為什么不直接用回調(diào)函數(shù),我也不懂,還望大神們私信給個說明感激不盡)v
25、ibdata;staticvoidmx6_vibrator_off(void)gpio_direction_output(SABRESD_VIBRATOR_CTL,0);wake_unlock(&vibdata.wklock);/震動關(guān)閉就可以釋放wake_lock鎖voidmx6_motor_enable(structtimed_output_dev*sdev,intvalue)mutex_lock(&vibdata.lock);/關(guān)鍵代碼段,同一時間只允許一個線程執(zhí)行/*cancelprevioustimerandsetGPIOaccordingtovalue*/當(dāng)先前定時器完成后關(guān)閉這個
26、定時器/當(dāng)上次震動完成后關(guān)閉這次動作/開始震動打開wakelock鎖不允許休眠hrtimer_cancel(&vibdata.timer);cancel_work_sync(&vibdata.work);if(value)wake_lock(&vibdata.wklock);gpio_direction_output(SABRESD_VIBRATOR_CTL,1);if(value0)if(valueMAX_TIMEOUT)value=MAX_TIMEOUT;value+=45;/為了使震動變得明顯,固定增加一個時間.跟硬件有關(guān)系hrtimer_start(&vibdata.timer,/開始
27、定時器ns_to_ktime(u64)value*NSEC_PER_MSEC),HRTIMER_MODE_REL);elsemx6_vibrator_off();mutex_unlock(&vibdata.lock);/關(guān)鍵代碼段執(zhí)行完成,釋放互斥鎖intmx6_get_time(structtimed_output_dev*sdev)if(hrtimer_active(&vibdata.timer)/讀取剩余時間按并返回ktime_tr=hrtimer_get_remaining(&vibdata.timer);returnktime_to_ms(r);return0;structtimed
28、_output_devmx6_motot_driver=/注意這個名字,由于HAL層里面的設(shè)備為/sys/class/timed_output/vibrator/enable/因此這個名字必須為=vibrator,.enable=mx6_motor_enable,.get_time=mx6_get_time,;staticenumhrtimer_restartmx6_vibrator_timer_func(structhrtimer*timer)/定時器結(jié)束時候的回調(diào)函數(shù)schedule_work(&vibdata.work);定時器完成了執(zhí)行work隊列回調(diào)函數(shù)來關(guān)
29、閉電機returnHRTIMER_NORESTART;staticvoidmx6_vibrator_work(structwork_struct*work)/工作隊列處理函數(shù),當(dāng)工作隊列執(zhí)行當(dāng)/schedule_work時候執(zhí)行mx6_vibrator_off();void_initmx6_motor_init()intret=0;hrtimer_init(&vibdata.timer,CLOCK_MONOTONIC,HRTIMER_MODE_REL);/初始化定時器vibdata.timer.function=mx6_vibrator_timer_func;/設(shè)置回調(diào)函數(shù)INIT_WORK(&vibdata.work,mx6_vibrator_work);/初始化工作隊列ret=gpio_request(SABRESD_VIBRATOR_CTL,vibrator-en);/申請IOif(ret0)printk(vibratorrequestIOerr!:%dn,ret);returnret;wake_lock_init(&vibdata.wklock,WAKE_LOCK_SUSPEND,vibrator);/初始
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 2025年辦公樓租賃合同標準協(xié)議
- 維修合同樣本-合同范本-維修合同6篇
- 2025年企業(yè)股權(quán)置換策劃合同模板
- 2025年金融行業(yè)勞動合同范例樣本
- 2025年產(chǎn)品銷售合同書
- 2025年無房產(chǎn)證房產(chǎn)買賣合同范本
- 2025年工程項目中標后合同范例
- 2025年股權(quán)轉(zhuǎn)讓合同
- 建筑裝飾工程施工合同(合同示范文本)6篇
- 入股分紅和合作協(xié)議區(qū)別
- GB 4404.1-2024糧食作物種子第1部分:禾谷類
- 副總經(jīng)理招聘面試題與參考回答(某大型國企)2024年
- 診所與醫(yī)生合作協(xié)議
- 西嶺雪山旅游區(qū)總體規(guī)劃終稿文本(09-08-02)
- 一般固廢危廢安全管理制度
- 三大戰(zhàn)役完整版本
- DB11T 353-2021 城市道路清掃保潔質(zhì)量與作業(yè)要求
- 2024電力建設(shè)土建工程施工技術(shù)檢驗規(guī)范
- 2024 smart汽車品牌用戶社區(qū)運營全案
- 2023-2024學(xué)年粵教版(2019)高中信息技術(shù)必修一《數(shù)據(jù)與計算》第一章第一節(jié)《數(shù)據(jù)及其特征》教案
- 5 《人應(yīng)當(dāng)堅持正義》教案統(tǒng)編版選擇性必修中冊
評論
0/150
提交評論