1. 程式人生 > >linux 輸入子系統之電阻式觸控式螢幕驅動

linux 輸入子系統之電阻式觸控式螢幕驅動

一、輸入子系統情景回憶ING......

在Linux中,輸入子系統是由輸入子系統裝置驅動層、輸入子系統核心層(Input Core)和輸入子系統事件處理層(Event Handler)組成。其中裝置驅動層提供對硬體各暫存器的讀寫訪問和將底層硬體對使用者輸入訪問的響應轉換為標準的輸入事件,再通過核心層提交給事件處理層;而核心層對下提供了裝置驅動層的程式設計介面,對上又提供了事件處理層的程式設計介面;而事件處理層就為我們使用者空間的應用程式提供了統一訪問裝置的介面和驅動層提交來的事件處理。所以這使得我們輸入裝置的驅動部分不在用關心對裝置檔案的操作,而是要關心對各硬體暫存器的操作和提交的輸入事件。下面用圖形來描述一下這三者的關係吧!



二、S3C2440觸控式螢幕介面預熱ING......

S3C2440提供的觸控式螢幕介面有4種處理模式,分別是:正常轉換模式、單獨的X/Y位置轉換模式、自動X/Y位置轉換模式

和等待中斷模式,對於在每種模式下工作的要求,請詳細檢視資料手冊的描述。本驅動例項將採用自動X/Y位置轉換

模式和等待中斷模式。

三、tq2440_ts.c原始碼分析

1.入口函式,為了方便分析,清晰架構,這裡省去了返回值的判斷,最詳細的還請參考後面的原始碼。

[cpp]  view plain  copy
 print ?
  1. static int __init tq2440ts_init(void)  
  2. {  
  3.     struct input_dev *input_dev;  
  4.   
  5.     /* 獲取ADC時鐘,使能時鐘(CLKCON[15]) 
  6.      * ADC(&Touch Screen) [15], Control PCLK into ADC block.
     
  7.      */  
  8.     adc_clock = clk_get(NULL, "adc");  
  9.     clk_enable(adc_clock);  
  10.   
  11.     /* ADCCON暫存器地址:0x58000000 */  
  12.     base_addr=ioremap(S3C2410_PA_ADC,0x20);   
  13.   
  14.     /* 使能預分頻,預分頻係數PRSCVL為0xff */  
  15.     iowrite32(S3C2410_ADCCON_PRSCEN | S3C2410_ADCCON_PRSCVL(0xFF),base_addr+S3C2410_ADCCON);  
  16.       
  17.     /* ADCDLY = 0xffff */  
  18.     iowrite32(0xffff,  base_addr+S3C2410_ADCDLY);  
  19.       
  20.     /* 進入等待按下中斷模式 */  
  21.     iowrite32(WAIT4INT(0), base_addr+S3C2410_ADCTSC);  
  22.   
  23.     /* 分配一個input_dev結構體 */  
  24.     input_dev = input_allocate_device();      
  25.   
  26.     /* 初始化輸入裝置,即input_dev成員 */  
  27.     dev = input_dev;  
  28.   
  29.     /* 支援同步事件、按鍵事件、絕對位移事件 */  
  30.     dev->evbit[0] = BIT(EV_SYN) | BIT(EV_KEY) | BIT(EV_ABS);  
  31.   
  32.     /* 支援按鍵類中的觸控式螢幕點選 */  
  33.     dev->keybit[BITS_TO_LONGS(BTN_TOUCH)] = BIT(BTN_TOUCH);  
  34.   
  35.     /* 設定觸控式螢幕的X座標、Y座標、壓力 */  
  36.     input_set_abs_params(dev, ABS_X, 0, 0x3FF, 0, 0);  /* Resolution: 10-bit,0x3ff即10位 */  
  37.     input_set_abs_params(dev, ABS_Y, 0, 0x3FF, 0, 0);  
  38.     input_set_abs_params(dev, ABS_PRESSURE, 0, 1, 0, 0);  
  39.   
  40.     /* 下面這些資訊在驅動掛載後在/proc/bus/input/devices中看到 */  
  41.     dev->name = tq2440ts_name;  
  42.     dev->id.bustype = BUS_RS232;  
  43.     dev->id.vendor = 0xDEAD;  
  44.     dev->id.product = 0xBEEF;  
  45.     dev->id.version = S3C2410TSVERSION;  
  46.   
  47.     /* 分別申請ADC、TC中斷,在ADC中斷裡使用了IRQF_SHARED 
  48.      * 共享中斷標誌,因為在ADC驅動裡也使用了ADC中斷  
  49.      */  
  50.     request_irq(IRQ_ADC, stylus_action, IRQF_SHARED|IRQF_SAMPLE_RANDOM, tq2440ts_name, dev)  
  51.     request_irq(IRQ_TC, stylus_updown, IRQF_SAMPLE_RANDOM, tq2440ts_name, dev)  
  52.   
  53.     printk(KERN_INFO "%s successfully loaded\n", tq2440ts_name);  
  54.   
  55.     /* 將觸控式螢幕輸入設備註冊到輸入子系統 */  
  56.     input_register_device(dev);  
  57.     return 0;  
  58. }  

驅動載入函式tq2440ts_init主要做了以下一些事情:獲取ADC時鐘,使能ADC時鐘,對映ADC的IO地址,使能預分頻、設ADCDLY暫存器,進入等待按下中斷模式,分配一個input_dev結構體,初始化input_dev結構體成員,如:支援哪類事件、支援這類事件的哪些事件,申請ADC、TC中斷,最後註冊一個觸控式螢幕輸入裝置。萬事具備,只欠東風。載入函式準備好一切條件後,就當你觸控觸控式螢幕了,當觸控式螢幕被觸控後,即被按下後,會進入觸控式螢幕中斷處理函式stylus_updown

[cpp]  view plain  copy  print ?
  1. /* 觸控式螢幕中斷服務程式,當觸控式螢幕按下或擡起時觸發執行 */  
  2. static irqreturn_t stylus_updown(int irq, void *dev_id)  
  3. {  
  4.     unsigned long data0;  
  5.     unsigned long data1;  
  6.     /* 用於判斷觸控式螢幕是按下還是擡起 */  
  7.     int updown;  
  8.   
  9.     /* ADC資源可以獲取,即上鎖 */  
  10.     if (down_trylock(&ADC_LOCK) == 0)  
  11.     {  
  12.         /* 標識觸控式螢幕資源可用 */  
  13.         OwnADC = 1;  
  14.   
  15.         /* 讀取AD轉換後的值,注意這次重點是讀出狀態 */  
  16.         data0 = ioread32(base_addr+S3C2410_ADCDAT0);  
  17.         data1 = ioread32(base_addr+S3C2410_ADCDAT1);  
  18.         updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));  
  19.   
  20.         if (updown)  
  21.         {  
  22.             /*  ADCDAT0[15] = 0,則updown = 1,此時表示按下狀態 
  23.              *  那麼呼叫touch_timer_fire函式啟動ADC轉換 
  24.              */  
  25.             touch_timer_fire(0);  
  26.         }  
  27.         else  
  28.         {  
  29.             /* 如果是擡起狀態,就結束這次的操作,並釋放ADC資源的佔用,即解鎖 */  
  30.             OwnADC = 0;  
  31.             up(&ADC_LOCK);  
  32.         }  
  33.     }  
  34.     return IRQ_HANDLED;  
  35. }  
stylus_updown函式首先獲得ADC資源,因為在ADC驅動裡也有可能使用了ADC資源,然後獲得觸控式螢幕狀態,判斷觸控式螢幕是被按下還是被擡起,如果是被按下,那麼呼叫touch_timer_fire函式啟動ADC轉換;如果是擡起狀態,就結束這次的操作,並釋放ADC資源的佔用。
touch_timer_fire函式分析

[cpp]  view plain  copy  print ?
  1. static void touch_timer_fire(unsigned long data)  
  2. {  
  3.     unsigned long data0;  
  4.     unsigned long data1;  
  5.     int updown;  
  6.   
  7.     /* 讀取AD轉換後的值,注意這次重點是讀出狀態 */  
  8.     data0 = ioread32(base_addr+S3C2410_ADCDAT0);  
  9.     data1 = ioread32(base_addr+S3C2410_ADCDAT1);  
  10.     updown = (!(data0 & S3C2410_ADCDAT0_UPDOWN)) && (!(data1 & S3C2410_ADCDAT0_UPDOWN));  
  11.   
  12.     if (updown) {  
  13.         /* 如果是按下狀態,並且ADC已經轉換,就報告事件和資料 */  
  14.         if (count != 0)  
  15.         {  
  16.             long tmp;  
  17. 相關推薦

    linux 輸入子系統電阻觸控式螢幕驅動

    一、輸入子系統情景回憶ING...... 在Linux中,輸入子系統是由輸入子系統裝置驅動層、輸入子系統核心層(Input Core)和輸入子系統事件處理層(Event Handler)組成。其中裝置驅動層提供對硬體各暫存器的讀寫訪問和將底層硬體對使用者輸入訪問的響應轉換為標準的輸入事件,再

    linux驅動由淺入深系列:輸入子系統二(編寫一個gpio_key驅動)

    本系列導航: 在上一篇文章中我們大致瞭解了linux input subsystem的功能及應用層的使用,本文我們一起來看一看驅動程式碼的編寫。接下來一篇,計劃寫一下應用層如何模擬按鍵訊息,產生與按下實際按鍵相同的效果。 在“linux驅動由淺入深系列:驅動程式的基

    linux驅動由淺入深系列:輸入子系統三(應用層模擬input_event)

    本系列導航: 在上一篇文章中編寫了gpio_key的驅動,可以看到每次gpio_key按下會上報event到/dev/input /event7節點。其實在應用層是可以完全模擬出這個按鍵過程的,原理是向EV_KEY型別的eventX訊息節點write event將

    Android驅動 Linux Input子系統TP——A/B(Slot)協議

    翻譯 莫名其妙 屬性 設備 事件 ng- 點數據 希望 top utm_source=tuicool&utm_medium=referral">點擊打開鏈接將A/B協議這部分單獨拿出來說一方面是由於這部分內容是比較easy忽視的。周圍大多數用到input子系統的

    Linux 輸入子系統分析 Linux輸入子系統分析(詳解)

    為什麼要引入輸入子系統? 在前面我們寫了一些簡單的字元裝置的驅動程式,我們是怎麼樣開啟一個裝置並操作的呢? 一般都是在執行應用程式時,open一個特定的裝置檔案,如:/dev/buttons 1 ..... 2 int main(int argc, char **argv) 3 {

    Linux時間子系統八:動態時鐘框架(CONFIG_NO_HZ、tickless)

    sleep file rup linux時間 load 曾經 大致 獲取 conf 在前面章節的討論中,我們一直基於一個假設:Linux中的時鐘事件都是由一個周期時鐘提供,不管系統中的clock_event_device是工作於周期觸發模式,還是工作於單觸發模式,也不管定時

    Linux時間子系統四:定時器的引擎:clock_event_device

    到來 開始 register 工作模式 統一 10個 net 說過 序列 早期的內核版本中,進程的調度基於一個稱之為tick的時鐘滴答,通常使用時鐘中斷來定時地產生tick信號,每次tick定時中斷都會進行進程的統計和調度,並對tick進行計數,記錄在一個jiffies變量

    Linux時間子系統六:高精度定時器(HRTIMER)的原理和實現

    3.4 size 屬於 running return repr 而是 復雜度 ctu 上一篇文章,我介紹了傳統的低分辨率定時器的實現原理。而隨著內核的不斷演進,大牛們已經對這種低分辨率定時器的精度不再滿足,而且,硬件也在不斷地發展,系統中的定時器硬件的精度也越來越高,這也給

    Linux時間子系統七:定時器的應用--msleep(),hrtimer_nanosleep()

    get 關系 警告 mov signed num wakeup sch switch 我們已經在前面幾章介紹了低分辨率定時器和高精度定時器的實現原理,內核為了方便其它子系統,在時間子系統中提供了一些用於延時或調度的API,例如msleep,hrtimer_nanosleep

    Linux時間子系統二:Alarm Timer

    數據 類型 oid mtime orm 分別是 type mon 超時 一、前言 嚴格來講Alarm Timer也算POSIX Timer一部分,包含兩種類型CLOCK_REALTIME_ALARM和CLOCK_BOOTTIME_ALARM。分別是在CLOCK_REALTI

    linux 輸入子系統

    gpo sdn font width idt hid -s OS div 1、分層結構     用戶層     事件處理層     輸入核心層     設備驅動層 2、步驟: https://blog.csdn.net/woshidahuaidan2011/art

    linux音訊子系統alsa asoc層

    ALSA SoC層概述 ALSA片上系統(ASoC)層的總體專案目標是為嵌入式片上系統處理器(例如pxa2xx,au1x00,iMX等)和行動式音訊編解碼器提供更好的ALSA支援。在ASoC子系統之前,核心對SoC音訊有一些支援,但它有一些限制: - 編解碼器驅動程式通常與底層SoC CPU緊密

    輸入子系統events訊息資料傳遞

    參考連結:http://book.51cto.com/art/200803/66870.htm 在Linux核心中,input裝置用input_dev結構體描述,使用input子系統實現輸入裝置驅動的時候,驅動的核心工作是向系統報告按鍵、觸控式螢幕、鍵盤、滑鼠等輸入事件(event,通過in

    Linux輸入子系統

    為何需要input子系統 Linux系統支援的許多裝置,都是輸入性的裝置,如按鍵、觸控式螢幕、鍵盤、滑鼠。本質上都是一個個的字元裝置驅動,Linux系統為這些裝置統一管理實現了input子系統,方便驅動和應用的開發。 input子系統軟體架構 linux輸

    Linux輸入子系統:事件的編碼 -- event-codes.txt

    輸入系統協議用型別types和編碼codecs來表示輸入裝置的值並用此來通知使用者空間的應用程式。這篇文件對這些型別和編碼進行了說明並且指出什麼時候和如何使用這些型別和編碼。  一個單一的硬體事件可以產生多個輸入事件,每個輸入事件包含一個單一資料項的新的資料值。EV_SYN

    linux輸入子系統——按鍵

    轉載linux之輸入子系統分析 實現步驟 1、定義、分配一個input-dev結構體 static struct input_dev *buttons_dev; buttons_dev=input_allocate_device(); 2、設定 buttons_dev->n

    Linux網路子系統---- PHY 配置

     MII即媒體獨立介面,也叫介質無關介面。 它包括一個數據介面,以及一個MAC和PHY之間的管理介面(圖1)。 資料介面包括分別用於傳送器和接收器的兩條獨立通道。每條通道都有自己的資料、時鐘和控制訊號。MII資料介面總共需16個訊號。 管理介面是個雙訊號介面:一個是時鐘訊

    S5PV210 Linux 模擬SPI方式控制ADS7846觸控式螢幕驅動

    /************************************************************************************** * ads7846 touch screen ads.c * Light < [email&

    Linux時間子系統三:時間的維護者:timekeeper

    本系列文章的前兩節討論了用於計時的時鐘源:clocksource,以及核心內部時間的一些表示方法,但是對於真實的使用者來說,我們感知的是真實世界的真實時間,也就是所謂的牆上時間,clocksource只能提供一個按給定頻率不停遞增的週期計數,如何把它和真實的牆上時間相關聯

    Android輸入子系統應用程式註冊訊息監聽過程分析

    應用程式註冊訊息監聽過程分析 CPP層InputManagerService啟動後就需要監聽按鍵輸入了,當InputManagerService監聽到鍵盤輸入的事件後就需要分發鍵盤事件,但是分發給誰呢?這裡首先應該是分發給當前啟用的Window視窗,但是當前啟