成人国产在线小视频_日韩寡妇人妻调教在线播放_色成人www永久在线观看_2018国产精品久久_亚洲欧美高清在线30p_亚洲少妇综合一区_黄色在线播放国产_亚洲另类技巧小说校园_国产主播xx日韩_a级毛片在线免费

資訊專欄INFORMATION COLUMN

高級驅(qū)動——(驅(qū)動所有按鍵)

JessYanCoding / 3605人閱讀

摘要:我們用一種更為高級的方法去驅(qū)動所有的按鍵理論上按鍵最多可以驅(qū)動個,但是我的板子只有三個按鍵所以現(xiàn)在只能驅(qū)動三個,但是驅(qū)動三個和驅(qū)動個都是一樣的。

我們用一種更為高級的方法去驅(qū)動所有的按鍵————理論上按鍵最多可以驅(qū)動768個,但是我的板子只有三個按鍵
所以現(xiàn)在只能驅(qū)動三個,但是驅(qū)動三個和驅(qū)動768個都是一樣的。
首先我們要利用起設(shè)備樹文件了,如果不用設(shè)備樹的話,你就得一個一個的去驅(qū)動,雖然你可以在一個模塊上完成所有的按鍵驅(qū)動,但是要是真的驅(qū)動768個按鍵,那么你估計能寫上萬行代碼。你要跟以前的方法一樣,每一個按鍵都要去實例化設(shè)備,然后獲取中斷,地址,…這些信息,然后再處理這些信息。
但是如果你用了設(shè)備樹,我直接在設(shè)備樹上寫好這些信息,到時候你拿的去用就可以了。
并且你直接整一個for循環(huán),它就自動把768個設(shè)備信息給你全部拿過來了,豈不爽哉!!
那就讓我們來領(lǐng)略一下設(shè)備樹的魅力:
————————————————————————————————————————————————
驅(qū)動所有按鍵第一步:
編寫設(shè)備樹:
我們之前也編寫過,這里我們詳細(xì)的講一下:(設(shè)備樹就是用來存儲設(shè)備信息的)
首先是在根節(jié)點下創(chuàng)建了一個屬于我們的設(shè)備叫:key_int_node.
我們要驅(qū)動三個按鍵,所以在這個我們的設(shè)備下面創(chuàng)建了三個子設(shè)備,代表我這設(shè)備由這三個設(shè)備共同組成。
要是你有一千個設(shè)備那么你也可以吧一千個設(shè)備寫里面組成你的設(shè)備。
好讓我們看一下每一個子設(shè)備下存儲了上面信息

```c在設(shè)備樹文件中設(shè)置這幾個元素:  key_int_node{            compatible = "test_key";            #address-cells = <1>;            #size-cells = <1>;            key_int@0 {                    key_name = "key2_power_eint";     //表示我這個子設(shè)備名字叫....自定義                    key_code = <116>;	              //設(shè)置這個子設(shè)備的鍵值,就是代表這個鍵是用來干嘛的,                    									//你可以隨便設(shè)你想讓它有上面功能都可以                    gpio = <&gpx1 1 0>;				//代表這個引腳在電路圖上是屬于gpx1_1引腳,后面可以讀這個引腳的值來獲                    								//取按鍵有沒有按下,就很方便                    reg = <0x11000C20 0x18>;			//物理地址                    interrupt-parent = <&gpx1>;			//表示中斷繼承了gpx1                    interrupts = <1 0>;					//代表是gpx1_1的中斷,后面根據(jù)節(jié)點獲取中斷號就是            };            key_int@1 {                    key_name = "key3_vup_eint";                    key_code = <115>;                    gpio = <&gpx1 2 0>;                    reg = <0x11000C20 0x18>;                    interrupt-parent = <&gpx1>;                    interrupts = <2 0>;            };            key_int@2 {                    key_name = "key4_vdown_eint";                    key_code = <114>;                    gpio = <&gpx3 2 0>;                    reg = <0x11000C60 0x18>;                    interrupt-parent = <&gpx3>;                    interrupts = <2 0>;            };	};		好了第一步完成,你可以根據(jù)芯片手冊,把所有的按鍵信息寫進(jìn)去

——————————————————————————————————————
驅(qū)動所有按鍵第二步:
接下來我們就要編寫設(shè)備模塊代碼了
1)首先就是日常搭框架
2)然后就是想辦法從設(shè)備樹上把這些我們寫的文件信息拿過來。

我們采用了我通用的設(shè)備信息結(jié)構(gòu)體,
然后我用一個數(shù)組去實例化它,那么我只要一個數(shù)組的名字我就可以存儲并且找到所有的設(shè)備信息了。

struct  key_desc{	char *name;	int key_code;	int irqno;	int gpio_num;	void *regbase;	struct device_node *cnp;	};struct key_desc *all_dev[KEY_NOM];

那我們有這樣一個結(jié)構(gòu)體數(shù)組了,那我還是沒有從設(shè)備樹上獲取到信息啊。
別急——我們寫一個函數(shù),直接對著設(shè)備樹就是 —拿來吧你
我們需要一個中介去連接我們的設(shè)備樹,和用來存儲信息的結(jié)構(gòu)體:這個中介就是: struct device_node *cnp; 這是一個設(shè)備節(jié)點在結(jié)構(gòu)體中已經(jīng)定義了
首先我們像獲取中斷號一樣,從設(shè)備樹上獲取到節(jié)點,但是這個節(jié)點,不是我們要的兒子節(jié)點。所有我們得獲取到子節(jié)點點,并且,
要一個設(shè)備結(jié)構(gòu)體數(shù)組對應(yīng)一個子節(jié)點信息:

void get_allirqno(void){	//從設(shè)備樹上獲取設(shè)備節(jié)點	struct device_node *np = of_find_node_by_path("/key_int_node");	if(np == NULL){		printk("find_node error/n");		return 0;	}	struct  device_node*lcnp;   //用來記錄節(jié)點的,到時候再賦給每一個的all_dev的cnp		//要獲取的節(jié)點的上一個節(jié)點,這樣就可以通過上一個節(jié)點的位置獲取到我要獲取的節(jié)點的位置	 struct device_node *prev = NULL;	int i=0;		do{					if(lcnp != NULL){				all_dev[i++].cnp = lcnp;//將當(dāng)前的節(jié)點記錄下來			}			prev = lcnp; //把當(dāng)前的設(shè)置位prev		}while(of_get_next_child(np, prev) != NULL);								}

這樣我們就可以通過設(shè)備結(jié)構(gòu)體數(shù)組中的子節(jié)點與設(shè)備樹建立了連接。

——————————————————————————————————————————————————
接下來是驅(qū)動第三步:
完成模塊裝載入口
我們之前在模塊裝載路口做了三件事:
1,分配一個input device對象
2, 初始化input device對象
3,注冊input device對象
我們現(xiàn)在也是做這三件事;
1)實例化一個輸入設(shè)備對象,并發(fā)分配空間,和部分初始化
struct input_dev *inputdev; //實例化一個輸入設(shè)備對象
inputdev = input_allocate_device(void);
2)可以添加設(shè)備信息
3)調(diào)用我們的獲取信息的函數(shù)————因為我們接下來要用到這些在設(shè)備樹上的信息

4)初始化input device對象
這里需要初始化倆個:
一個是按鍵類型
//初始化inputdevice對象—設(shè)為按鍵類型信息
_set_bit(EV_KEY, inputdev->evbit);
還有就是按鍵的具體信息:
但是不要忘了,我們有很多很多的按鍵,所以我們要利用我們之前的設(shè)備結(jié)構(gòu)體數(shù)組中的子節(jié)點
然后利用for循環(huán),把設(shè)備樹上的其它對應(yīng)信息讀到對應(yīng)的設(shè)備結(jié)構(gòu)體數(shù)組中去
我們還要
1)設(shè)置鍵值具體信息:所以要拿到對應(yīng)的鍵值
of_property_read_u32(cnp,“key_code”, &code
2)申請對應(yīng)中斷:所以要拿到中斷號
irqno = irq_of_parse_and_map(cnp, 0)
3)我們還可以打印設(shè)備名字用來區(qū)分設(shè)備
of_property_read_string(cnp, “key_name”, &key_name);

這樣我們就完成了,設(shè)備的初始化以及中斷申請
4)注冊設(shè)備:
我們申請了設(shè)備(由很多子設(shè)備組成的大設(shè)備)就要注冊進(jìn)去,讓內(nèi)核幫我們匹配
input_register_device(inputdev);
——————————————————————————————
接下來是驅(qū)動第三步:
那我們拿到數(shù)據(jù)了,怎么把按鍵的值傳出去呢?
,我們寫在中斷處理函數(shù)里面,但是我有幾百個設(shè)備,我只用了一個中斷處理函數(shù)我怎么區(qū)分你按的是什么中斷?
首先我們在申請中斷的時候就會把,設(shè)備信息結(jié)構(gòu)體指針傳個中斷處理函數(shù)。
我們直接可以區(qū)分不同的鍵值。
并且我們還可以直接根據(jù)設(shè)備樹上的gpionum直接去讀引腳的數(shù)據(jù)判斷,是否被按下————nice
int gpionum = of_get_named_gpio(pdesc->cnp, “gpio”, 0);
//直接通過gpio獲取按鍵狀態(tài)
int value = gpio_get_value(gpionum);
——————————————————總的代碼————————————————————

#include #include #include #include #include #include #include #include #define KEY_NUMS 3#define KEY_NOM 3#define IRQFLAGS IRQF_TRIGGER_FALLING|IRQF_TRIGGER_RISINGstruct input_dev *inputdev;  //實例化一個輸入設(shè)備對象struct  key_desc{	char *name;	int key_code;	int irqno;	int gpio_num;	void *regbase;	struct device_node *cnp;	};struct key_desc all_dev[KEY_NOM];irqreturn_t  input_key_irq_handler(int irqno, void *devid){		//區(qū)分不同的按鍵	struct key_desc *pdesc = (struct key_desc *)devid;	int gpionum = of_get_named_gpio(pdesc->cnp, "gpio", 0);	//直接通過gpio獲取按鍵狀態(tài)	int value = gpio_get_value(gpionum);	if(value){//抬起				input_report_key(inputdev, pdesc->key_code, 0);		input_sync(inputdev);//上報數(shù)據(jù)結(jié)束				}else{		input_report_key(inputdev, pdesc->key_code, 1);		input_sync(inputdev);//上報數(shù)據(jù)結(jié)束}return IRQ_HANDLED;}void get_allirqno(void){	//從設(shè)備樹上獲取設(shè)備節(jié)點	struct device_node *np = of_find_node_by_path("/key_int_node");	if(np == NULL){		printk("find_node error/n");		return 0;	}	struct  device_node*lcnp;   //用來記錄節(jié)點的,到時候再賦給每一個的all_dev的cnp		//要獲取的節(jié)點的上一個節(jié)點,這樣就可以通過上一個節(jié)點的位置獲取到我要獲取的節(jié)點的位置	 struct device_node *prev = NULL;	int i=0;		do{					if(lcnp != NULL){				all_dev[i++].cnp = lcnp;//將當(dāng)前的節(jié)點記錄下來			}			prev = lcnp; //把當(dāng)前的設(shè)置位prev		}while(of_get_next_child(np, prev) != NULL);								}static int __init akey_dev_init(void){	//編寫輸入子系統(tǒng)代碼	/*		1,分配一個input device對象		2, 初始化input  device對象		3,注冊input device對象	*/	//1、給實例化的輸入設(shè)備對象分配空間并部分初始化	inputdev = input_allocate_device(void);	if(inputdev == NULL)	{		printk(KERN_ERR "input_allocate_device error/n");		return -ENOMEM;	}	//添加設(shè)備信息/sys/class/input/eventx/device/	//自定義	inputdev->name = "input key";	inputdev->phys = "key/input/input0";	inputdev->uniq = "simple key0 for 4412";	inputdev->id.bustype = BUS_HOST;	inputdev->id.vendor =0x1234 ;	inputdev->id.product = 0x8888;	inputdev->id.version = 0x0001;	get_allirqno();		//初始化inputdevice對象---設(shè)為按鍵類型信息	_set_bit(EV_KEY, inputdev->evbit);	//利用設(shè)備樹多個獲取信息	int i;	for(i=0;i<KEY_NOM;++i){			struct device_node *cnp = all_dev[i].cnp;   //這個cnp記錄了每個設(shè)備的節(jié)點	//獲取鍵值	int code;	of_property_read_u32(cnp,"key_code", &code);	_set_bit(code, inputdev->keybit); //將從設(shè)備樹上獲取的鍵值設(shè)置位鍵值數(shù)據(jù)code	 all_dev[i].key_code = code; //把code信息記錄到每個子設(shè)備的結(jié)構(gòu)體中	//獲取中斷號	int irqno;	irqno = irq_of_parse_and_map(cnp, 0);	all_dev->irqno = irqno;	//獲取按鍵name	char *key_name ;	of_property_read_string(cnp, "key_name",  &key_name);	all_dev[i].name = key_name;	//申請中斷		ret = request_irq(irqno, input_key_irq_handler, irqflags, 					key_name, &all_dev[i]);		if(ret != 0)		{			printk("request_irq error/n");			goto err_1;			}		}	//注冊設(shè)備	ret = input_register_device(inputdev);	if(ret != 0)	{		printk(KERN_ERR "input_register_device error/n");		goto err_0;	}	return 0;err_1:	input_unregister_device(inputdev);err_0:	input_free_device(inputdev);}static int __exit akey_dev_exit(void){	int i;	for(i=0; i<KEY_NOM; i++)		free_irq(all_dev[i].irqno, &all_dev[i]);			input_unregister_device(inputdev);	input_free_device(inputdev);}module_init(akey_dev_init);module_exit(akey_dev_exit);MODULE_LICENSE("GPL");

—————————————————————應(yīng)用程序代碼———————————————————————

#include #include #include #include #include #include #include #include int main(void){	int fd;	int ret;	struct input_event event;		fd = open("/dev/input/event1", O_RDWR);	if(fd < 0)	{		perror("open");		exit(1);	}	while(1)	{		ret = read(fd, &event, sizeof(struct input_event));		if(ret < 0)		{			perror("read");			exit(1);		}		if(event.type == EV_KEY){					switch(event.code){				case KEY_POWER:					if(event.value){ //按下						printf("__APP_USER__ :  power pressed/n");					}else{						printf("__APP_USER__ :  power up/n");					}					break;				case KEY_VOLUMEDOWN:					if(event.value){ //按下						printf("__APP_USER__ :  vollum dowm  pressed/n");					}else{						printf("__APP_USER__ :  vollum dowm up/n");					}					break;				case KEY_VOLUMEUP:					if(event.value){ //按下						printf("__APP_USER__ :  vollum up  pressed/n");					}else{						printf("__APP_USER__ :  vollum up up/n");					}					break;				default:					printf("error");			}		}			}	close(fd);	return 0;}

文章版權(quán)歸作者所有,未經(jīng)允許請勿轉(zhuǎn)載,若此文章存在違規(guī)行為,您可以聯(lián)系管理員刪除。

轉(zhuǎn)載請注明本文地址:http://systransis.cn/yun/121073.html

相關(guān)文章

  • ??爬蟲+自動化利器 selenium 之自學(xué)成才篇(一)??

    文章目錄 selenium 簡介selenium安裝安裝瀏覽器驅(qū)動確定瀏覽器版本下載驅(qū)動 定位頁面元素打開指定頁面id 定位name 定位class 定位tag 定位xpath 定位css 定位link 定位partial_link 定位 瀏覽器控制修改瀏覽器窗口大小瀏覽器前進(jìn)&后退瀏覽器刷新瀏覽器窗口切換常見操作 鼠標(biāo)控制單擊左鍵單擊右鍵雙擊拖動鼠標(biāo)懸停 鍵盤控制 seleni...

    james 評論0 收藏0
  • YOOGA 40藍(lán)牙雙模焊接PCB簡要說明

    摘要:鍵盤使用說明索引均為出廠默認(rèn)值升級固件軟件支持一些常見問題解答電池開關(guān)電池插座轉(zhuǎn)接小板連接首次使用測試步驟藍(lán)牙和切換鍵盤默認(rèn)層默認(rèn)觸發(fā)層的鍵配置的功能默認(rèn)功能層配置的功能默認(rèn)的快捷鍵藍(lán)牙配對藍(lán)牙參數(shù)藍(lán)牙地址管理升級固件 ...

    不知名網(wǎng)友 評論0 收藏0
  • 事件驅(qū)動模型

    摘要:應(yīng)用程序的模型是基于一個事件驅(qū)動的協(xié)作式多任務(wù)模型。兩個數(shù)據(jù)字段均不包含數(shù)據(jù)的事件有和。僅在短數(shù)據(jù)字段中包含數(shù)據(jù)的典型事件有,僅在長數(shù)據(jù)字段中包含數(shù)據(jù)的典型事件有和。 BREW應(yīng)用程序的模型是基于一個事件驅(qū)動的協(xié)作式多任務(wù)模型。事件處理機(jī)制的核心問題是程序應(yīng)該只處理需要的事件,對于不...

    MiracleWong 評論0 收藏0
  • 【Python爬蟲】4萬字,詳解selenium從入門到實戰(zhàn)【錯過再無】

    摘要:難在哪里根據(jù)上面的標(biāo)簽需要定位最后一行標(biāo)簽,以下列出了四種方式,定位的方式多樣并不唯一,使用時根據(jù)情況進(jìn)行解析即可。加入每日一練我們使用并指明標(biāo)簽內(nèi)全部文本即可定位。 ...

    shiyang6017 評論0 收藏0

發(fā)表評論

0條評論

最新活動
閱讀需要支付1元查看
<