android書2.基礎(chǔ)kernel開發(fā)培訓(xùn)_第1頁
android書2.基礎(chǔ)kernel開發(fā)培訓(xùn)_第2頁
android書2.基礎(chǔ)kernel開發(fā)培訓(xùn)_第3頁
android書2.基礎(chǔ)kernel開發(fā)培訓(xùn)_第4頁
android書2.基礎(chǔ)kernel開發(fā)培訓(xùn)_第5頁
已閱讀5頁,還剩44頁未讀, 繼續(xù)免費閱讀

下載本文檔

版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認領(lǐng)

文檔簡介

1、AndroidKernel 開發(fā)系列培訓(xùn)E-Mai Linux開發(fā)環(huán)境篇 LinuxAndroidKernel 開發(fā)系列培訓(xùn)E-Mai Linux開發(fā)環(huán)境篇 Linux驅(qū)動開發(fā)篇 Linux 內(nèi)核篇一。AndroidKernel kernel:linuxGCC編譯器toolchain/arm-eabi-4.2.1 linux 主機環(huán)境:ubuntu-8.101.kerneltoolchainarmgcc編輯Makefile sudovim$sudoscripts/kconfig/conf.c: 在函數(shù)conf_askvalue中scripts/kconfig/conf.c:104: 有 scr

2、ipts/kconfig/conf.c: 在函數(shù)conf_choice中scripts/kconfig/conf.c:306: HOSTCC *Unabletofindthencursesscripts/kconfig/conf.c: 在函數(shù)conf_askvalue中scripts/kconfig/conf.c:104: 有 scripts/kconfig/conf.c: 在函數(shù)conf_choice中scripts/kconfig/conf.c:306: HOSTCC *Unabletofindthencurseslibrariesor*requiredheader 有 *configre

3、quiresthencurses*Installncurses(ncurses-devel)andtrymake1:*scripts/kconfig/dochecklxdialog 1make:*config sudoapt-getinstalllibncurses5-make二.Androidwindowlinux SAMBASSHwindowsourceinsightwindow linuxvicscope+1.windowUbuntulinux 下建立SAMBASamba(注:若在windowlinuxSamba服務(wù)器od -R改變權(quán)限#apt-getinstall#mkdirod777

4、/root/share#apt-getinstall#mkdirod777/root/share-#cp/etc/samba/smb.conf/etc/samba/smb.conf.bak #vim /etc/samba/smb.confworkgroup:Workgroup=displaycharsetUTF-8 dos charset = cp936 unix charset = UTF-8=encrypt passwords: encryptpasswordsyescomment=MyShareDirectory available = yes browseable = yes publ

5、ic = yes writable = yes createmode=0664directorymode=samba#/etc/init.d/sambawindowsamba輸入linuxIPsharesourceinsight 看代碼了Ubuntulinux 安裝SSHssh若出現(xiàn)以下錯誤,則是因為還沒有安裝 ssh-ssh:connecttohostlocalhostport22:Connection安裝SSH-sudoapt-getinstallopenssh-啟動SSH-ssh:connecttohostlocalhostport22:Connection安裝SSH-sudoapt-g

6、etinstallopenssh-啟動SSH-sudo/etc/init.d/sshwindowlinuxmake linux安裝文本編輯器:sudoapt-getinstall制作cscope索引文件:$sudoapt-getinstall制作ctags文件: $sudoapt-getinstall使用方法首先進入kernel 的主目錄(也就是內(nèi)核源代碼根目錄輸入make輸入ctagsvi來閱讀源碼了init/main.c,你要用: vi init/main.c而不要 cd init; vi main.c函數(shù)使用CtrlCtrl鍵和鍵如果此函數(shù)有多個實例,會有個列表供你選擇返回上一級函數(shù)使用

7、Ctrl+tCtrl鍵和t鍵)vim 中執(zhí)行”:help tags”命令查詢它的用法二.Androidlinux 1.Androidlinux 驅(qū)動開發(fā)術(shù)一個應(yīng)用程序從頭到尾完成一個任務(wù),而模塊則是為以后處理某些請求而主”函數(shù)就立即中止了。自通常稱執(zhí)行態(tài)為“內(nèi)核空間”和“用戶空間”Linux 執(zhí)行,也稱為“管理員態(tài)”,在這一級任何操作都可以執(zhí)行。 程序則執(zhí)行在最低級,所謂的“用戶態(tài)”對硬件的直 接。模塊是在所謂的“內(nèi)核空間”中運行的,而應(yīng)用程 序則是在“用戶空間”它們分不同的內(nèi)“地址空間”Linux 通過系統(tǒng)調(diào)用和硬件中斷完成從用戶空間到內(nèi)核空間的控制轉(zhuǎn)移。執(zhí)行系2.Androidlinux

8、設(shè)備驅(qū)動開發(fā)的基本流Linux 硬件。Android Linux 開發(fā)沒有區(qū)別。可以在硬件生產(chǎn)廠家或ernet 上尋找驅(qū)動程序,也可以根據(jù)相近的Linux (6)測試2.Androidlinux 設(shè)備驅(qū)動開發(fā)的基本流Linux 硬件。Android Linux 開發(fā)沒有區(qū)別。可以在硬件生產(chǎn)廠家或ernet 上尋找驅(qū)動程序,也可以根據(jù)相近的Linux (6)測試該設(shè)備,編寫應(yīng)用程序,對驅(qū)動程序3.Androidlinux 設(shè)備驅(qū)動開發(fā)關(guān)鍵函數(shù)介從Linux2.6機制:Platform_device和Platform_driver。Linux大部分的設(shè)備驅(qū)動,都可以使用這套機制, Platform

9、_device。Linuxplatformdriver機制和傳統(tǒng)的devicedriver 機制(通過driver_registerplatform platform device 提供的標(biāo)準(zhǔn)接口進行申請并使用。這樣提高了驅(qū)動platform_device_register(structplatform_devicevoidplatform_device_unregister(structplatform_deviceplatform_driver_register(structplatform_drivervoidplatform_driver_unregister(structplatfo

10、rm_driverinit_module()0void#defines icinlineinitcall_t returninitfn;init_module(void) attribute /*Thisisonlyrequiredifyouwanttovoid#defines icinlineinitcall_t returninitfn;init_module(void) attribute /*Thisisonlyrequiredifyouwanttobeunloadable.*/ #define module_exit(exitfn)s icinlineexitcall_t retur

11、nexitfn;voidcleanup_module(void) attribute 雖然模塊作為內(nèi)核的一部分,但并未被編譯到內(nèi)核中,它們被分別編譯和件。在命令行里加上-c的參數(shù)和“-D KERNEL -DMODULE”參數(shù)。然后用depmod -a模塊用 insmod 命令加載,用 rmmod 命令來卸載,這兩個命令分別調(diào)用 init_module()和 cleanup_ module()lsmod 命 令來查看所有已加載的模塊的狀態(tài)。insmod 文件,但不同的是它們被成可重定位映像。insmod 將執(zhí)行一個級系統(tǒng)調(diào)用 級系統(tǒng)調(diào)用 create_module()module uniniti

12、alized。malloc free void*voidkfree(void*len 為希望申請的字節(jié)數(shù),obj 的內(nèi)存指針。priority (4)在設(shè)備驅(qū)動程序中,一般都需要用到計時機制。在Linux系統(tǒng)中,時鐘是由系統(tǒng)接管的,設(shè)#include #includevoidadd_timer(structtimer_list*timer); del_timer(struct timer_list * timer);inlinevoidinit_timer(struct(4)在設(shè)備驅(qū)動程序中,一般都需要用到計時機制。在Linux系統(tǒng)中,時鐘是由系統(tǒng)接管的,設(shè)#include #includev

13、oidadd_timer(structtimer_list*timer); del_timer(struct timer_list * timer);inlinevoidinit_timer(structtimer_list*structtimer_liststruct timer_list structtimer_list*next; structtimer_list*prev; unsignedlongexpires; unsigned long data;void(*function)(unsignedlong其中,expiresfunctionjiffiesadd_timer jiff

14、ies=JIFFIES+numnum 有關(guān),里定義了常 數(shù)HZ秒內(nèi)最小時間間隔的數(shù)目,則 num*HZ 表示 num 秒。系統(tǒng)計時到預(yù)定時間就調(diào) 用 function,并把此子程序從定時隊列里刪除,可見,如果想要每隔一定時間間隔執(zhí)行 一次的話,就必須在function 里再一次調(diào)用add_timer。Function 的參數(shù)d 即為timer 里面的datalinux2.6#include linux/#include #include voidhrtimer_init(structhrtimer*timer,clockid_twhich_clock,enumhrtimer_mode/*Bas

15、ictimeroperations:hrtimer_start(structhrtimer*timer,ktime_ttim,constenumhrtimer_modemode); hrtimer_cancel(struct hrtimer *timer);s icinlinektime_tktime_add(constktime_tadd1,constktime_ts ic structhrtimerstructrb_node enum hrtimer_restart structhrtimer_clock_base unsigned longstruct(*function)(struct

16、hrtimer*);#ifdefS;其中,ktime_ttim 是要執(zhí)行function的時間。系統(tǒng)計時到預(yù)定時間就調(diào) 用function,并把此子程序從定時隊列里刪除,可見,如果想要每隔一定時間間隔執(zhí)行 一次的話,就必須在 function 里再一次調(diào)用 hrtimer_restart HRTIMER_RESTART。 voidirq,voiddev_id,struct;其中,ktime_ttim 是要執(zhí)行function的時間。系統(tǒng)計時到預(yù)定時間就調(diào) 用function,并把此子程序從定時隊列里刪除,可見,如果想要每隔一定時間間隔執(zhí)行 一次的話,就必須在 function 里再一次調(diào)用 h

17、rtimer_restart HRTIMER_RESTART。 voidirq,voiddev_id,structpt_regsunsignedlongflags, const char *device, void *dev_idvoidirq,void handler 為向系統(tǒng)登記的中斷處理子程序,中斷產(chǎn)生時由系統(tǒng)來調(diào)用,調(diào)用時所 帶參irq為中斷號,dev_id為申請時告訴系統(tǒng)的設(shè)備標(biāo)識,regs為中斷發(fā)生時寄存器 內(nèi)容。 flag 理程序是快速處理程序(flag 里設(shè)置了 ERRUPT)還是慢速處理程序(不設(shè)置_irq=2set_external_irq (eret_val = requ

18、est_irq(e2_handler, “S3C2410X eif(ret_val 0)returnLinux Linux MakefileLinux Linux driver/input/keyboard driver/input/keyboard/Kconfigdriver/input/keyboard/Kconfig修改完成后,5.AD修改完成后,5.AD按鍵驅(qū)動實例(T28按鍵2-4-1 Ad(1)AdRK2806 4(1)AdRK2806 4 AD 控制器,可以方便地輸入各種信號。T28 目標(biāo)板選用 RK2806 微處理器,帶有5 個接到AD 通道1 的按鍵, 硬件原理圖如圖2-4-

19、1 所示。按鍵控ADAD 值的不同分別區(qū)別不同的按鍵按下。與按鍵相AD 6.3 所示的控制寄存器配置AD2-4-3 AD Ad控制器驅(qū)動接口函數(shù) #define IN_API_DRIVER_ADC #include #include #include #include #include#include #include #include #include#includelinux/kernel#include:ADC: : ADC 32#include #include #include #include#includeADC_STAS = ADC_STOP) adcReturn=-retur

20、n:8 :ADC的轉(zhuǎn)換 ch0-: :0-328pADC_REGpheadAdc=(pADC_REG)/rockchip_scu_reset_unit(7return(-pheadAdc-ADC_CTRL = (pheadAdc-ADC_CTRL & 0 xe0) | ADC_ ADC_START|ch;return|:ADC: :pADC_REGpheadAdc=pheadAdc-ADC_CTRL = (pheadAdc-ADC_CTRL & 0 xe0) | ADC_ ADC_START|ch;return|:ADC: :pADC_REGpheadAdc=(pADC_REG)pheadAd

21、c-ADC_CTRL=(pheadAdc-ADC_CTRL&0 xdf)|;:ADC: :pADC_REGpheadAdc=(pADC_REG)pheadAdc-ADC_CTRL=(pheadAdc-ADC_CTRL&0 xdf)|;:ADC: :32 adcData; adcData=:ADC: :0-32pADC_REGpheadAdc=(pADC_REG)rockchip_scu_register(_LSADC , SCU_MODE_FREQ 1 , NULL /* :ADC: :0-32pADC_REGpheadAdc=(pADC_REG)rockchip_scu_register(_

22、LSADC , SCU_MODE_FREQ 1 , NULL /* max return(-return:ADC: :pADC_REGpheadAdc=(pADC_REG) _LSADC:adc adc: :void32if (adcTemp != -1) : :void32if (adcTemp != -1) k(nRockA canning:notifg_adcch =Au16returnreturnreturn/*BATTERY u16returnsicstructresource0= = /*BATTERY u16returnsicstructresource0= = .end =AD

23、C_BASE_ADDR+SZ_4K-= 1= .start= .end = sicstructplatform_devicerk28_key_device=-= .resource = ,=void); #include #include #include #include linux/#include #include#include #include #include#includelinux/delay#includeasm/mach-types#include#include#include #include #include*KeypadController/#define#incl

24、ude0 #include /*Debug*/ #if 0#define DBG(x.)#includeasm/mach-types#include#include#include #include #include*KeypadController/#define#include0 #include /*Debug*/ #if 0#define DBG(x.)k(KERN_INFOx) #defineDBG(x.) /ROCKCHIPADKEYCODE,fordemo#if/59 /VOLUME_UP 158116#defineValuedrift #defineEmptyADValue #

25、defineADKEYNumereventO 158116#defineValuedrift #defineEmptyADValue #defineADKEYNumereventO12s = /*per sicunsigned icunsigned icicvaluecount=g_code=g_wakerk28_pm_s us #defineKEY_PHYS_NAME /ADC typedef structs-ADC_keystad1valuetab=95,sADC_keystad2valuetab=95, /keycodes icunsignedcharinitkey_code/keyco

26、des icunsignedcharinitkey_codestructrk28_AD_button_platform_datastructrk28_AD_buttonstructrk28_AD_button_platform_data*pdata; struct timer_list timer;struct clk structinput_dev*input_dev; void iomem/* matrix key code map */ unsignedcharkeycodes13;/* erowbitsofeachcolumn scan32_tdirect_key_s structrk

27、28_AD_buttonvoid pr32ADCInit(void); advalue,pADC_keystreturn ptab-adc_keycode;returnsrk28_AD_button_open(structinput_devstructrk28_AD_button*AD_button=returnsicvoidreturn ptab-adc_keycode;returnsrk28_AD_button_open(structinput_devstructrk28_AD_button*AD_button=returnsicvoidrk28_AD_button_close(struc

28、tinput_devstructrk28_AD_button*AD_button=#defineres_size(res)(res)-end-(res)-start+s leTimes=s icvoidrk28_adkeyscan_timer(unsignedlongADKEY1,code=/*Enable ADcontrollertoleif leTimesleTimesgoto/*scangpiobuttonleTimes=/*Get button value*/ goto scan_io_key1;if(valuecount2)goto scan_code; valuecount = 2

29、;goto scan_code;valuecount/*Get button value*/ goto scan_io_key1;if(valuecount s = us=if(g_wake=g_wake=0; /*alreadywakek(n%sWakeUp!n, FUNCTION voidrk28_send_wakeup_key(voidk(n%sWakeUp!n, FUNCTION voidrk28_send_wakeup_key(voidsicirqreturn_trk28_AD_irq_handler(s32irq,voidif(rk28_pm_s us=g_wakek(n%sWak

30、eUp!n, FUNCTION ); return IRQ_HANDLED;s devinitrk28_AD_button_probe(structplatform_devicestructrk28_AD_button*AD_button; struct input_dev *input_dev;AD_button=kzalloc(sizeof(structrk28_AD_button),/*Createandregistertheinputdriver.*/ input_dev = input_allocate_device();if(!input_dev|!AD_button)dev_er

31、r(&pdev-dev,failedtoallocateinputdevicen); error = -ENOMEM;gotoret=request_irq(IRQ_NR_ADC,rk28_AD_irq_handler,0,ADC,if(ret 0) k(KERN_CRITCantregisterif(ret keycodes,initkey_code,sizeof(AD_button-keycodes); input_dev-name = pdev-name;input_dev-open = rk28_AD_button_open; input_dev-close=rk28_AD_butto

32、n_close; input_dev-dev.parent = &pdev-dev; input_dev-phys = KEY_PHYS_NAME; input_dev-id.vendor = 0 x0001;input_duct=input_dev-keycode = AD_button-keycodes; input_dev-keycodesize=sizeof(unsignedchar);for (i = 0; i keybit); AD_button-input_dev = input_dev; input_dev-evbit0=BIT_MASK(EV_KEY);

33、platform_set_drvdata(pdev,AD_button); /*Registertheinputdevice 一個input error=input_register_device(input_dev); if (error) dev_err(&pdev-dev,failedtoregisterinputdevicen); goto failed2;setup_timer(&AD_button-timer,rk28_adkeyscan_timer,(unsignedlong)AD_button); AD_button-timer.expires = jiffies + 3;中斷

34、回調(diào)函數(shù)error=request_gpio_irq(GPIOPortE_Pin2,rk28_AD_irq_handler,GPIOEdgelFalling,NULL); k(unabletorequestrecoverkeyIRQn); goto failed2;return0; platform_set_drvdata(pdev, NULL);returnserror=request_gpio_irq(GPIOPortE_Pin2,rk28_AD_irq_handler,GPIOEdgelFalling,NULL); k(unabletorequestrecoverkeyIRQn); go

35、to failed2;return0; platform_set_drvdata(pdev, NULL);returns devexitrk28_AD_button_remove(structplatform_devicestructrk28_AD_button*AD_button= returnsicstructplatform_driverrk28_AD_button_driver= = = = init returnsicvoid exit MODULE_DESCRIPTION(rk28ADbuttonController三.AndroidKernel MODULE_DESCRIPTIO

36、N(rk28ADbuttonController三.AndroidKernel 1.PlatformDeviceandplatform是一個虛擬總線,相比PCI,USB,它主要用于描述SOC上的資源。platform資源有一個共同點,就是在CPU總線直接取址。platform管理,在驅(qū)動程序中使用這些資源時通過platform device structbus_typeplatform_bus_type=.name=.dev_attrs=.match=.uevent=.pm=在2.6內(nèi)核中platform設(shè)備用結(jié)構(gòu)體platform_device來描述設(shè)備的資源信息,例如設(shè)備structpla

37、tform_device /*include/linux/platform_deviceh*/ const char * name;structdeviceu32;structresource*structresource constchar/*指向此資源的名稱。*flags constchar/*指向此資源的名稱。*flagsunsignedlong32位標(biāo)志值,unsignedlongflags; structresourceparent,sibling,資源的指針do_basic_setup()/*init/main.c 調(diào)用/driver/base下各子系統(tǒng)初始化函數(shù)-driver_i

38、nit(/*drivers/base/init.c 初始化驅(qū)動模型- - 作 -strncmp(pdev-name,drv-name,BUS_ID_SIZE), probe 成功則綁定該設(shè)備到該驅(qū)動. linuxinputsubsystem InputSubsystemmaindatastructinput_dev voidconstchar*name; const char *phys; const char *uniq; structinput_idid;unsigned long evbitNBITS(EV_MAX); unsigned long keybitNBITS(KEY_MAX)

39、; unsigned long relbitNBITS(REL_MAX); unsigned long absbitNBITS(ABS_MAX); unsignedlongmscbitNBITS(MSC_MAX); unsigned long ledbitNBITS(LED_MAX);unsignedlinuxinputsubsystem InputSubsystemmaindatastructinput_dev voidconstchar*name; const char *phys; const char *uniq; structinput_idid;unsigned long evbi

40、tNBITS(EV_MAX); unsigned long keybitNBITS(KEY_MAX); unsigned long relbitNBITS(REL_MAX); unsigned long absbitNBITS(ABS_MAX); unsignedlongmscbitNBITS(MSC_MAX); unsigned long ledbitNBITS(LED_MAX);unsignedlongunsignedunsignedlongvoid(*setkeycode)(struct input_dev Struct驅(qū)動層物理Input設(shè)備的基本數(shù)據(jù)Struct Evdev Stru

41、ct Mousedev StructEven ndler層邏輯 Input 設(shè)備 Structndler的ndler層,定義一個具體的EvenStruct用來創(chuàng)建驅(qū)動層 Dev 和 Handler鏈表的鏈表構(gòu)ndler層中分配,包含Evdev/Mousedev中。(*getkeycode)(struct input_dev structff_devicestructtimer_list0absABS_MAX+repREP_MAX+unsignedlongkeyNBITS(KEY_MAX); unsigned long ledNBITS(LED_MAX);unsignedlongunsigned

42、(*getkeycode)(struct input_dev structff_devicestructtimer_list0absABS_MAX+repREP_MAX+unsignedlongkeyNBITS(KEY_MAX); unsigned long ledNBITS(LED_MAX);unsignedlongunsignedlongabsmaxABS_MAX+absminABS_MAX+absfuzzABS_MAX+absflatABS_MAX+(*open)(struct input_dev *dev); void(*close)(structinput_dev*dev);(*fl

43、ush)(structinput_dev*dev,structfile type,structinput_handlestructmutexstructdevicedev; union structdevice struct list_headstruct list_head/* input_handle list節(jié)點structinput_handle void *private;constcharstructinput_devstructinput_handlerstructlist_headstructlist_headstructinput_handlervoidvoid(*event

44、)(structinput_handle*handle,(*connect)(structinput_handler*handler,structinput_devconststructinput_device_id*id); void (*disconnect)(struct input_handle *handle);structlist_headstructlist_headstructinput_handlervoidvoid(*event)(structinput_handle*handle,(*connect)(structinput_handler*handler,structi

45、nput_devconststructinput_device_id*id); void (*disconnect)(struct input_handle *handle);void(*start)(structinput_handleconststructfile_operations*fops; constcharconststructinput_device_idconststructinput_device_idstructstructinputsubsystem 輸入子系統(tǒng)由輸層( ore ),驅(qū)動層和事件處理層ore input 一個輸入事件,如鼠標(biāo)移動,鍵盤按鍵按下,joyst

46、ick ndleruserspace 的順序到達用戶空間傳給應(yīng)用程序(其中ore InputLayer ndler層的編程接口。Driver - (1)在內(nèi)核中,input_dev inputinput_dev_list :/- (1)在內(nèi)核中,input_dev inputinput_dev_list :/- |-|+-+-|+-+-|+-+-|+-+-|-+-+-|-.-|-+-+-在調(diào)|+-+-|+-+-|+-+-|-+-+-|-.-| | |input_dev_list|-|/-|+-|+-|+-+-|+-+-|+-+-|-+-|-.|/-|+-|+-|+-+-|+-+-|+-+-|-

47、+-|-.-| +-| +-| |+-/-| | |repREP_DELAY 和 structinput_handler*handler; const char *path;EV_SYN 置位, 即 所有設(shè) 備 都支持 這 個事件 . dev-repREP_DELAY 和 set_bit(EV_SYN,dev-*Ifdelayandperiodarepre-setbythedriver,then*ishandledbythedriveritselfandwetin .if(!dev-repREP_DELAY&!dev-repREP_PERIOD) dev-timer.data = (long)

48、 dev;dev-timer.function=input_repeat_key; dev-repREP_DELAY = 250;dev-repREP_PERIOD=如 果inputdevice沒有定義getkeycode和setkeycode.則將其賦默認值。還記得在鍵盤驅(qū)動中 的分析嗎這兩個操作函數(shù)就可以用來取鍵的掃描碼 和設(shè)置鍵的掃描碼。然后調(diào)用device_add()將input_dev中封裝的到if(!dev-dev-getkeycode=input_default_getkeycode; if (!dev-setkeycode)dev-setkeycode=f(dev-dev.bu

49、s_id, sizeof(dev-input%ld,(unsignedlong)atomic_inc_return(&input_no)-1); error = device_add(&dev-dev);ifreturnpath=kobject_get_path(&dev-dev.kobj,GFP_KERNEL); k(KERN_INFO input: %s as %sn,dev-name?dev-name:Unspecifieddevice,path?path:N/A); error = mutex_lock_if (error) return error;這 里就是重點了。將 input

50、device 掛到 input_dev_list 鏈表上然后,對每一個掛在 input_handler_list handler input_attach_handler().在這里的情況有好比設(shè)備模型中的 input_handler_list 上。面的分析中曾分析過。Input_device 的 evbit list_add_tail(&dev-node, &input_dev_list); list_for_each_entry(handler,&input_handler_list,node) input_attach_handler(dev, handler); returninput

51、_attach_handler(structinput_devstructinput_handlerconststructinput_device_idiflist_add_tail(&dev-node, &input_dev_list); list_for_each_entry(handler,&input_handler_list,node) input_attach_handler(dev, handler); returninput_attach_handler(structinput_devstructinput_handlerconststructinput_device_idif

52、(handler-blacklist&input_match_device(handler-blacklist,dev) return -ENODEV;id=input_match_device(handler-id_table,dev); if (!id)return-error=handler-ndler,dev,if(error&error!=-k(KERN_ERRinput: failed to attach handler %s to device %s, error:%dn,handler-name,kobject_name(&dev-dev.kobj),error);return

53、icconststructinput_device_id*input_match_device(constinput_device_id*id,structinput_devid-flags id-flags 的匹配項了.MATCH_BIT宏的定義可以看出。只有當(dāng)iputdeviceinpu ndler的id成 員在evbitkeybit,swbitevbit,keybitswbit.id 中的下一項進行比較.for(;id-flags|id-driver_info;id+)id-flags INPUT_DEVICE_ID_MATCH_BUSinputdevice和ndler的總線類型if(i

54、d-flags&INPUT_DEVICE_ID_MATCH_BUS) if (id-bustype != dev-id.bustype)INPUT_DEVICE_ID_MATCH_VENDOR , INPUT_DEVICE_ID_MATCH_PRODUCT 分別要求設(shè)備廠商。設(shè)備號和設(shè)備版本handle blacklist blacklist dev-id 匹配成功過后再來匹配 handle-id 和 dev-id 中的數(shù)據(jù)。如果匹配成功,則調(diào)用if(id-flags&INPUT_DEVICE_ID_MATCH_VENDOR) if (id-vendor != dev-id.vendor)if

55、(id-flags&INPUT_DEVICE_ID_MATCH_PRODUCT) if (id-product != duct)if(id-flags&)if(id-!=dev-MATCH_BIT(evbit, if(id-flags&INPUT_DEVICE_ID_MATCH_VENDOR) if (id-vendor != dev-id.vendor)if(id-flags&INPUT_DEVICE_ID_MATCH_PRODUCT) if (id-product != duct)if(id-flags&)if(id-!=dev-MATCH_BIT(

56、evbit, EV_MAX); MATCH_BIT(, KEY_MAX);MATCH_BIT(relbit, REL_MAX); MATCH_BIT(absbit,ABS_MAX); MATCH_BIT(ledbit, LED_MAX);MATCH_BIT(sndbit, it, MATCH_BIT(swbit, returnreturnMATCH_BIT 宏的定義如下#defineMATCH_BIT(bit,max)for(i=0;ibiti & dev-biti) != id-biti) break;if(i!=BITS_TO_LONGS(max) 一類新的 ndler已Devicendl

57、erConnect函數(shù)確定是否需要創(chuàng)建新的設(shè)備節(jié)點input_register_handler(structinput_handlerstructinput_dev*dev; retval = mutex_lock_if (retval)return retval; if (handler-fops != NULL) handler-minor input 設(shè)備節(jié)點的次設(shè)備號.handler-minor input_table中.input_talbe的作用if(input_tablehandler-minor5)retval=-gotoinput_tablehandler-minor5=ha

58、ndler input_handler_list 中 list_add_tail(&handler-node,retval=-gotoinput_tablehandler-minor5=handler input_handler_list 中 list_add_tail(&handler-node,&input_handler_list);將其與掛在input_dev_list中的input device匹配.這個過程和input device有相似的list_for_each_entry(dev, &input_dev_list, node) return retval;input_regi

59、ster_handle(structinput_handlestructinput_handler*handler=handle-handler; struct input_dev *dev = handle-dev;Wetakedev-mutexheretopreventraceerror = mutex_lock_if (error)returnlist_add_tail_rcu(&handle-d_node,&dev-h_list); *Sinceweareedtobecalledfrom-whichismutuallyexclusivewith-wecantberacingwith*a

60、ndsoockisnotneededhandleinput device的h_list鏈表上.handlehandler的hlist鏈 表上.handler 定義了start 函數(shù),將調(diào)用之. returninputdevice,handlerhandleinputdevice,handlerhandle是怎么關(guān)聯(lián)起來的了.ndler ndler直觀起見,物理設(shè)備用戶程序通過ndler 層創(chuàng)建的設(shè)備節(jié)點的Open,read,write 等函數(shù)打用戶程序通過ndler 層創(chuàng)建的設(shè)備節(jié)點的Open,read,write 等函數(shù)打開和讀寫OpenndlerOpen和該類型設(shè)備相關(guān)的通用事務(wù),比如初始

溫馨提示

  • 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. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。

評論

0/150

提交評論