日韩无码专区无码一级三级片|91人人爱网站中日韩无码电影|厨房大战丰满熟妇|AV高清无码在线免费观看|另类AV日韩少妇熟女|中文日本大黄一级黄色片|色情在线视频免费|亚洲成人特黄a片|黄片wwwav色图欧美|欧亚乱色一区二区三区

RELATEED CONSULTING
相關(guān)咨詢
選擇下列產(chǎn)品馬上在線溝通
服務(wù)時(shí)間:8:30-17:00
你可能遇到了下面的問(wèn)題
關(guān)閉右側(cè)工具欄

新聞中心

這里有您想知道的互聯(lián)網(wǎng)營(yíng)銷解決方案
Linux設(shè)備驅(qū)動(dòng):按鍵輸入的實(shí)現(xiàn)(linux設(shè)備驅(qū)動(dòng)按鍵)

在Linux系統(tǒng)中,設(shè)備驅(qū)動(dòng)是一個(gè)非常重要的組件。同時(shí),作為一個(gè)Linux開(kāi)發(fā)者,熟練掌握設(shè)備驅(qū)動(dòng)的編寫是非常必要的。在本文中,我們將討論Linux設(shè)備驅(qū)動(dòng)的一種實(shí)現(xiàn):按鍵輸入。

為什么需要按鍵輸入驅(qū)動(dòng)?

在現(xiàn)代計(jì)算機(jī)系統(tǒng)中,特別是在一些嵌入式設(shè)備中,按鍵是一個(gè)極其重要的輸入設(shè)備。按鍵可以用于各種目的,例如啟動(dòng)或停止某個(gè)應(yīng)用程序,或者執(zhí)行某個(gè)操作。因此,對(duì)于我們的應(yīng)用程序或操作系統(tǒng)來(lái)說(shuō),需要一個(gè)可靠的驅(qū)動(dòng)程序來(lái)處理按鍵輸入事件。

按鍵輸入驅(qū)動(dòng)的實(shí)現(xiàn)

Linux內(nèi)核為我們提供了一些內(nèi)核接口和數(shù)據(jù)結(jié)構(gòu)以支持設(shè)備驅(qū)動(dòng)的編寫。最常用的數(shù)據(jù)結(jié)構(gòu)是input_dev結(jié)構(gòu)體,如下所示:

struct input_dev {

const char *name;

const struct input_id *id;

unsigned long evbit[NBITS(EV_CNT)];

unsigned long keybit[NBITS(KEY_CNT)];

unsigned long ledbit[NBITS(LED_CNT)];

unsigned long mscbit[NBITS(MSC_CNT)];

unsigned long relbit[NBITS(REL_CNT)];

unsigned long abit[NBITS(ABS_CNT)];

unsigned long ffbbit[NBITS(FF_CNT)];

unsigned long propbit[NBITS(INPUT_PROP_CNT)];

unsigned long quirk;

struct input_absinfo *absinfo;

struct device *dev;

struct input_mt_slot *mt;

};

在實(shí)際的按鍵輸入驅(qū)動(dòng)中,我們需要完成以下任務(wù):

1. 定義input_dev結(jié)構(gòu)體:我們需要指定輸入設(shè)備的名稱,以及支持的輸入事件類型和輸入事件所對(duì)應(yīng)的數(shù)據(jù)格式。

2. 注冊(cè)輸入設(shè)備:我們需要注冊(cè)輸入設(shè)備和它的事件處理函數(shù)。

3. 處理輸入事件:在輸入事件被注冊(cè)之后,我們需要編寫一個(gè)輸入事件處理函數(shù)來(lái)處理它。這個(gè)函數(shù)會(huì)被內(nèi)核自動(dòng)調(diào)用,以處理輸入設(shè)備生成的輸入事件。

在實(shí)現(xiàn)按鍵輸入驅(qū)動(dòng)之前,我們需要先了解一下Linux內(nèi)核輸入子系統(tǒng)提供的常見(jiàn)輸入事件類型:

EV_SYN:輸入事件的同步信號(hào)。

EV_KEY:按鍵事件。

EV_REL:相對(duì)運(yùn)動(dòng)事件(鼠標(biāo)滾輪)。

EV_ABS:絕對(duì)運(yùn)動(dòng)事件(鼠標(biāo)位置、觸摸屏,等等)。

EV_MSC:描述設(shè)備的狀態(tài)或模式。

EV_SW:開(kāi)關(guān)事件。

EV_LED:LED燈的開(kāi)關(guān)事件。

EV_SND:音頻事件。

EV_REP:用于自動(dòng)重復(fù)事件的時(shí)間設(shè)置。

EV_FF:力反饋事件。這可以用于游戲手柄的振動(dòng)反饋等功能。

在按鍵這里,我們將使用EV_KEY事件。EV_KEY事件和其他事件一樣,由一個(gè)值、一個(gè)代碼和一個(gè)狀態(tài)組成。值是事件類型,代碼是鍵碼,而狀態(tài)則表示按鍵是按下還是釋放。

我們現(xiàn)在來(lái)看一下實(shí)現(xiàn)按鍵輸入驅(qū)動(dòng)的代碼:

// 定義input_dev結(jié)構(gòu)體

static struct input_dev *input_device;

static int button_init(void)

{

int ret;

// 在內(nèi)核中注冊(cè)一個(gè)新的輸入設(shè)備

input_device = input_allocate_device();

if (!input_device) {

printk(KERN_ERR “input_allocate_device fled\n”);

return -ENOMEM;

}

// 指定輸入設(shè)備的名稱

input_device->name = “button”;

// 指定輸入設(shè)備支持的事件類型和數(shù)據(jù)格式

input_set_capability(input_device, EV_KEY, N_0);

// 注冊(cè)輸入設(shè)備

ret = input_register_device(input_device);

if (ret) {

printk(KERN_ERR “input_register_device() fled\n”);

input_free_device(input_device);

}

return ret;

}

static void button_exit(void)

{

// 撤銷輸入設(shè)備的注冊(cè)

input_unregister_device(input_device);

// 釋放輸入設(shè)備

input_free_device(input_device);

}

static int __init button_init_module(void)

{

return button_init();

}

static void __exit button_cleanup_module(void)

{

button_exit();

}

// 處理輸入事件的函數(shù)

static irqreturn_t button_handler(int irq, void *dev_id)

{

struct input_dev *dev = dev_id;

// 讀取當(dāng)前按鍵狀態(tài)

int value = gpio_get_value(GPIO_BUTTON);

input_report_key(dev, N_0, value);

input_sync(dev);

return IRQ_HANDLED;

}

在這個(gè)例子中,我們首先調(diào)用input_allocate_device()函數(shù)來(lái)創(chuàng)建一個(gè)input_dev結(jié)構(gòu)體并分配內(nèi)存。然后,我們將設(shè)備的名稱設(shè)置為“button”,并使用input_set_capability()函數(shù)來(lái)指定輸入設(shè)備支持的事件類型和數(shù)據(jù)格式。在我們的實(shí)現(xiàn)中,我們只使用了是一個(gè)N_0按鍵。我們調(diào)用input_register_device()來(lái)注冊(cè)輸入設(shè)備。

處理輸入事件的函數(shù)由button_handler()實(shí)現(xiàn)。它首先讀取一個(gè)GPIO輸入,并使用input_report_key()函數(shù)來(lái)生成一個(gè)輸入事件。該函數(shù)將生成一個(gè)EV_KEY事件,其中N_0作為鍵碼,并根據(jù)GPIO的狀態(tài)設(shè)置按下或釋放狀態(tài)。

我們使用input_sync()函數(shù)將事件提交給內(nèi)核輸入子系統(tǒng)。

到此為止,我們已經(jīng)學(xué)習(xí)了如何編寫Linux設(shè)備驅(qū)動(dòng),實(shí)現(xiàn)了按鍵輸入驅(qū)動(dòng)。在實(shí)際應(yīng)用中,我們可以根據(jù)需要擴(kuò)展此驅(qū)動(dòng)程序以支持各種不同的輸入設(shè)備、事件類型和數(shù)據(jù)格式。

對(duì)于Linux內(nèi)核的驅(qū)動(dòng)程序開(kāi)發(fā)者來(lái)說(shuō),掌握輸入事件類型和數(shù)據(jù)格式,編寫輸入事件處理函數(shù)以及在內(nèi)核中注冊(cè)和注銷輸入設(shè)備都是非常重要的技能。

成都網(wǎng)站建設(shè)公司-創(chuàng)新互聯(lián)為您提供網(wǎng)站建設(shè)、網(wǎng)站制作、網(wǎng)頁(yè)設(shè)計(jì)及定制高端網(wǎng)站建設(shè)服務(wù)!

linux下如何模擬按鍵輸入和模擬鼠標(biāo)

網(wǎng)頁(yè)鏈閉祥接

這個(gè)是我找的源態(tài)埋雹螞一個(gè)別人的博客

linux/input.h 中有定義,這個(gè)文件還定義了標(biāo)準(zhǔn)按鍵的編猜孝銀碼等 struct input_event { struct timeval time; //按鍵時(shí)間 __u16 type; //類型,在下面有定義穗宴 __u16 code; //要模擬成什么按鍵 __s32 value;//是按下還是釋放 }; code: 事件的代碼.如果事件的類型代碼是EV_KEY,該代碼code 為設(shè)備鍵盤代碼.代碼植0~127 為鍵盤上的按鍵代碼,0x110~0x116 為鼠標(biāo)上按鍵代碼,其中0x110(N_ LEFT)為鼠標(biāo)左鍵,0x111(N_RIGHT)為鼠標(biāo)右鍵,0x112(N_ MIDDLE)為鼠標(biāo)中鍵.其它代碼含義請(qǐng)參看 include/linux/input.h 文件. 如果事件的類型代碼是EV_REL,code 值表示軌跡的類型.如指示鼠標(biāo)的X軸方向REL_X(代碼為0x00),指示鼠標(biāo)的Y 軸方向REL_Y(代碼為0x01),指示鼠標(biāo)中輪子方向 REL_WHEEL(代碼為0x08). type: EV_KEY,鍵盤 EV_REL,相對(duì)坐標(biāo) EV_ABS,絕對(duì)坐標(biāo) value: 事件的值.如果事件的類型代碼是EV_KEY,當(dāng)按鍵按下時(shí)值為1,松開(kāi)時(shí)值為0;如果事件的類型代碼是 EV_ REL,value 的正數(shù)值和負(fù)數(shù)值分別代表兩個(gè)不同方向的值. /* * Event types */ #define EV_SYN 0x00 #define EV_KEY 0x01 //按鍵 #define EV_REL 0x02 //相對(duì)坐標(biāo)(軌跡球) #define EV_ABS 0x03 //絕對(duì)坐標(biāo) #define EV_MSC 0x04 //其他 #define EV_SW 0x05 #define EV_LED 0x11 //LED #define EV_SND 0x12//聲音 #define EV_REP 0x14//repeat #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1) 1。模擬按鍵輸入 //其中0 表示釋放,1 按鍵按下,2 表示一直按下 //0 for EV_KEY for release, 1 for keypress and 2 for autorepeat. void simulate_key(int fd,int value) { struct input_event event; event.type = EV_KEY; //event.code = KEY_0;//要模擬成什么按鍵 event.value = value;//是按下還是釋放按鍵慎衡或者重復(fù) gettimeofday(&event.time,0); if(write(fd,&event,sizeof(event)) window; //一定要設(shè)置為主窗口 event->key.keyval = keyval; //FIXME:一定要加上這個(gè),要不然容易出錯(cuò) g_object_ref(event->key.window); gdk_threads_enter(); //FIXME: 記得用這個(gè)來(lái)發(fā)送事件 gtk_main_do_event(event); gdk_threads_leave(); gdk_event_free(event); } kernel 里input 模塊 input_dev 結(jié)構(gòu): struct input_dev { void *private; const char *name; const char *phys; const char *uniq; struct input_id id; /* * 根據(jù)各種輸入信號(hào)的類型來(lái)建立類型為unsigned long 的數(shù)組, * 數(shù)組的每1bit 代表一種信號(hào)類型, * 內(nèi)核中會(huì)對(duì)其進(jìn)行置位或清位操作來(lái)表示時(shí)間的發(fā)生和被處理. */ unsigned long evbit; unsigned long keybit; unsigned long relbit; unsigned long abit; unsigned long mscbit; unsigned long ledbit; unsigned long sndbit; unsigned long ffbit; unsigned long swbit; ………………………………….. }; /** * input_set_capability – mark device as capable of a certain event * @dev: device that is capable of emitting or accepting event * @type: type of the event (EV_KEY, EV_REL, etc…) * @code: event code * * In addition to setting up corresponding bit in appropriate capability * bitmap the function also adjusts dev->evbit. */ /* 記錄本設(shè)備對(duì)于哪些事件感興趣(對(duì)其進(jìn)行處理)*/ void input_set_capability(struct input_dev *dev, unsigned int type, unsigned int code) { switch (type) { case EV_KEY: __set_bit(code, dev->keybit);//比如按鍵,應(yīng)該對(duì)哪些鍵值的按鍵進(jìn)行處理(對(duì)于其它按鍵不予理睬) break; case EV_REL: __set_bit(code, dev->relbit); break; case EV_ABS: __set_bit(code, dev->abit); break; case EV_MSC: __set_bit(code, dev->mscbit); break; case EV_SW: __set_bit(code, dev->swbit); break; case EV_LED: __set_bit(code, dev->ledbit); break; case EV_SND: __set_bit(code, dev->sndbit); break; case EV_FF: __set_bit(code, dev->ffbit); break; default: printk(KERN_ERR “input_set_capability: unknown type %u (code %u)\n”, type, code); dump_stack(); return; } __set_bit(type, dev->evbit);//感覺(jué)和前面重復(fù)了(前面一經(jīng)配置過(guò)一次了) } EXPORT_SYMBOL(input_set_capability); static irqreturn_t gpio_keys_isr(int irq, void *dev_id) { int i; struct platform_device *pdev = dev_id; struct gpio_keys_platform_data *pdata = pdev->dev.platform_data; struct input_dev *input = platform_get_drvdata(pdev); for (i = 0; i nbuttons; i++) { struct gpio_keys_button *button = &pdata->buttons; int gpio = button->gpio; if (irq == gpio_to_irq(gpio)) {//判斷哪個(gè)鍵被按了? unsigned int type = button->type ?: EV_KEY; int state = (gpio_get_value(gpio) ? 1 : 0) ^ button->active_low;//記錄按鍵狀態(tài) input_event(input, type, button->code, !!state);//匯報(bào)輸入事件 input_sync(input);//等待輸入事件處理完成 } } return IRQ_HANDLED; } /* * input_event() – report new input event * @dev: device that generated the event * @type: type of the event * @code: event code * @value: value of the event * * This function should be used by drivers implementing various input devices * See also input_inject_event() */ void input_event(struct input_dev *dev, unsigned int type, unsigned int code, int value) { struct input_handle *handle; if (type > EV_MAX || !test_bit(type, dev->evbit))//首先判斷該事件類型是否有效且為該設(shè)備所接受 return; add_input_randomness(type, code, value); switch (type) { case EV_SYN: switch (code) { case SYN_CONFIG: if (dev->event) dev->event(dev, type, code, value); break; case SYN_REPORT: if (dev->sync) return; dev->sync = 1; break; } break; case EV_KEY: /* * 這里需要滿足幾個(gè)條件: * 1: 鍵值有效(不超出定義的鍵值的有效范圍) * 2: 鍵值為設(shè)備所能接受(屬于該設(shè)備所擁有的鍵值范圍) * 3: 按鍵狀態(tài)改變了 */ if (code > KEY_MAX || !test_bit(code, dev->keybit) || !!test_bit(code, dev->key) == value) return; if (value == 2) break; change_bit(code, dev->key);//改變對(duì)應(yīng)按鍵的狀態(tài) /* 如果你希望按鍵未釋放的時(shí)候不斷匯報(bào)按鍵事件的話需要以下這個(gè)(在簡(jiǎn)單的gpio_keys 驅(qū)動(dòng)中不需要這個(gè),暫時(shí)不去分析) */ if (test_bit(EV_REP, dev->evbit) && dev->rep && dev->rep && dev->timer.data && value) { dev->repeat_key = code; mod_timer(&dev->timer, jiffies + msecs_to_jiffies(dev->rep)); } break; ……………………………………………….. if (type != EV_SYN) dev->sync = 0; if (dev->grab) dev->grab->handler->event(dev->grab, type, code, value); else /* * 循環(huán)調(diào)用所有處理該設(shè)備的handle(event,mouse,ts,joy 等), * 如果有進(jìn)程打開(kāi)了這些handle(進(jìn)行讀寫),則調(diào)用其對(duì)應(yīng)的event 接口向氣匯報(bào)該輸入事件. */ list_for_each_entry(handle, &dev->h_list, d_node) if (handle->open) handle->handler->event(handle, type, code, value); } EXPORT_SYMBOL(input_event); event 層對(duì)于input 層報(bào)告的這個(gè)鍵盤輸入事件的處理: drivers/input/evdev.c: static struct input_handler evdev_handler = { .event = evdev_event, .connect = evdev_connect, .disconnect = evdev_disconnect, .fops = &evdev_fops, .minor = EVDEV_MINOR_BASE, .name = “evdev”, .id_table = evdev_ids, }; Linux 有自己的 input 子系統(tǒng),可以統(tǒng)一管理鼠標(biāo)和鍵盤事件。 基于輸入子系統(tǒng) 實(shí)現(xiàn)的 uinput 可以方便的在用戶空間模擬鼠標(biāo)和鍵盤事件。 當(dāng)然,也可以自己造輪子, 做一個(gè)字符設(shè)備接收用戶輸入,根據(jù)輸入,投遞 input 事件。 還有一種方式就是直接 往 evnent 里寫入數(shù)據(jù), 都可以達(dá)到控制鼠標(biāo)鍵盤的功能。 本篇文章就是演示直接寫入 event 的方法。 linux/input.h 中有定義,這個(gè)文件還定義了標(biāo)準(zhǔn)按鍵的編碼等 struct input_event { struct timeval time; //按鍵時(shí)間 __u16 type; //類型,在下面有定義 __u16 code; //要模擬成什么按鍵 __s32 value;//是按下還是釋放 }; code: 事件的代碼.如果事件的類型代碼是EV_KEY,該代碼code 為設(shè)備鍵盤代碼.代碼植0~127 為鍵盤上的按鍵代碼, 0x110~0x116 為鼠標(biāo)上按鍵代碼,其中0x110(N_ LEFT)為鼠標(biāo)左鍵,0x111(N_RIGHT)為鼠標(biāo)右鍵,0x112(N_ MIDDLE)為鼠標(biāo)中鍵.其它代碼含義請(qǐng)參看 include/linux /input.h 文件. 如果事件的類型代碼是EV_REL,code 值表示軌跡的類型.如指示鼠標(biāo)的X軸方向 REL_X (代碼為0x00),指示鼠標(biāo)的Y 軸方向REL_Y(代碼為0x01),指示鼠標(biāo)中輪子方向 REL_WHEEL(代碼為0x08). type: EV_KEY,鍵盤 EV_REL,相對(duì)坐標(biāo) EV_ABS,絕對(duì)坐標(biāo) value: 事件的值.如果事件的類型代碼是EV_KEY,當(dāng)按鍵按下時(shí)值為1,松開(kāi)時(shí)值為0;如果事件的類型代碼是 EV_ REL,value 的正數(shù)值和負(fù)數(shù)值分別代表兩個(gè)不同方向的值. /* * Event types */ #define EV_SYN 0x00 #define EV_KEY 0x01 //按鍵 #define EV_REL 0x02 //相對(duì)坐標(biāo)(軌跡球) #define EV_ABS 0x03 //絕對(duì)坐標(biāo) #define EV_MSC 0x04 //其他 #define EV_SW 0x05 #define EV_LED 0x11 //LED #define EV_SND 0x12//聲音 #define EV_REP 0x14//repeat #define EV_FF 0x15 #define EV_PWR 0x16 #define EV_FF_STATUS 0x17 #define EV_MAX 0x1f #define EV_CNT (EV_MAX+1) 下面是一個(gè)模擬鼠標(biāo)和鍵盤輸入的例子: #include #include #include #include #include #include #include #include #include #include #include void simulate_key(int fd,int kval) { struct input_event event; event.type = EV_KEY; event.value = 1; event.code = kval; gettimeofday(&event.time,0); write(fd,&event,sizeof(event)) ; event.type = EV_SYN; event.code = SYN_REPORT; event.value = 0; write(fd, &event, sizeof(event)); memset(&event, 0, sizeof(event)); gettimeofday(&event.time, NULL); event.type = EV_KEY; event.code = kval; event.value = 0; write(fd, &event, sizeof(event)); event.type = EV_SYN; event.code = SYN_REPORT; event.value = 0; write(fd, &event, sizeof(event)); } void simulate_mouse(int fd) { struct input_event event; memset(&event, 0, sizeof(event)); gettimeofday(&event.time, NULL); event.type = EV_REL; event.code = REL_X; event.value = 10; write(fd, &event, sizeof(event)); event.type = EV_REL; event.code = REL_Y; event.value = 10; write(fd, &event, sizeof(event)); event.type = EV_SYN; event.code = SYN_REPORT; event.value = 0; write(fd, &event, sizeof(event)); } int main() { int fd_kbd; int fd_mouse; fd_kbd = open(“/dev/input/event1”,O_RDWR); if(fd_kbdlinux設(shè)備驅(qū)動(dòng) 按鍵的介紹就聊到這里吧,感謝你花時(shí)間閱讀本站內(nèi)容,更多關(guān)于linux設(shè)備驅(qū)動(dòng) 按鍵,Linux設(shè)備驅(qū)動(dòng):按鍵輸入的實(shí)現(xiàn),linux下如何模擬按鍵輸入和模擬鼠標(biāo)的信息別忘了在本站進(jìn)行查找喔。

香港云服務(wù)器機(jī)房,創(chuàng)新互聯(lián)(www.cdcxhl.com)專業(yè)云服務(wù)器廠商,回大陸優(yōu)化帶寬,安全/穩(wěn)定/低延遲.創(chuàng)新互聯(lián)助力企業(yè)出海業(yè)務(wù),提供一站式解決方案。香港服務(wù)器-免備案低延遲-雙向CN2+BGP極速互訪!


本文題目:Linux設(shè)備驅(qū)動(dòng):按鍵輸入的實(shí)現(xiàn)(linux設(shè)備驅(qū)動(dòng)按鍵)
當(dāng)前網(wǎng)址:http://www.5511xx.com/article/dpjjdgg.html