本帖最后由 sandman78 于 2017-6-26 09:32 编辑
开发板上S2为用户按键,按下按键会引起中断,中断服务程序会产生事件,该事件通过EVDEV返回到用户程序。我们在获取输入设备的事件时往往通过/dev/input/eventx来获取,通过open read操作完成。 通过命令捕获按键状态
使用下面的命令获取按键对应的事件名- $ cat /proc/bus/input/devices
- ...省略无关显示
- I: Bus=0019 Vendor=0001 Product=0001 Version=0100
- N: Name="gpio-keys"
- P: Phys=gpio-keys/input0
- S: Sysfs=/devices/platform/gpio-keys/input/input2
- U: Uniq=
- H: Handlers=kbd event2
- B: PROP=0
- B: EV=3
- B: KEY=4
从最后一段可知Name="gpio-keys"对应的是Handlers=kbd event2
访问event2的设备结点捕获按键状态- $ cat /dev/input/event2 | hexdump -C
- 00000000 78 77 09 59 68 2e 03 00 01 00 02 00 00 00 00 00 |xw.Yh...........|
- 00000010 78 77 09 59 68 2e 03 00 00 00 00 00 00 00 00 00 |xw.Yh...........|
- 00000020 78 77 09 59 ef b9 0b 00 01 00 02 00 01 00 00 00 |xw.Y............|
- 00000030 78 77 09 59 ef b9 0b 00 00 00 00 00 00 00 00 00 |xw.Y............|
命令执行后处于等待状态,按下按键后将上报事件
中间两块为收到的数据,共有16列
- 第1列到第8列为事件发生的时间
- 第9第10列为 1 表示为按键事件
- 第13-16列为0表示按键按下, 为1表示按键释放
通过程序捕获按键状态
用Go来获取按键状态时,先打开/dev/input/event2文件,在阻塞读取数据,并通过Go的通信机制通知应用程序
代码分解程序开启两个goroutine,一个用于读取按键事件,另一个模拟应用,用于事件处理 - const keyEventFile = "/dev/input/event2"
- k, err := os.Open(keyEventFile)
定义文件名为常量,并打开文件
- data := make([]byte, 16)
- _, err := k.Read(data)
阻塞读取上报的数据
- var et uint16
- buf := bytes.NewReader(data[8:10])
- err = binary.Read(buf, binary.LittleEndian, &et)
提取事件类型,bytes用于处理数组切片,binary包用于字节序列和数据之间的转化,binary.LittleEndian表示采用小端方式处理
- if et == evKey {
- buf = bytes.NewReader(data[12:])
- err = binary.Read(buf, binary.LittleEndian, &value)
- }
如果事件类型为按键事件,继续读取4个字节数据,该数据表示是按下或释放按键
- ch := make(chan uint32)
- ch <- value
将收到的数据传递给应用程序,这里利用了Go提供的Channel通信机制, Channel是goroutine之间进行通信的一种方式
程序验证交叉编译并在开发板上运行
- 按下按键后,控制台输出"Key Pressed"
- 释放按键后,控制台输出"Key released"。
完整代码
- package main
- import (
- "bytes"
- "encoding/binary"
- "fmt"
- "os"
- )
- const keyEventFile = "/dev/input/event2"
- const evKey = 1
- func main() {
- k, err := os.Open(keyEventFile)
- check(err)
- defer k.Close()
- ch := make(chan uint32)
- go func() {
- data := make([]byte, 16)
- for {
- _, err := k.Read(data)
- check(err)
- var et uint16
- buf := bytes.NewReader(data[8:10])
- err = binary.Read(buf, binary.LittleEndian, &et)
- check(err)
- var value uint32
- if et == evKey {
- buf = bytes.NewReader(data[12:])
- err = binary.Read(buf, binary.LittleEndian, &value)
- check(err)
- ch <- value
- }
- }
- }()
- go func() {
- for {
- value := <-ch
- if value == 0 {
- fmt.Println("Key pressed")
- } else if value == 1 {
- fmt.Println("Key released")
- }
- }
- }()
- fmt.Println("Press enter key to exit")
- var b [1]byte
- os.Stdin.Read(b[:])
- }
- func check(err error) {
- if err != nil {
- panic(err)
- }
- }