




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
1、Android震動系統(tǒng)開發(fā)全過程5一、前言本人剛學習安卓驅動開發(fā),水平不能說菜,是根本沒有水平,在這里把學習過程貼出來,跟大家一起學習交流,還望大家多多指正,轉載的請標明出處。二、android驅動介紹安卓總體架構是在Linux內核基礎上,增加硬件抽象層(HAL),運行庫,java虛擬機,程序框架等組成的,具體如下圖。HardwareAbstractionLayerqpcnGL|E5IlfAl-_-7HanicrCartLibniriflt賦酈林IAPPLICATICNS毗Zr1Gimli忖盧ClockAPPLIEATIDNRRAMEWORKActMty-ManagerManasrLinuxK
2、ernei_Drivr?ButfactliDriverU5R口抽刖W(wǎng)iA口聽比九udi臼焙MlPp羽fCalendarPacoAlbumAin尺口F匚)RLINTIN1Ej.;LIBRARIES銘曠觀;廠履贏安卓的應用程序是從applicationframework層架構上建立的。所有APK應用程序都是通過framework層來運行的。applicationframework是google寫好的,除非自己深度定制,一般是不會更改這個層的。對于驅動開發(fā)來講,我們要做的就是讓framework層能認識并操作我們的硬件設備就0K了。因此我們關心主要有3個層面:linuxKernel層HAL層JNI層
3、linuxKernel:是google在linux內核基礎上,專門為移動設備優(yōu)化后的內核,增加修改一些東西,擔修改的不多,對于內核驅動來講,基本沒有修改,做過linux驅動開發(fā)的人應該很容易理解。HAL,硬件抽象層:簡單來說,就是對Linux內核驅動程序的封裝,向上提供接口,屏蔽低層的實現(xiàn)細節(jié)。也就是說,把對硬件的支持分成了兩層,一層放在用戶空間(UserSpace),一層放在內核空間(KernelSpace),其中,硬件抽象層運行在用戶空間。用戶空間不屬于內核不必遵守GPL協(xié)議,各個廠商可以把與自己硬件設備相關,具有商業(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ā)板時候都會帶相應的資料。震動系統(tǒng)是android里面比較簡單的一個系統(tǒng),我采用的是從高層到底層的學習方式。因為我們的驅動最終是給應用程序用的,從application的需求分析JNI,然后分析HAL最后在我們寫linuxkernel驅動時候,很容易理解為什么要這么寫。好了開始正式分析。
5、Application層:通過google我找到關于APK訪問震動的如下說明:A、通過系統(tǒng)服務獲得手機震動服務,Vibratorvibrator=(Vibrator)getSystemService(VIBRATOR_SERVICE);B、得到震動服務后檢測vibrator是否存在:vibrator.hasVibrator();檢測當前硬件是否有vibrator,如果有返回true,如果沒有返回false。C、根據(jù)實際需要進行適當?shù)恼{用,vibrator.vibrate(longmilliseconds);開始啟動vibrator持續(xù)milliseconds毫秒。vibrator.vibrat
6、e(longpattern,intrepeat);以pattern方式重復repeat次啟動vibrator。(pattern的形式為newIongarg1,arg2,arg3,arg4.,其中以兩個一組的如arg1和arg2為一組、arg3和arg4為一組,每一組的前一個代表等待多少毫秒啟動vibrator,后一個代表vibrator持續(xù)多少毫秒停止,之后往復即可。Repeat表示重復次數(shù),當其為-1時,表示不重復只以pattern的方式運行一次)。D、vibrator.cancel();Vibrator停止。從上面的說明,可以看出應用程序調用震動系統(tǒng),是調用一個叫VIBRATOR_SERV
7、ICE的服務,這個服務有3個函數(shù),分別是hasVibrator(),r.vibrate,.cancel();當然這個三個函數(shù)可能在framework層進行的另一層的封裝,我沒有去深究。但可以推測出JNI層要做的是與注冊VIBRATOR_SERVICE服務和實現(xiàn)這三個函數(shù)相關的.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)/關閉振動器/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、.務returnjniRegisterNativeMethods(env,com/android/server/VibratorService,method_table,NELEM(method_table);從上面代碼可以看出,JNI做了兩件事:其一注冊vibrator服務,其二,實現(xiàn)了vibratorExists,vibratorOn,vibratorOff三個服務函數(shù)。進而我們可以分析出HAL層主要的就是實現(xiàn)次代碼里調用的三個函數(shù)vibrator_exists(),vibrator_on(timeout_ms),vibrator_off()。HAL層:經過各種查找我們找到了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()/關閉振動器就是設置振動器打開時間為0returnsendit(0);分析上面代碼可以看出,HAL訪問這個設備是打開/sys/class/timed_output/vibrator/enable,這個設備文件,然后向文件中寫入打開時間來完成設備操作的。因此很容易我們可以推斷出,linuxkernel層是要
14、生成這個設備文件然后,實現(xiàn)相應的函數(shù)。Linuxkernel層:通過上面分析我們大概了解了內核驅動所要實現(xiàn)的功能。通過各種參考資料,我查到了這個設備驅動是通過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分析上面代碼可以看出,我們的驅動是要實現(xiàn)timed_output_dev結
23、構體,然后注冊這個結構體就行了。下面我們開始真正動手。由于本人水平有限,參考了samung個公開kernel的代碼里的馬達驅動。寫出了自己的驅動:本人硬件的馬達通過P4.17腳控制高打開低關閉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腳控制高打開低關閉#defineMAX_TIMEOUT10000/*10s*/最長可打開10sstaticstructvibratorstructwake_lockwklock;/wake_lock防止震動過程中系統(tǒng)休眠,線程不釋放此設備,造成不必要錯誤structhrtimertimer;/高精度定時器structmutexlock;/互斥鎖,防止多線程同時訪問這個設備.structwork_structwork;/設備操作隊列,用于一次操作完成和下一次開始同步用(三星這么用的,具體為什么不直接用回調函數(shù),我也不懂,還望大神們私信給個說明感激不盡)v
25、ibdata;staticvoidmx6_vibrator_off(void)gpio_direction_output(SABRESD_VIBRATOR_CTL,0);wake_unlock(&vibdata.wklock);/震動關閉就可以釋放wake_lock鎖voidmx6_motor_enable(structtimed_output_dev*sdev,intvalue)mutex_lock(&vibdata.lock);/關鍵代碼段,同一時間只允許一個線程執(zhí)行/*cancelprevioustimerandsetGPIOaccordingtovalue*/當先前定時器完成后關閉這個
26、定時器/當上次震動完成后關閉這次動作/開始震動打開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;/為了使震動變得明顯,固定增加一個時間.跟硬件有關系hrtimer_start(&vibdata.timer,/開始
27、定時器ns_to_ktime(u64)value*NSEC_PER_MSEC),HRTIMER_MODE_REL);elsemx6_vibrator_off();mutex_unlock(&vibdata.lock);/關鍵代碼段執(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層里面的設備為/sys/class/timed_output/vibrator/enable/因此這個名字必須為=vibrator,.enable=mx6_motor_enable,.get_time=mx6_get_time,;staticenumhrtimer_restartmx6_vibrator_timer_func(structhrtimer*timer)/定時器結束時候的回調函數(shù)schedule_work(&vibdata.work);定時器完成了執(zhí)行work隊列回調函數(shù)來關
29、閉電機returnHRTIMER_NORESTART;staticvoidmx6_vibrator_work(structwork_struct*work)/工作隊列處理函數(shù),當工作隊列執(zhí)行當/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ù)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)系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 農村建屋合同范例
- 醫(yī)美合同范例范例
- 醫(yī)院員工社保合同范本
- 臨時入股合同范本
- 單筆物流運輸合同范本
- 保潔服務加盟合同范本
- 公司兼職用工合同范本
- 合伙合同范本符號
- 名創(chuàng)優(yōu)品合同范本
- 冶金焦合同范本
- 家庭節(jié)約用水
- 2022公務員錄用體檢操作手冊(試行)
- 電力事業(yè)部崗位職責
- GB/T 7024-2008電梯、自動扶梯、自動人行道術語
- GB/T 36663-2018船舶和海上技術船舶系泊和拖帶設備閉式導纜孔
- GB/T 3077-2015合金結構鋼
- 肝硬化超聲診斷 課件
- 現(xiàn)代節(jié)水灌溉技術課件
- 常用臨床檢驗
- 人類行為與社會環(huán)境全套課件
- 運輸管理實務教案
評論
0/150
提交評論