日韩av黄I国产麻豆传媒I国产91av视频在线观看I日韩一区二区三区在线看I美女国产在线I麻豆视频国产在线观看I成人黄色短片

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 >

Linux input子系统 io控制字段【转】

發布時間:2024/9/21 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Linux input子系统 io控制字段【转】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

轉自:http://www.cnblogs.com/leaven/archive/2011/02/12/1952793.html

http://blog.csdn.net/guoshaobei/archive/2010/08/06/5792635.aspx

include/linux/input.h

?

#define EVIOCGVERSION?? ??? ?_IOR('E', 0x01, int)?? ??? ??? ?/* get driver version */
#define EVIOCGID?? ??? ?_IOR('E', 0x02, struct input_id)?? ?/* get device ID */
#define EVIOCGREP?? ??? ?_IOR('E', 0x03, int[2])?? ??? ??? ?/* get repeat settings */
#define EVIOCSREP?? ??? ?_IOW('E', 0x03, int[2])?? ??? ??? ?/* set repeat settings */
#define EVIOCGKEYCODE?? ??? ?_IOR('E', 0x04, int[2])?? ??? ??? ?/* get keycode */
#define EVIOCSKEYCODE?? ??? ?_IOW('E', 0x04, int[2])?? ??? ??? ?/* set keycode */

#define EVIOCGNAME(len)?? ??? ?_IOC(_IOC_READ, 'E', 0x06, len)?? ??? ?/* get device name */
#define EVIOCGPHYS(len)?? ??? ?_IOC(_IOC_READ, 'E', 0x07, len)?? ??? ?/* get physical location */
#define EVIOCGUNIQ(len)?? ??? ?_IOC(_IOC_READ, 'E', 0x08, len)?? ??? ?/* get unique identifier */

#define EVIOCGKEY(len)?? ??? ?_IOC(_IOC_READ, 'E', 0x18, len)?? ??? ?/* get global keystate */
#define EVIOCGLED(len)?? ??? ?_IOC(_IOC_READ, 'E', 0x19, len)?? ??? ?/* get all LEDs */
#define EVIOCGSND(len)?? ??? ?_IOC(_IOC_READ, 'E', 0x1a, len)?? ??? ?/* get all sounds status */
#define EVIOCGSW(len)?? ??? ?_IOC(_IOC_READ, 'E', 0x1b, len)?? ??? ?/* get all switch states */

#define EVIOCGBIT(ev,len)?? ?_IOC(_IOC_READ, 'E', 0x20 + ev, len)?? ?/* get event bits */
#define EVIOCGABS(abs)?? ??? ?_IOR('E', 0x40 + abs, struct input_absinfo)?? ??? ?/* get abs value/limits */
#define EVIOCSABS(abs)?? ??? ?_IOW('E', 0xc0 + abs, struct input_absinfo)?? ??? ?/* set abs value/limits */

#define EVIOCSFF?? ??? ?_IOC(_IOC_WRITE, 'E', 0x80, sizeof(struct ff_effect))?? ?/* send a force effect to a force feedback device */
#define EVIOCRMFF?? ??? ?_IOW('E', 0x81, int)?? ??? ??? ?/* Erase a force effect */
#define EVIOCGEFFECTS?? ??? ?_IOR('E', 0x84, int)?? ??? ??? ?/* Report number of effects playable at the same time */

#define EVIOCGRAB?? ??? ?_IOW('E', 0x90, int)?? ??? ??? ?/* Grab/Release device */

?

原文:http://www.linuxjournal.com/article/6429

盡管原文寫于2003,仍有參考價值。

?

<!-- @page { margin: 0.79in } P { margin-bottom: 0.08in } H4 { margin-bottom: 0.08in } PRE.cjk { font-family: "DejaVu Sans", monospace } TD P { margin-bottom: 0in } -->

The Linux USB Input Subsystem

Part 1

?

Linux USB輸入子系統是一種簡單的協調的管理所有輸入設備的方式。

本文討論 4部分內容:輸入子系統的描述;內核中輸入子系統的實現;輸入子系統的用戶空間 API;在你的程序中如何使用它。

?

什么是輸入子系統 ?
輸入子系統是 Linux內核用于管理各種輸入設備 (鍵盤,鼠標,遙控桿,書寫板等等 )的部分,用戶通過輸入子系統進行內核,命令行,圖形接口之間的交換。輸入子系統在內核里實現,因為設備經常要通過特定的硬件接口被訪問 (例如串口, ps/2, usb等等 ),這些硬件接口由內核保護和管理。內核給用戶導出一套固定的硬件無關的 input API,供用戶空間程序使用。

?

理解內核內部實現

輸入子系統分為三塊: input core, drivers和 event handlers。他們之間的關系如圖 1所示。正常的路徑是從底層硬件到驅動,從驅動到 input core,從 input core到 event handler,從 event handler到 user space。此外,還存在一個返回路徑 (return path)。返回路徑允許給一個鍵盤設置 LED,給一個 force feedback joystick提供 motion commands。路徑的兩個方向(指從內核到用戶的方向和從用戶到內核的方向)使用相同的 event定義和不同的 type identifier。

?

?

這三個核心模塊之間的交互主要通過 events數據結構來實現, events的數據結構定義如下:

Listing 1. event-dev-struct.txt

struct input_dev {

void *private;

char *name;
char *phys;
char *uniq;
struct input_id id;

unsigned long evbit[NBITS(EV_MAX)];
unsigned long keybit[NBITS(KEY_MAX)];
unsigned long relbit[NBITS(REL_MAX)];
unsigned long absbit[NBITS(ABS_MAX)];
unsigned long mscbit[NBITS(MSC_MAX)];
unsigned long ledbit[NBITS(LED_MAX)];
unsigned long sndbit[NBITS(SND_MAX)];
unsigned long ffbit[NBITS(FF_MAX)];
int ff_effects_max;

unsigned int keycodemax;
unsigned int keycodesize;
void *keycode;

unsigned int repeat_key;
struct timer_list timer;

struct pm_dev *pm_dev;
int state;

int sync;

int abs[ABS_MAX + 1];
int rep[REP_MAX + 1];

unsigned long key[NBITS(KEY_MAX)];
unsigned long led[NBITS(LED_MAX)];
unsigned long snd[NBITS(SND_MAX)];

int absmax[ABS_MAX + 1];
int absmin[ABS_MAX + 1];
int absfuzz[ABS_MAX + 1];
int absflat[ABS_MAX + 1];

int (*open)(struct input_dev *dev);
void (*close)(struct input_dev *dev);
int (*accept)(struct input_dev *dev,
struct file *file);
int (*flush)(struct input_dev *dev,
struct file *file);
int (*event)(struct input_dev *dev,
unsigned int type,
unsigned int code,
int value);
int (*upload_effect)(struct input_dev *dev,
struct ff_effect *effect);
int (*erase_effect)(struct input_dev *dev,
int effect_id);

struct list_head h_list;
struct list_head node;
};

type域顯示了被報告事件的類型,例如,一個 key press或者 button press, relative motion(比如移動鼠標 )或者 absolute motion(比如移動游戲桿 ); code域告訴你是哪一個 key或者坐標軸在被操作; value域告訴你現在的狀態或者運動情況是什么。

例如,如果 type域是一個 key, code域告訴你是哪一個 key, value域告訴你該 key是被按下還是抬起。類似的,如果 type域是一個相對坐標軸, code域告訴你是哪一個坐標軸, value域告訴你移動的距離以及相對坐標軸的方向。

如果你以對角線的方向移動鼠標,同時移動滾輪,你將獲得三個相對事件:垂直軸上的運動事件 (x-axis),水平軸上的運動事件 (y-axis),滾輪的運動事件。

?

Event handlers給用戶空間提供接口,將標準事件格式轉換為特定 API所需要的格式。 Handlers也通常負責設備節點 (/dev entries)。最常見的 handler是 keyboard handler,它是大多數 C程序員熟悉的” standard input”

驅動通常提供底層硬件的接口,例如 USB, PCI memory或者 I/O regions,或者 serial port I/O regions。

在發送給 input core之前,驅動將用戶接口的底層硬件形式轉換為標準的事件格式。 Input core使用標準的內核 plugin design:使用 input_register_device()來添加設備,使用 input_unregister_device()來刪除設備。這些調用的參數是 struct input_device, 如 listing-1所描述。盡管這個數據結構看起來很大,但是絕大多數的域被提供,用于保證驅動可以規定一個設備的能力,例如哪種事件類型,設備接受或者發送的 codes。

?

除了管理驅動和 handlers, input core也導出了一些有用的 /proc文件系統接口,用于查看當前活動的設備和事件 handlers。下面是查看 usb鼠標的例子 (cat /proc/bus/input/devices)

I: Bus=0003 Vendor=046d Product=c002 Version=0120
N: Name="Logitech USB-PS/2 Mouse M-BA47"
P: Phys=usb-00:01.2-2.2/input0
H: Handlers=mouse0 event2
B: EV=7
B: KEY=f0000 0 0 0 0 0 0 0 0
B: REL=103

?

I line:這行包含身份信息,顯示了 bus type是 3 (usb), vendor, product, version等來來自 usb descriptoer關于鼠標的廠商信息。

N line:這行包含了名字信息。

P line:這行包含了物理設備信息。上述例子包含了 usb controller的 pci address, usb tree以及 input interface。

H line: 這行包含了與設備關聯的 handler drivers。

B line: 這些行包含了顯示設備能力的一些位域 (bitfield)。

?

Listing 2. register.c

#include <linux/input.h>
#include <linux/module.h>
#include <linux/init.h>

MODULE_LICENSE("GPL");

struct input_dev ex1_dev;

static int __init ex1_init(void)
{
/* extra safe initialization */
memset(&ex1_dev, 0, sizeof(struct input_dev));
init_input_dev(&ex1_dev);

/* set up descriptive labels */
ex1_dev.name = "Example 1 device";
/* phys is unique on a running system */
ex1_dev.phys = "A/Fake/Path";
ex1_dev.id.bustype = BUS_HOST;
ex1_dev.id.vendor = 0x0001;
ex1_dev.id.product = 0x0001;
ex1_dev.id.version = 0x0100;

/* this device has two keys (A and B) */
set_bit(EV_KEY, ex1_dev.evbit);
set_bit(KEY_B, ex1_dev.keybit);
set_bit(KEY_A, ex1_dev.keybit);

/* and finally register with the input core */
input_register_device(&ex1_dev);

return 0;
}

static void __exit ex1_exit(void)
{
input_unregister_device(&ex1_dev);
}

module_init(ex1_init);
module_exit(ex1_exit);

?

?

/proc接口是一種簡單使用的方法來測試一些簡單的驅動??紤]如下 listing 2的一個驅動例子,在 init()里注冊,在 removal()里注銷。該驅動示例使用 init_input_dev()來做一些初步的初始化工作:設置名字,物理描述符,身份描述符;然后設置 bit arrays來指定設備提供的事件類型是 EV_KEY,兩個可能的 codes是 KEY_A, KEY_B。初始化代碼然后將設備注冊到 input core。如果你將這個示例代碼 modprobe到內核,你會從 /proc/bus/input/devices里看到如下信息:

I: Bus=0019 Vendor=0001 Product=0001 Version=0100
N: Name="Example 1 device"
P: Phys=A/Fake/Path
H: Handlers=kbd event3
B: EV=3
B: KEY=10000 40000000

?

如果我想從設備驅動發送事件到 input core,我們需要調用 input_event()或者更便利的封裝函數,例如 input_report_key()/input_report_abs(),在 include/linux/input.h里定義。示例 listing 3使用了這些函數。

這個示例與 listing 2示例基本相同,但是增加了一個 timer,調用 ex2_timeout()。這個新函數發送了 4次 KEY_A press和 4次 KEY_B press。注意這總共會產生 16次 press 事件,這是因為每次 event由一次按鍵或一次釋放鍵產生。這些事件傳遞給 input core,然后傳遞給 keyboard handler,產生” aaaabbbb”或者” AAAABBBB”,依賴于 shift鍵是否被選擇。 timer在 4秒后被設置循環運行, 4秒的時間確保你有最夠的時間移除模塊當你認為打印了足夠的測試信息。同樣注意需要調用 input_sync()函數。該函數用于通知 event handler (這里是 keyboard handler)設備已經傳遞完一組完整的數據。在 input_sync()函數被調用之前,

handler可能緩存 events。

?

Listing 3. aaaabbbb.c

struct input_dev ex2_dev;

void ex2_timeout(unsigned long unused/*UNUSED*/)
{
int x;

for (x=0;x<4;x++) {
/* letter a or A */
input_report_key(&ex2_dev, KEY_A, 1);
input_sync(&ex2_dev);
input_report_key(&ex2_dev, KEY_A, 0);
input_sync(&ex2_dev);
}
for (x=0;x<4;x++) {
/* letter b or B */
input_report_key(&ex2_dev, KEY_B, 1);
input_sync(&ex2_dev);
input_report_key(&ex2_dev, KEY_B, 0);
input_sync(&ex2_dev);
}

/* set timer for four seconds */
mod_timer(&ex2_dev.timer,jiffies+4*HZ );
}

static int __init ex2_init(void)
{

... do initialization ...

/* set up a repeating timer */
init_timer(&ex2_dev.timer);
ex2_dev.timer.function = ex2_timeout;
ex2_dev.timer.expires = jiffies + HZ;
add_timer(&ex2_dev.timer);

return 0;
}

static void __exit ex2_exit(void)
{
del_timer_sync(&ex2_dev.timer);
input_unregister_device(&ex2_dev);
}

?

讓我們來看最后一個驅動例子,顯示相對信息如何提供,如 listing 4所示。這個驅動例子模仿了一個鼠標。初始化代碼配置設備有兩個坐標軸 (REL_X和 REL_Y)和一個 key(BTN_LEFT)。我們使用一個 timer來運行 ex3_timeout。這個 timer調用 input_report_rel來提供相對運動 (5個單步 ---相對運動是函數的的 3個參數 ),包含 30步向右, 30 步向下, 30步向左, 30步向上,因此光標構成了一個正方形。為了提供運動動畫,

timeout是 20毫秒。再次強調的是, input_sync()是保證事件 handler處理一個完整的事件數據的,你需要調用 input_sync()來確保你的數據已經完整的傳遞給 input core。如果你向對角線移動,你需要這樣做:

...
input_report_rel(..., REL_X, ...);
input_report_rel(..., REL_Y, ...);
input_sync(...);
...

?

這樣確保了鼠標對角線移動,而不是現橫向移動,后豎向移動。

Listing 4. squares.c

void ex3_timeout(unsigned long unused /*UNUSED*/)
{
/* move in a small square */
if (state<30)
input_report_rel(&ex3_dev, REL_X, 5);
else if (state < 60)
input_report_rel(&ex3_dev, REL_Y, 5);
else if (state < 90)
input_report_rel(&ex3_dev, REL_X, -5);
else
input_report_rel(&ex3_dev, REL_Y, -5);

input_sync(&ex3_dev);

if ((state++) >= 120)
state = 0;

/* set timer for 0.02 seconds */
mod_timer(&ex3_dev.timer, jiffies+HZ/50);
}

static int __init ex3_init(void)
{
/* extra safe initialization */
memset(&ex3_dev, 0, sizeof(struct input_dev));
init_input_dev(&ex3_dev);

/* set up descriptive labels */
ex3_dev.name = "Example 3 device";
/* phys is unique on a running system */
ex3_dev.phys = "A/Fake/Path";
ex3_dev.id.bustype = BUS_HOST;
ex3_dev.id.vendor = 0x0001;
ex3_dev.id.product = 0x0003;
ex3_dev.id.version = 0x0100;

/* this device has two relative axes */
set_bit(EV_REL, ex3_dev.evbit);
set_bit(REL_X, ex3_dev.relbit);
set_bit(REL_Y, ex3_dev.relbit);

/* it needs a button to look like a mouse */
set_bit(EV_KEY, ex3_dev.evbit);
set_bit(BTN_LEFT, ex3_dev.keybit);

/* and finally register with the input core */
input_register_device(&ex3_dev);

/* set up a repeating timer */
init_timer(&ex3_dev.timer);
ex3_dev.timer.function = ex3_timeout;
ex3_dev.timer.expires = jiffies + HZ/10;
add_timer(&ex3_dev.timer);

return 0;
}

static void __exit ex3_exit(void)
{
del_timer_sync(&ex3_dev.timer);
input_unregister_device(&ex3_dev);
}

module_init(ex3_init);
module_exit(ex3_exit);

?

Handlers---到達用戶空間

我們看到設備驅動位于硬件設備和 input core之間,將硬件事件(通常是中斷)翻譯成 input events。為了使用 input events,我們使用 handlers,它提供了用戶空間的接口。

?

input子系統包含了你需要的大多數 handlers:一個提供 console的 keyboard handler;一個供應用程序使用的 mouse handler;一個 joystick handler以及一個 touchscreen handler。同樣有一個通用的 event handler,向用戶空間提供 basic input events。這意味著你不需要在內核里再寫一個 handler,因為你可以在用戶空間通過訪問 event handler完成你需要的功能。

?

?

<!-- @page { size: 8.5in 11in; margin: 0.79in } P { margin-bottom: 0.08in } H4 { margin-bottom: 0.08in } TD P { margin-bottom: 0in } -->

Using the Input Subsystem

part 2

?

Linux input子系統一個很重要的特性是它提供了 event interface。它通過字符設備節點對用戶空間導出了原生 event,允許用戶程序操作任何 event,不會遺失任何信息。

?

查找 event interface版本

使用 EVIOCGVERSION ioctl function。參數是 32位 int類型,代表 major version (two high bytes), minor version (third byte), patch level (low byte)。 Listing 1顯示了使用 EVIOCGVERSION的例子:第 1個參數是 event device node的打開文件描述符。你需要傳遞一個指向 int數據的一個指針作為第 3個參數。

Listing 1. Sample EVIOCGVERSION Function

/* ioctl() accesses the underlying driver */
if (ioctl(fd, EVIOCGVERSION, &version)) {
perror("evdev ioctl");
}

/* the EVIOCGVERSION ioctl() returns an int */
/* so we unpack it and display it */
printf("evdev driver version is %d.%d.%d\n",
version >> 16, (version >> 8) & 0xff,
version & 0xff);

?

查找設備身份信息

event interface支持獲取設備的身份信息,使用 EVIOCGID ioctl function。參數是指向 input_id數據結構的指針。 input_id數據結構定義如 listing 2所示。 _u16數據類型是 16為無符號整型。

Figure 2. input_id Structure Definitions

struct input_id {
__u16 bustype;
__u16 vendor;
__u16 product;
__u16 version;
};

?

bustype 域包含了你需要的準確的數據信息。你應把它當作是一個非透明的枚舉類型,需要與通過 <linux/input.h>里定義的 BUG_x 類型比較獲知。 vendor/product/version是與 bus type相關的表示設備身份信息的域?,F代設備(如 USB, PCI)都使用了這些域,但是傳統的設備( serial mice, ps/2 keyboard, ISA sound card)沒有這些域。 EVIOCGID的使用如 listing 3所示。這個例子調用了 ioctl并打印了結果。

Listing 3. Sample EVIOCGID ioctl

/* suck out some device information */
if(ioctl(fd, EVIOCGID, &device_info)) {
perror("evdev ioctl");
}

/* the EVIOCGID ioctl() returns input_devinfo
* structure - see <linux/input.h>
* So we work through the various elements,
* displaying each of them
*/
printf("vendor %04hx product %04hx version %04hx",
device_info.vendor, device_info.product,
device_info.version);
switch ( device_info.bustype)
{
case BUS_PCI :
printf(" is on a PCI bus\n");
break;
case BUS_USB :
printf(" is on a Universal Serial Bus\n");
break;
...

?

除了 bus type/vendor/product/version等設備信息,某些設備還會提供一個有意義的名字字符串,使用 EVIOCGNAME獲取。如果名字串太長,則在返回的參數里被截取。 Listing 4顯示了它的使用的例子。

Listing 4. Example Truncated String

int fd = -1;
char name[256]= "Unknown";

if ((fd = open(argv[1], O_RDONLY)) < 0) {
perror("evdev open");
exit(1);
}

if(ioctl(fd, EVIOCGNAME(sizeof(name)), name) < 0) {
perror("evdev ioctl");
}

printf("The device on %s says its name is %s\n",
argv[1], name);

close(fd);

?

下面是上述例子運行的結果樣例:

The device on /dev/input/event0 says its name is Logitech USB-PS/2 Optical Mouse

?

盡管設備身份信息和名字信息通常很有用,但是它也許并沒有提供足夠的信息告訴你當前在使用哪個設備。例如,你當前有兩個完全相同的遙控桿,你需要確定每個使用哪個端口。這通常屬于拓撲信息( topology information),可以使用 EVIOCGPHYS ioctl獲取。它返回一串字符串(或者一個負值錯誤碼)。 Listing 5顯示了它的使用的例子。

Listing 5. Using EVIOCGPHYS for Topology Information

if(ioctl(fd, EVIOCGPHYS(sizeof(phys)), phys) < 0) {
perror("event ioctl");
}
printf("The device on %s says its path is %s\n",
argv[1], phys);

?

它的運行結果樣例如下所示:

The device on /dev/input/event0 says its path is usb-00:01.2-2.1/input0

?

為了了解輸出的含義,你需要將其分成幾部分。 Usb部分意味著這使用 usb系統的一個物理拓撲。 00:01.2是 usb host controller所在的 pci bus information (bus 0, slot 1, function 2)。 2.1表示了從 root hub到 device的路徑,這里表示上行 hub接在 root hub的第 2個端口上,設備接在上行 hub的第 1個端口上。 Input0表示這是設備的第 1個 event device 節點。大部分設備只有一個 event device節點,但是有些設備例外。比如多媒體鍵盤,它有一個 event device節點用于 normal keyboard,另一個 event device節點用于 multimedia keyboard。拓撲示例如下圖表示。

如果你在同一根連接線上將一個設備還成另外一個同樣的設備,你無法區分設備更換,除非每一個設備有一個唯一號,比如 serial number。使用 EVIOCGUNIQ可以獲取。 Listing 6是其示例。絕大多數設備沒有這樣的唯一號,所以你使用該 ioctl將返回一個空字符串。

Listing 6. Finding a Unique Identifier

if(ioctl(fd, EVIOCGUNIQ(sizeof(uniq)), uniq) < 0) {
perror("event ioctl");
}

printf("The device on %s says its identity is %s\n",
argv[1], uniq);

?

確定設備能力和特性

對于一些設備,也許知道設備的身份信息就足夠了,因為它允許你根據設備的使用情況處理設備的任何 case。但是這總做法的尺度不好。比如,你有一個設備僅有一個滑輪,你想使能處理滑輪的 handler,但是你并不想在 code里列出每個帶有滑輪的鼠標的 vendor/product信息。為此, event interface允許你對于某個設備確定有哪些功能和特性。 Event interface支持的 feature types有:

  • EV_KEY: absolute binary results, such as keys and buttons.

  • EV_REL: relative results, such as the axes on a mouse.

  • EV_ABS: absolute integer results, such as the axes on a joystick or for a tablet.

  • EV_MSC: miscellaneous uses that didn't fit anywhere else.

  • EV_LED: LEDs and similar indications.

  • EV_SND: sound output, such as buzzers.

  • EV_REP: enables autorepeat of keys in the input core.

  • EV_FF: sends force-feedback effects to a device.

  • EV_FF_STATUS: device reporting of force-feedback effects back to the host.

  • EV_PWR: power management events

這些僅僅是 type features。每個 type feature包含了很大范圍的不同的個體 feature。例如, EV_REL type區別了 x軸, y軸, z軸,橫輪,豎輪。同樣, EV_KEY type包含了成千上百個 keys和 buttons。

使用 EVIOCGBIT ioctl可以獲取設備的能力和特性。它告知你設備是否有 key或者 button。

EVIOCGBIT ioctl處理 4個參數 ( ioctl(fd, EVIOCGBIT(ev_type, max_bytes), bitfield))。 ev_type是返回的 type feature( 0是個特殊 case,表示返回設備支持的所有的 type features)。 max_bytes表示返回的最大字節數。 bitfield域是指向保存結果的內存指針。 return value表示保存結果的實際字節數,如果調用失敗,則返回負值。 Listing 7展現了其使用示例,測試了 /dev/input/event0設備節點支持哪些 type feature。

#include <stdio.h>

#include <stdlib.h>

#include <unistd.h>

#include <fcntl.h>

#include <string.h>

#include <linux/input.h>

#define BITS_PER_LONG 32

#define BIT_WORD(nr) ((nr) / BITS_PER_LONG)

static int test_bit(int nr, const volatile unsigned long *addr)

{

return 1UL & (addr[BIT_WORD(nr)] >> (nr & (BITS_PER_LONG-1)));

}

int main(int argc, char ** argv)

{

int fd;

unsigned long *evtype_b = malloc(sizeof(int));

int yalv;

if ((fd = open(argv[1], O_RDONLY)) < 0) {

perror("evdev open");

exit(1);

}

memset(evtype_b, 0, sizeof(evtype_b));

if (ioctl(fd, EVIOCGBIT(0, EV_MAX), evtype_b) < 0) {

perror("evdev ioctl");

}

printf("Supported event types:\n");

for (yalv = 0; yalv < EV_MAX; yalv++) {

if (test_bit(yalv, evtype_b)) {

/* the bit is set in the event types list */

printf(" Event type 0x%02x ", yalv);

switch ( yalv)

{

case EV_SYN :

printf(" (Synch Events)\n");

break;

case EV_KEY :

printf(" (Keys or Buttons)\n");

break;

case EV_REL :

printf(" (Relative Axes)\n");

break;

case EV_ABS :

printf(" (Absolute Axes)\n");

break;

case EV_MSC :

printf(" (Miscellaneous)\n");

break;

case EV_LED :

printf(" (LEDs)\n");

break;

case EV_SND :

printf(" (Sounds)\n");

break;

case EV_REP :

printf(" (Repeat)\n");

break;

case EV_FF :

case EV_FF_STATUS:

printf(" (Force Feedback)\n");

break;

case EV_PWR:

printf(" (Power Management)\n");

break;

default:

printf(" (Unknown: 0x%04hx)\n",

yalv);

}

}

}

close(fd);

}

?

這個例子使用了 evtype_bit掩碼 EV_MAX(在 <linux/input.h>里定義),覺得 bit array需要多少內存。當 ioctl提交后,由 event layer填充 bit array。我們測試 bit array里的每一個 bit,來確定設備支持哪些 feature type。所有的設備都支持 EV_SYNC,該 bit由 input core來設置。

下面是運行結果的樣例:

如果是 keyboard,則

Supported event types:
Event type 0x00 (Synchronization Events)
Event type 0x01 (Keys or Buttons)
Event type 0x11 (LEDs)
Event type 0x14 (Repeat

?

如果是 mouse,則

Supported event types:
Event type 0x00 (Synchronization Events)
Event type 0x01 (Keys or Buttons)
Event type 0x02 (Relative Axes)

?

獲取設備 (from or to)的 input

?

當確定了設備的能力和特性后,你就知道了設備的事件類型。

獲取設備的 event通過 char設備的 read function。當你從 event device (例如 /dev/input/event0)里讀取 event時,你將獲得一系列 events,每個 event由 input_event結構表示。

Listing 8示例展示了讀取一個打開文件描述符 fd的事件。它過濾了不屬于 key的事件,并打印 input_event結構里的每個域。

Listing 8. Checking for Busy Spots

/* how many bytes were read */
size_t rb;
/* the events (up to 64 at once) */
struct input_event ev[64];

rb=read(fd,ev,sizeof(struct input_event)*64);

if (rb < (int) sizeof(struct input_event)) {
perror("evtest: short read");
exit (1);
}

for (yalv = 0;
yalv < (int) (rb / sizeof(struct input_event));
yalv++)
{
if (EV_KEY == ev[yalv].type)
printf("%ld.%06ld ",
ev[yalv].time.tv_sec,
ev[yalv].time.tv_usec,
printf("type %d code %d value %d\n",
ev[yalv].type,
ev[yalv].code, ev[yalv].value);
}

?

下面是運行的結果樣例:

Event: time 1033621164.003838, type 1, code 37, value 1
Event: time 1033621164.027829, type 1, code 38, value 0
Event: time 1033621164.139813, type 1, code 38, value 1
Event: time 1033621164.147807, type 1, code 37, value 0
Event: time 1033621164.259790, type 1, code 38, value 0
Event: time 1033621164.283772, type 1, code 36, value 1
Event: time 1033621164.419761, type 1, code 36, value 0
Event: time 1033621164.691710, type 1, code 14, value 1
Event: time 1033621164.795691, type 1, code 14, value 0

?

對于每個 key,你會獲得一個 key press和一個 key depress的 event。

這是 char設備的標準 read接口,所以你不需要在程序里 busy loop。此外,如果你想同時獲得許多設備的 input事件時,使用 poll/select函數。

給設備發送信息,使用 char設備的標準 write函數,發送的數據必須是 input_event數據結構。

Listing 9展示了簡單的給設備寫數據的示例。這個例子先讓 Caps Lock LED打開,等 200毫秒,然后讓 Caps Lock LED關閉;然后讓 Num Lock LED打開,等 200毫秒,然后讓 Num Lock LED關閉。不斷循環這個過程,你會看到鍵盤上的指示燈交替閃爍。

Listing 9. Sample Data Write Function

struct input_event ev; /* the event */

/* we turn off all the LEDs to start */
ev.type = EV_LED;
ev.code = LED_CAPSL;
ev.value = 0;
retval = write(fd, &ev, sizeof(struct input_event));
ev.code = LED_NUML;
retval = write(fd, &ev, sizeof(struct input_event));
ev.code = LED_SCROLLL;
retval = write(fd, &ev, sizeof(struct input_event));

while (1)
{
ev.code = LED_CAPSL;
ev.value = 1;
write(fd, &ev, sizeof(struct input_event));
usleep(200000);
ev.value = 0;
write(fd, &ev, sizeof(struct input_event));

ev.code = LED_NUML;
ev.value = 1;
write(fd, &ev, sizeof(struct input_event));
usleep(200000);
ev.value = 0;
write(fd, &ev, sizeof(struct input_event));
}

?

現在我們清楚的知道如何接收或者發送一個事件 ---key按下 /抬起,鼠標移動等等。對于一些程序,可能還需要知道設備的一些全局狀態。比如,一個管理 keyboard的程序需要知道當前的哪些指示燈在亮,哪些鍵被釋放。

EVIOCGKEY ioctl用于確定一個設備的全局 key/button狀態,它在 bit array里設置了每個 key/button是否被釋放。 Listing 10展示了該示例。

Listing 10. Determining a Device's Global Key and Button

State

uint8_t key_b[KEY_MAX/8 + 1];

memset(key_b, 0, sizeof(key_b));
ioctl(fd, EVIOCGKEY(sizeof(key_b)), key_b);

for (yalv = 0; yalv < KEY_MAX; yalv++) {
if (test_bit(yalv, key_b)) {
/* the bit is set in the key state */
printf(" Key 0x%02x ", yalv);
switch ( yalv)
{
case KEY_RESERVED :
printf(" (Reserved)\n");
break;
case KEY_ESC :
printf(" (Escape)\n");
break;
/* other keys / buttons not shown */
case BTN_STYLUS2 :
printf(" (2nd Stylus Button )\n");
break;
default:
printf(" (Unknown key)\n");
}
}
}

?

EVIOCGLED和 EVIOCGSND ioctl與 EVIOCGKEY類似,分別表示當前 LED亮燈和聲音通道打開。 Listing 11展示了 EVIOCGLED的使用。

Listing 11. Using EVIOCGLED

memset(led_b, 0, sizeof(led_b));
ioctl(fd, EVIOCGLED(sizeof(led_b)), led_b);

for (yalv = 0; yalv < LED_MAX; yalv++) {
if (test_bit(yalv, led_b)) {
/* the bit is set in the LED state */
printf(" LED 0x%02x ", yalv);
switch ( yalv)
{
case LED_NUML :
printf(" (Num Lock)\n");
break;
case LED_CAPSL :
printf(" (Caps Lock)\n");
break;
/* other LEDs not shown here*/
default:
printf(" (Unknown LED: 0x%04hx)\n",
yalv);
}
}
}

?

使用 EVIOCGREP ioctl來獲取鍵盤的重復速率。 Listing 12展示了該示例。(重復速率指你按下鍵后,輸出的事件的次數。例如,按下 1鍵且不釋放, console里會輸出多個 1的速率)

Listing 12. Checking the Repeat Rate Settings

int rep[2];

if(ioctl(fd, EVIOCGREP, rep)) {
perror("evdev ioctl");
}

printf("[0]= %d, [1] = %d\n", rep[0], rep[1]);

其中, rep[0]表示在按鍵重復出現之前 delay的時間; rep[1]表示按鍵重復出現的時間間隔。

?

使用 EVIOCSREP ioctl來設置鍵盤的重復速率。 Listing 13展示了該示例。

Listing 13. Setting the Repeat Rates

int rep[2];

rep[0] = 2500;
rep[1] = 1000;

if(ioctl(fd, EVIOCSREP, rep)) {
perror("evdev ioctl");
}

rep[0]/rep[1]的含義同 Listing 12。

?

有些 input driver支持 key mapping。使用 EVIOCGKEYCODE ioctl獲取一個 key對應的 scancode。 Listing 14/Listing 15展示了 key mapping的示例。注意有些鍵盤驅動并不支持這個特性(比如 USB鍵盤)。如果你想修改 key mapping,使用 EVIOCSKEYCODE ioctl即可。

Listing 14. Looping over Scancodes

int codes[2];

for (i=0; i<130; i++) {
codes[0] = i;
if(ioctl(fd, EVIOCGKEYCODE, codes)) {
perror("evdev ioctl");
}
printf("[0]= %d, [1] = %d\n",
codes[0], codes[1]);
}

?

Listing 15. Mapping Keys

int codes[2];

codes[0] = 58; /* M keycap */
codes[1] = 49; /* assign to N */

if(ioctl(fd, EVIOCSKEYCODE, codes)) {
perror("evdev ioctl");
}

?

使用 EVIOCGABS ioctl提供絕對坐標軸設備的狀態信息。它為每一個絕對坐標軸提供了一個 input_absinfo數據結構(參考 Listing 16)。如果你想查看設備的全局狀態,對每一個坐標軸調用 EVIOCGABS ioctl函數。 Listing 17展示了該示例。

Listing 16. input_absinfo for an Absolute Axis

struct input_absinfo {
__s32 value; // current value of the axis
__s32 minimum; // current limits of the axis
__s32 maximum; // current limits of the axis
__s32 fuzz;
__s32 flat;
};

?

Listing 17. Checking Global State by Axis

uint8_t abs_b[ABS_MAX/8 + 1];
struct input_absinfo abs_feat;

ioctl(fd, EVIOCGBIT(EV_ABS, sizeof(abs_b)), abs_b);

printf("Supported Absolute axes:\n");

for (yalv = 0; yalv < ABS_MAX; yalv++) {
if (test_bit(yalv, abs_b)) {
printf(" Absolute axis 0x%02x ", yalv);
switch ( yalv)
{
case ABS_X :
printf("(X Axis) ");
break;
case ABS_Y :
printf("(Y Axis) ");
break;
default:
printf("(Unknown abs feature)");
}
if(ioctl(fd, EVIOCGABS(yalv), &abs_feat)) {
perror("evdev EVIOCGABS ioctl");
}
printf("%d (min:%d max:%d flat:%d fuzz:%d)",
abs_feat.value,
abs_feat.minimum,
abs_feat.maximum,
abs_feat.flat,
abs_feat.fuzz);
printf("\n");
}
}

?

Force Feedback (力回饋)

有三個 ioctl用于控制 force-feedback設備: EVIOCSFF, EVIOCRMFF, EVIOCGEFFECT。這三個 ioctl分別表示發送一個 force-feedback effect,刪除一個 force-feedback effect,獲取當前多少個 effect在同時使用。

轉載于:https://www.cnblogs.com/sky-heaven/p/8869830.html

總結

以上是生活随笔為你收集整理的Linux input子系统 io控制字段【转】的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。

亚洲人人精品 | 久久综合丁香 | 亚州精品在线视频 | 亚洲一区网| 色婷婷www | 久草在线免费电影 | 在线成人观看 | 日韩va亚洲va欧美va久久 | 91av视频 | 国产精品 亚洲精品 | 国产一区在线免费观看 | 婷婷亚洲综合五月天小说 | 国产96在线 | 欧美激情精品久久 | 成人久久久电影 | 天天综合导航 | 久久久www| 国产精品久久久久久久久久尿 | 国产在线更新 | 美女久久久久久久久久 | 中文字幕在线久一本久 | 亚洲一区二区精品 | 国产人成在线观看 | 精品一区精品二区高清 | 欧美性大胆 | 日韩av看片| 成人精品99| 久久国产亚洲 | 中文在线a天堂 | 免费男女羞羞的视频网站中文字幕 | 美女视频免费精品 | 成人av高清在线观看 | 欧美一级电影在线观看 | 免费av电影网站 | 久久久久久久网 | 成人99免费视频 | 91精品婷婷国产综合久久蝌蚪 | 精品一区二区视频 | 在线观看aaa | 亚洲视屏在线播放 | 久久av不卡| 18岁免费看片 | av在线成人 | 久久亚洲私人国产精品va | 日韩一区二区三区高清免费看看 | 日本黄色免费大片 | 91av短视频 | 狠狠色丁香婷婷综合久小说久 | 五月婷婷六月丁香在线观看 | 午夜国产福利视频 | 亚洲日本色 | 波多野结衣电影一区二区三区 | 国产中文字幕视频 | 美女黄网久久 | 中文字幕免费成人 | 日日精品 | 久久精品网站视频 | 黄毛片在线观看 | 亚洲理论电影 | 日韩精品资源 | 一本一本久久a久久精品综合 | 色黄久久久久久 | 中文字幕第一页在线播放 | 综合激情网 | 国产视频在线一区二区 | 五月天综合婷婷 | 国产麻豆视频在线观看 | 天天摸天天舔 | 在线观看播放av | 欧洲黄色片 | 国产午夜在线观看视频 | 亚洲欧美综合精品久久成人 | 国产色在线视频 | 国产在线精品国自产拍影院 | 亚洲国产精品va在线看 | 97人人澡人人爽人人模亚洲 | 久久黄色小说 | 国内精品久久久精品电影院 | 国产亚洲精品久久久久秋 | 探花视频免费在线观看 | 天天操人人要 | 天天碰天天操视频 | 亚洲一区视频免费观看 | www国产亚洲精品久久网站 | 国产中文字幕在线播放 | 1区2区3区在线观看 三级动图 | 中文字幕免费不卡视频 | 亚洲精品中文字幕在线观看 | 国产成人三级一区二区在线观看一 | 视频一区二区视频 | 日韩在线观看第一页 | 又色又爽的网站 | 久久综合偷偷噜噜噜色 | 国产精品男女视频 | 久草视频中文 | 9热精品| 一本之道乱码区 | 婷婷成人亚洲综合国产xv88 | 91人人网 | 久久爱导航 | 在线日韩三级 | 激情av资源| 99视频精品免费视频 | 免费观看一级成人毛片 | 欧美人操人 | 亚洲aⅴ免费在线观看 | 中国美女一级看片 | 在线视频一区二区 | 亚洲激色 | 去看片| 最近日本韩国中文字幕 | 精品国产aⅴ一区二区三区 在线直播av | 国产欧美最新羞羞视频在线观看 | 特级大胆西西4444www | 日韩综合视频在线观看 | 五月婷婷丁香在线观看 | 久久久久久久久影院 | 日日夜夜天天久久 | 久久香蕉国产 | 成人久久影院 | 日韩精品中文字幕av | 久久,天天综合 | 日本丶国产丶欧美色综合 | 国产精品久久久久久久午夜片 | 国产午夜精品理论片在线 | 激情五月婷婷综合 | 国产va饥渴难耐女保洁员在线观看 | 99免费在线| 狠狠干网 | 国产玖玖在线 | 99精品视频在线观看免费 | 成年人国产视频 | 这里只有精彩视频 | 久久视屏网 | 美女视频一区二区 | 人人爽久久久噜噜噜电影 | 8x8x在线观看视频 | 久草在线最新视频 | 久久久久在线观看 | 久久爱992xxoo | 日韩亚洲在线视频 | 99re久久资源最新地址 | 99日精品| 国产精品男女视频 | av五月婷婷| 久草网在线视频 | 亚洲九九 | 99久久网站| 天天操天天色综合 | 亚洲精品乱码久久久久久蜜桃不爽 | 97热在线观看 | 97网在线观看 | 中文字幕区 | 99综合影院在线 | 亚洲天堂精品视频在线观看 | 成人免费一区二区三区在线观看 | www婷婷| 丝袜网站在线观看 | 91.精品高清在线观看 | 久草在线视频网站 | 在线免费视频一区 | 久久精品电影院 | 97视频在线观看成人 | 国产色视频一区二区三区qq号 | 亚洲码国产日韩欧美高潮在线播放 | 99热国产在线观看 | 久久久精品网 | 国产美女在线精品免费观看 | 天堂激情网 | 久久视频这里有精品 | 久久性生活片 | 婷婷丁香激情五月 | 黄色一级免费 | 99草视频| 手机成人av在线 | 中文不卡视频 | 久草在线一免费新视频 | 色中色亚洲 | 午夜av免费观看 | 国产一级一级国产 | 黄色一级网 | 国产精品大片免费观看 | 色狠狠一区二区 | 成人国产精品久久久春色 | 激情网五月婷婷 | 久久国产亚洲视频 | 在线精品视频免费观看 | 欧美一级裸体视频 | 一区二区三区不卡在线 | 国产精品国产三级国产不产一地 | 国产成人三级在线播放 | 久久精品高清 | 中文字幕一区二 | 91久久一区二区 | 日韩久久久久久久久 | 黄色片免费看 | 久久人人97超碰国产公开结果 | 92国产精品久久久久首页 | 国产视频一区二区三区在线 | 91天天操| av免费线看| 中文字幕在线观看免费 | www.夜夜操.com| 成人黄色大片 | 性色av一区二区三区在线观看 | 免费日韩电影 | 麻豆 91 在线 | 九九视频在线观看视频6 | 婷婷亚洲综合 | 69国产精品视频免费观看 | 97色在线视频 | 色婷婷综合久久久中文字幕 | 91香蕉视频好色先生 | 美女免费视频一区 | 久久香蕉电影 | 欧美激情h| 天天射天天射天天射 | 欧美日韩综合在线观看 | 91大神免费视频 | 午夜久久影院 | 99精品视频一区二区 | 91色国产在线 | 免费在线a | 夜夜视频 | 成人欧美日韩国产 | 天堂va在线观看 | 中文字幕在线看视频国产 | 免费看黄电影 | 亚洲 欧美 变态 国产 另类 | 亚洲dvd| 国产精品美乳一区二区免费 | 久久激情视频 久久 | 亚洲精品videossex少妇 | 天天色天天射综合网 | 99久久精品免费看国产麻豆 | 日韩欧美高清不卡 | 久久官网| 日韩r级电影在线观看 | 国产精品日韩在线观看 | 日韩av免费在线看 | 久久国产影视 | 能在线观看的日韩av | 亚洲国产精品久久久久久 | 99免费在线| 精品一区二区精品 | 久久99视频免费 | 人人精久 | 99操视频| 午夜av免费看 | 国产96在线观看 | 五月天亚洲综合 | 一区二区激情 | 国产福利专区 | 精品国产欧美 | 91色欧美| 青青河边草免费直播 | 亚洲精品99久久久久中文字幕 | 国产a国产 | 久久综合欧美精品亚洲一区 | 中文字幕乱在线伦视频中文字幕乱码在线 | www亚洲精品 | 一区三区在线欧 | 91麻豆免费版 | 日本最新高清不卡中文字幕 | 少妇视频在线播放 | 九九视频精品免费 | 九九免费在线看完整版 | 麻豆视频大全 | 欧美最猛性xxxxx免费 | 欧美日韩不卡在线视频 | 国产色拍拍拍拍在线精品 | 黄色成人在线观看 | www.啪啪.com| 天天干天天操天天爱 | 99精品网站| av在线小说 | 不卡国产视频 | 久久久久久久久久久精 | 欧美精品久久久久久久久老牛影院 | 欧美男男激情videos | 国产91国语对白在线 | 日本中文字幕视频 | av三级av | 五月天综合色 | 欧洲精品码一区二区三区免费看 | 色婷婷a| 蜜臀一区二区三区精品免费视频 | 在线观看完整版 | 久久久久网站 | 亚洲成人黄| 九九在线视频免费观看 | 天天干 夜夜操 | 成人 亚洲 欧美 | 成年人国产在线观看 | 欧美在线99 | 狠狠色丁香久久婷婷综合_中 | 日韩中文字幕免费 | 中文字幕乱码电影 | 久久黄页 | 精品 一区 在线 | 很黄很污的视频网站 | 黄色小说在线观看视频 | 人人澡视频 | a午夜电影 | 中文字幕在线观 | 色在线亚洲 | 亚洲成a人片77777kkkk1在线观看 | 美女久久一区 | 国产一区网址 | 日韩三级免费观看 | 亚洲最新av网址 | 91九色网站| 欧美一区二区三区激情视频 | 色香天天 | 天天操狠狠操夜夜操 | 91激情在线视频 | 亚州精品国产 | 一级做a视频 | 日韩免费 | 亚洲精品国偷拍自产在线观看蜜桃 | 色网站黄 | 亚洲第一成网站 | 91少妇精拍在线播放 | 手机成人免费视频 | 成人免费网站在线观看 | 久久久久久蜜桃一区二区 | 国产成人亚洲在线观看 | 96亚洲精品久久 | 久久夜色精品国产欧美乱极品 | 中文在线a∨在线 | av色综合网 | 91亚洲成人 | 美女又爽又黄 | 在线电影日韩 | 久久久久久久久久久福利 | 国产成人精品久 | 亚洲天堂色婷婷 | 激情在线网站 | av网站手机在线观看 | 日韩在线观看第一页 | 午夜视频福利 | 免费av电影网站 | 国产夫妻性生活自拍 | 黄网站大全 | 欧美色婷婷 | 久久综合加勒比 | 激情综合电影网 | 就色干综合 | 91九色porny在线| 欧美精品一级视频 | 国产免费专区 | 欧美日韩国产成人 | 国产精品第72页 | 亚洲国产免费看 | 91亚洲狠狠婷婷综合久久久 | 欧美日韩3p| 久久久国产在线视频 | 中文字幕在线免费观看 | 国产精品成 | 99精品国产成人一区二区 | 成人一级片免费看 | 日韩色在线观看 | 中文字幕久久亚洲 | 日韩精品一卡 | 六月丁香婷婷网 | 国语黄色片 | 亚洲国产精品电影 | 91麻豆精品91久久久久同性 | 日韩av高清| a在线观看国产 | 日本中文字幕在线看 | 亚洲综合视频在线观看 | 超碰成人av| 日韩性xxxx | 特级a老妇做爰全过程 | 天天综合网 天天综合色 | 九九热av| 久久影视一区 | 亚洲精品乱码久久久久v最新版 | 国产成人亚洲在线观看 | 久久成人国产精品入口 | 免费av影视 | 中文字幕一区二 | 精品久久久久久久 | 日韩视频精品在线 | 精品国产乱码一区二区三区在线 | www五月 | 色姑娘综合 | 99热在线国产精品 | 国内精品久久久久久久久久 | 日韩免费视频 | 97在线看片| 九九在线视频免费观看 | 嫩嫩影院理论片 | 在线视频免费观看 | 久久www免费视频 | 欧美一区免费观看 | 国产精品电影一区 | 欧美激情视频免费看 | 丁香激情综合 | 国产乱码精品一区二区三区介绍 | 91网址在线 | aa一级片| 免费观看成人网 | 久精品一区 | 国产一区二区三区高清播放 | 日本久久成人中文字幕电影 | 成人av片免费看 | 国产3p视频 | 久久久综合精品 | www.久久免费 | 国产一级视频在线免费观看 | 亚洲免费公开视频 | 97色se| 在线a人v观看视频 | 久久高清免费视频 | 一级片色播影院 | 综合色亚洲 | 国产一区电影在线观看 | 99久久精品国产欧美主题曲 | 99久久婷婷国产综合亚洲 | 亚洲国产美女精品久久久久∴ | av丁香花 | 久久不卡av| 国产精品福利午夜在线观看 | 亚洲精品黄色在线观看 | 亚洲精品乱码久久久久久9色 | 免费进去里的视频 | 五月婷视频 | 亚洲精品午夜国产va久久成人 | 日日干天天插 | 黄色免费看片网站 | 99久久精品无码一区二区毛片 | 久草视频中文在线 | 国产精品18久久久久vr手机版特色 | 日韩特黄av| 国产精品久久久久久a | av 一区 二区 久久 | 又黄又爽的免费高潮视频 | 欧美亚洲国产一卡 | 久久久久激情 | 在线欧美国产 | 超碰在线观看av | 精品伊人久久久 | av一级久久 | 亚洲激情六月 | 在线黄色av电影 | 91av视频播放| 夜夜骑首页 | 夜夜视频欧洲 | 国产精品国产亚洲精品看不卡 | 免费在线观看成人小视频 | 最新av免费在线观看 | 在线精品观看 | 亚州精品成人 | 中文字幕日韩一区二区三区不卡 | 天天操天天干天天操天天干 | 婷婷亚洲综合五月天小说 | 亚洲国产色一区 | 超碰人在线 | 国产91欧美 | www五月天com| 999久久久国产精品 高清av免费观看 | 国产在线a视频 | 久久与婷婷 | 97爱 | 一区二区三区高清在线观看 | 亚洲h在线播放在线观看h | 热久久这里只有精品 | 国产精品一区二区三区在线播放 | 亚洲综合日韩在线 | 麻豆一二三精选视频 | 91精品视频在线看 | 日韩在线观看 | 夜夜爱av | 99久久精品国 | 中文字幕亚洲欧美日韩2019 | 丁香六月婷婷开心 | 中文字幕综合在线 | 国产成人精品午夜在线播放 | 久久久影院官网 | 草免费视频 | 国产精品中文字幕在线观看 | 国产精品影音先锋 | 涩五月婷婷| 免费在线一区二区 | 欧美精品在线观看免费 | 欧美日本在线视频 | 综合色中文 | 欧美精品久久久久久久亚洲调教 | 亚洲一级电影视频 | 免费视频一级片 | 五月丁色 | 男女视频国产 | 91在线porny国产在线看 | 久久国产福利 | 日韩精品一卡 | 欧美视频18 | 久久婷婷一区二区三区 | 97成人在线视频 | 成人免费网站视频 | 久久99亚洲精品久久久久 | 欧美一级特黄高清视频 | 欧美日本国产在线观看 | 免费网站在线观看人 | 亚洲国产成人精品久久 | 国产精品自在线拍国产 | 国产成人精品一区二区在线 | 肉色欧美久久久久久久免费看 | 人人澡超碰碰97碰碰碰软件 | 日韩在线视频一区 | 99久久精品国产一区二区三区 | 色视频在线 | 欧美一二三视频 | 人人爽人人| 久久一区91| 韩国一区二区三区在线观看 | 色天天久久 | 国产91精品一区二区麻豆网站 | 久久午夜影院 | 久久久国产精品麻豆 | www..com毛片 | 色婷婷综合在线 | 久久国产精品久久精品国产演员表 | 国产a级精品 | 黄色的网站在线 | 日韩视频免费观看高清完整版在线 | 天天摸天天舔天天操 | 日韩在线中文字幕视频 | www日| 免费观看www视频 | 五月婷婷导航 | 97精品国产97久久久久久免费 | 国产69熟 | 黄色免费看片网站 | 久久www免费视频 | 日韩av影视 | 日韩一级电影在线 | 99久久精品国产毛片 | 欧美日韩电影在线播放 | 中文字幕精品一区 | 国产色婷婷精品综合在线手机播放 | 国产精品高潮久久av | 精品在线亚洲视频 | 四虎永久视频 | 日韩精品欧美精品 | 免费高清在线观看电视网站 | 国产不卡在线播放 | 欧美日韩在线观看一区 | 国产小视频精品 | 久久亚洲国产精品 | 夜夜干天天操 | 五月天久久狠狠 | 91丨九色丨国产在线 | 欧美日韩不卡在线观看 | 99久久精品国产一区二区三区 | 天天操天天操天天操天天操天天操天天操 | 有码中文字幕在线观看 | 天天天天射 | 91网站免费观看 | 免费看国产一级片 | 免费在线观看黄网站 | 亚洲婷久久 | 日韩综合一区二区三区 | 天天射色综合 | 一级片视频在线 | 日韩欧美国产免费播放 | 精品久久久久久久久亚洲 | 亚洲精品在线一区二区三区 | 黄色小说免费在线观看 | 色综合国产 | 在线中文字幕av观看 | 97精品国自产拍在线观看 | 国产福利91精品 | 91免费试看| 亚洲国产精品资源 | 国产免费嫩草影院 | 天天操比 | 亚洲精品玖玖玖av在线看 | 国产高清在线永久 | 亚洲黄色片在线 | 91av片 | 国产精品久久久久久久久久久久 | 蜜桃麻豆www久久囤产精品 | 国产在线精品视频 | 亚洲 欧美 综合 在线 精品 | 亚洲国产影院 | 天天爱天天射天天干天天 | 精品久久一区 | 亚洲色影爱久久精品 | 九九色综合 | 欧美一二三四在线 | 日韩在线视频观看免费 | 99久久婷婷国产综合精品 | 久久97超碰 | 亚洲少妇天堂 | 国产精品午夜8888 | 久久五月激情 | 成人免费 在线播放 | 国产成人久久精品亚洲 | 精品欧美一区二区三区久久久 | 国产精品福利久久久 | 国产一区二区精品久久91 | 亚洲精品久久激情国产片 | 91视频免费观看 | 久久久久免费网站 | 久久久www成人免费精品张筱雨 | 国内成人综合 | 在线小视频你懂得 | 久久久久久久久久久久久9999 | 久久九九视频 | 欧美精品乱码久久久久 | 欧美整片sss| av在线免费不卡 | 九九免费在线观看 | 亚洲影视资源 | 久久高清国产视频 | 97视频人人澡人人爽 | 麻豆91精品91久久久 | 中文字幕在线观看第三页 | 日日综合网 | 手机在线看永久av片免费 | 成人影片在线免费观看 | 久久综合免费 | 伊人资源站 | 国产精品毛片久久久久久久 | 在线黄色免费 | 伊人天天色| 天天色天天射天天综合网 | 91xav | 蜜臀av性久久久久av蜜臀三区 | 超碰97人人射妻 | 91在线中字 | 丁香九月婷婷 | 成片免费观看视频999 | 国产裸体永久免费视频网站 | 免费av电影网站 | 国产视频亚洲精品 | 久久精彩 | 中文字幕电影一区 | 久草在线网址 | 国产精品高清一区二区三区 | 欧美日韩三级在线观看 | 久久社区视频 | 久久婷婷色综合 | 国产aaa毛片| 草免费视频 | 国产精品伦一区二区三区视频 | 成人在线网站观看 | 丝袜美腿av | 国产亚洲视频在线免费观看 | 久久免费大片 | 国产精品a级 | 激情视频免费在线 | 久久久午夜视频 | 啪啪激情网 | 久久毛片网站 | 一区二区三区视频网站 | 久久色亚洲 | 欧美一级爽 | 精品久久免费 | 五月婷婷久久丁香 | 最近字幕在线观看第一季 | 玖玖在线观看视频 | 日韩欧美xxx | 日韩av网站在线播放 | 久久色视频| 欧美最爽乱淫视频播放 | 黄色成人影视 | 亚洲一区免费在线 | 在线成人免费电影 | 精品国产区在线 | 国产99久久九九精品免费 | 中文字幕日韩一区二区三区不卡 | 久久精品久久久久久久 | 国产精品一区在线观看 | 亚洲在线精品视频 | 国产一区成人 | 热久久在线视频 | 亚洲视频axxx| 一区二区视频免费在线观看 | 伊人久久av | 永久免费av在线播放 | 最近中文字幕免费大全 | 久久久资源网 | 91大神免费视频 | 国产在线精品二区 | 国产精品18毛片一区二区 | 成 人 a v天堂 | 最新不卡av | 最近中文字幕免费av | 成人97人人超碰人人99 | 色老板在线视频 | 欧美日韩在线视频一区 | 日日天天干| 成人性生交大片免费观看网站 | 深夜国产福利 | 高清av免费一区中文字幕 | 亚洲国产精品一区二区久久hs | 久久免费视频精品 | 顶级欧美色妇4khd | 久久精品第一页 | 精品亚洲成人 | 欧美日韩1区2区 | 久久久电影网站 | 毛片99| www99精品| 国产精品中文字幕av | 天天干,天天操,天天射 | 欧美日韩精品在线视频 | 麻豆你懂的| 玖玖玖精品 | 日韩欧美国产成人 | 成人av网站在线播放 | 亚洲播放一区 | 婷婷综合久久 | 国产精品毛片一区二区 | 一区二区三区精品在线 | 亚洲国产激情 | 丁香花在线视频观看免费 | 欧美黄色软件 | 中文字幕之中文字幕 | 在线免费高清一区二区三区 | 狠狠操狠狠 | 欧洲精品二区 | 国产999精品久久久久久 | 中文字幕av免费在线观看 | 久草精品视频在线看网站免费 | 99精品视频在线观看免费 | 国产69精品久久久久久 | 五月婷婷丁香在线观看 | 在线观看视频中文字幕 | 国产精品美女999 | 99精品视频免费 | 天天操一操 | 精品久久久久久亚洲综合网站 | 成人在线免费av | 91人人在线 | 婷婷亚洲最大 | 国产精品久久久久久久久毛片 | 亚洲国产中文字幕在线观看 | 亚洲成人软件 | 欧美一区二区日韩一区二区 | 国产视频精品在线 | 亚洲成人影音 | 国产一级黄色av | 国产在线精品区 | 久久这里只有精品9 | 黄色国产区 | 国产精品一二 | 黄色小说在线观看视频 | 免费在线一区二区三区 | 五月婷婷精品 | 97精品在线 | 国产精品嫩草55av | 欧美一级日韩三级 | 天天干天天草天天爽 | www91在线观看 | 久久综合九色综合欧美狠狠 | 在线观看黄av | 九九九九热精品免费视频点播观看 | 国产亚洲一区二区在线观看 | 亚洲国产免费 | 国产一二三精品 | 国产一区二区不卡视频 | 中文字幕久久久精品 | 在线电影播放 | 久久黄色免费观看 | 成年人电影免费在线观看 | 中文在线| 欧美黑人xxxx猛性大交 | 黄色小说免费观看 | 欧美日韩一区三区 | 综合激情伊人 | 日韩综合一区二区三区 | 99精品视频免费在线观看 | 亚洲精品中文字幕在线 | 热久久最新地址 | 99久久精品日本一区二区免费 | 久久免费视频99 | 一本色道久久综合亚洲二区三区 | 国产小视频在线观看免费 | 久久艹艹 | 蜜桃视频色 | 免费三级av | 欧洲亚洲女同hd | 在线精品在线 | 精品国产乱码 | 欧美高清成人 | 91av网址| 久久久久久久久久亚洲精品 | 久久久黄视频 | 精品在线二区 | 在线草| 久久久精品成人 | 免费av网址在线观看 | 久久99精品视频 | 五月天电影免费在线观看一区 | 亚洲激情影院 | 亚洲视屏| 中文字幕亚洲欧美日韩 | aav在线| 久久综合久色欧美综合狠狠 | 亚洲成人黄色在线 | 亚洲一区二区观看 | 久久精品视频中文字幕 | 一级性视频 | 黄色成人在线 | 在线a人片免费观看视频 | 激情久久一区二区三区 | 人人爽人人爽人人片av免 | 亚洲国产精品成人精品 | 国产精品永久免费观看 | 伊人久久精品久久亚洲一区 | 免费视频 你懂的 | 久久精品播放 | 国产一区二区三区免费在线 | 久草久热 | 人人草在线观看 | 在线电影播放 | 黄色国产在线观看 | 婷婷丁香综合 | 免费观看一级成人毛片 | 久久久国产精品视频 | 婷婷丁香七月 | 久久综合欧美 | 国产一级特黄电影 | 成人国产在线 | 91精品入口 | av成人资源 | 成人久久久久 | 超碰在线观看av | 天天爱天天操天天射 | 日本精品视频一区 | 久久蜜臀av | 久久精品视频网 | 人人爽人人插 | 日本韩国中文字幕 | 久久精品国产精品亚洲 | 久草视频国产 | 国产玖玖在线 | 精品中文字幕在线播放 | 婷婷久操 | 国产亚洲精品久久久久久移动网络 | 国内精品久久久久久久97牛牛 | 特片网久久 | 免费h在线观看 | 青青河边草免费观看完整版高清 | 国产原创在线视频 | 天天av天天 | 亚洲日日夜夜 | 91在线视频在线观看 | 成 人 免费 黄 色 视频 | 亚洲国产黄色片 | 国产成本人视频在线观看 | 亚洲狠狠丁香婷婷综合久久久 | 免费看的黄色录像 | 高清日韩一区二区 | 欧美一区免费在线观看 | 99久久精品国 | 毛片一区二区 | 久久综合色影院 | 六月色丁香 | 久久99国产精品免费 | 久久免费国产视频 | 黄色在线观看www | 久久久一本精品99久久精品66 | 亚洲区视频在线观看 | 欧美精品一区二区在线播放 | 国产精品精 | 国产成人精品一区二区三区在线观看 | 日本激情动作片免费看 | 久草在线99 | 国产97视频 | 久草综合在线观看 | 国产精品 9999 | 国产亚洲久一区二区 | 国产成年免费视频 | 最新国产精品久久精品 | 91人人爽久久涩噜噜噜 | 精品国产成人 | 欧美日一级片 | 国产一区自拍视频 | 狠狠干夜夜操 | 人九九精品 | 2019中文在线观看 | 天天干视频在线 | 欧美色精品天天在线观看视频 | 国产在线免费av | 国产 日韩 欧美 中文 在线播放 | 日韩在线高清视频 | 三上悠亚一区二区在线观看 | 国产精品久久久久久久久岛 | 亚洲一级片在线观看 | av成人资源 | 九九免费精品视频在线观看 | 日韩综合视频在线观看 | 亚洲 欧美 国产 va在线影院 | 99视频国产精品 | 中文字幕精品一区 | 久久久人人爽 | 欧美性生活免费看 | 婷婷 综合 色| 欧美天堂久久 | 字幕网资源站中文字幕 | 亚洲aⅴ乱码精品成人区 | av天天干 | 日韩av中文 | 国产日韩高清在线 | 亚洲专区欧美 | 最近中文字幕免费 | 亚洲精色 | 干亚洲少妇 | 人人射网站| 看片在线亚洲 | 激情综合站 | 日韩a级免费视频 | av高清一区二区三区 | av福利电影 | 色婷婷国产精品一区在线观看 | 久久精品牌麻豆国产大山 | 久久精品欧美一区二区三区麻豆 | 四虎成人在线 | 国产精品一区二区视频 | 啪啪小视频网站 | 97高清免费视频 | 免费av福利 | 四虎影视av | 国产99久久久精品 | 狠狠狠狠狠狠天天爱 | 久热爱 | 天天干,天天插 | 国内精品视频免费 | 久草在线免费在线观看 | 在线电影播放 | 精品高清视频 | 欧美极品xxx| 99亚洲视频 | 欧美精品一区二区三区一线天视频 | 久草精品视频 | 2019中文最近的2019中文在线 | 操操综合网 | 国模精品一区二区三区 | 精品国产乱码久久久久久天美 | 国产一区福利 | 国产99在线播放 | 深爱激情久久 | 国产精品永久久久久久久www | 成人免费视频在线观看 | 97电影院在线观看 | 国产区精品在线观看 | 久久久久日本精品一区二区三区 | 精品福利在线视频 | 国产精品精品国产 | 成人黄色大片 | 激情婷婷丁香 | 在线日韩三级 | 久久久免费观看视频 | 中文一区在线观看 | 日韩在线理论 | 精品999国产 | 不卡的av电影 | 亚洲黄色小说网 | 久久五月婷婷综合 | 伊人影院得得 | 国产中文在线字幕 | 国产精品 日本 | 正在播放国产一区 | 在线91视频 | www黄色com | 午夜.dj高清免费观看视频 | 亚洲自拍偷拍色图 | 国产首页 | 欧美日韩在线观看一区 | 在线观看视频黄 | 日韩视频免费在线观看 | 狠狠躁夜夜躁人人爽超碰97香蕉 | 97超视频| 一本到在线| av无限看| 久久精品视频在线 | 国产精品久久久久aaaa九色 | 国产视频精品免费播放 | 国产精品视频专区 | 国产一级二级av | 日韩伦理片一区二区三区 | www.国产高清| 欧美精品一二三 | 免费观看性生活大片3 | 免费观看一区二区 | 黄色av电影一级片 | 国产综合精品久久 | 日韩精品最新在线观看 | 久久久久久不卡 | 国产乱老熟视频网88av | 日韩美一区二区三区 | 四虎免费在线观看视频 | 久久久久久免费网 |