注意:如果是编写的驱动在本机系统上用,则不必编译内核;如果是要在其他的系统上用,要编译成功目标机的内核版本。如果是第一种场景,则直接跳过章节1
1. 编译内核
首先查看一下内核版本
qpp@qpp-virtual-machine:$ uname -r
5.4.0-72-generic
这是我的内核版本。
安装编译时必须的依赖
qpp@qpp-virtual-machine:$ sudo apt-get install gcc make libncurses5-dev openssl libssl-dev
qpp@qpp-virtual-machine:$ sudo apt-get install build-essential
qpp@qpp-virtual-machine:$ sudo apt-get install libc6-dev
qpp@qpp-virtual-machine:$ sudo apt-get install bison
qpp@qpp-virtual-machine:$ sudo apt-get install flex
qpp@qpp-virtual-machine:$ sudo apt-get install libelf-dev
下载对应的内核源码
官网下载地址
编译
# 解压下载的内核源码
qpp@qpp-virtual-machine:$ sudo tar -zxvf linux-source-5.4.tar.bz2 -C ~/linux-kernel
# 到解压后的源码目录下
qpp@qpp-virtual-machine:$ cd ~/linux-kernel/linux-5.4/
# 配置,一路按“回车”
qpp@qpp-virtual-machine:/linux-kernel/linux-5.4$ sudo make oldconfig
# 编译,时间会比较久
qpp@qpp-virtual-machine:/linux-kernel/linux-5.4$ sudo make
qpp@qpp-virtual-machine:/linux-kernel/linux-5.4$ sudo make modules
qpp@qpp-virtual-machine:/linux-kernel/linux-5.4$ sudo make modules_install
# 在lib/modules目录中生成设备树
qpp@qpp-virtual-machine:/linux-kernel/linux-5.4$ cd /lib/modules
qpp@qpp-virtual-machine:/lib/modules$ ll
总用量 16
drwxr-xr-x 4 root root 4096 4月 16 10:30 ./
drwxr-xr-x 21 root root 4096 4月 15 22:38 ../
drwxr-xr-x 5 root root 4096 4月 15 22:46 5.4.0-42-generic/
drwxr-xr-x 5 root root 4096 4月 16 10:31 5.4.0-72-generic/
qpp@qpp-virtual-machine:/lib/modules$
我在编译的过程中,始终报下列错误,换了几个版本的源码也一样,因为驱动是用于本机版本,所以这个问题久暂时搁下了,我也没有找到解决方案,如果有小伙伴知道,请留言告诉我,感谢!!!
make[1]: *** 没有规则可制作目标“debian/canonical-certs.pem”,由“certs/x509_certificate_list” 需求。 停止。
Makefile:1734: recipe for target 'certs' failed
make: *** [certs] Error 2
2. 驱动demo
2.1 驱动程序
USB_INTERFACE_CLASS_HID:表示接口,每个接口代表一个功能
USB_INTERFACE_SUBCLASS_BOOT:自类
USB_INTERFACE_PROTOCOL_MOUSE:协议
2.2 Makefile
TBD.
2.3 测试程序
测试的时候,先把内核USB驱动关闭
/lib/modules/$ make menuconfig
3. USB驱动demo
首先对USB驱动有个感性的认识,我们看一下鼠标的驱动是怎样工作起来的:
系统驱动的输入设备中,有三个mouse
qpp@qpp-virtual-machine:/dev/input$ ls
by-id by-path event0 event1 event2 event3 event4 mice mouse0 mouse1 mouse2
我们先看一下mouse0:
qpp@qpp-virtual-machine:/dev/input$ sudo hexdump mouse0
0000000 0028 2881 bb00 0128 28fc fc01 0128 28fd
0000010 fd02 0128 28ff ff01 0128 28fe ff00 0108
0000020 2800 ff01 0008 0801 0100 0008 0802 0100
0000030 0008 0801 0200 0008 0802 0200 0008 1801
0000040 02ff 0008 0801 0200 0008 0802 0100 0008
0000050 0801 0100 0108 0800 0200 0108 0801 0101
0000060 0108 0800 0101 0008 0801 0001 0008 0801
0000070 0100 0008 1801 01ff 0008 1802 01ff ff18
0000080 1802 01ff 0008 1802 02ff fe18 1802 08fd
0000090 fd18 1807 05fe ff18 1805 07fd fe18 1806
00000a0 04ff ff18 1807 03ff ff18 0801 0200 0008
00000b0 1801 01ff 0008 0801 0200 fe18 0804 0300
00000c0 fe18 1807 05fe ff18 1804 06ff fd18 1807
00000d0 04ff ff18 1804 09fe ff18 1805 05ff fe18
00000e0 1808 06fe fe18 0804 0100 0008 0801 0504
00000f0 0408 0804 0806 0408 0806 0603 0308 0802
0000100 0402 0008 0801 0101 0108 0805 0001 0008
0000110 0802 0102 0008 0802 0100 0008 1801 02ff
^C
qpp@qpp-virtual-machine:/dev/input$
可以看到,在移动鼠标的过程中,会输出坐标值。具体是啥原理呢?我暂时也不知道,O(∩_∩)O哈哈~
先设定一个目标:
- 点击鼠标左键,终端输出“hello world!”;
- 点击鼠标右键,终端输出“0123456789”;
3.1 驱动程序
USB的应用开发大部分是在usb_drv_probe中。
按键:
# 按下
30 dd 5a 7d 60 0 0 0 0 8c e4 4 0 0 0 0 0 4 0 4 0 1 0 9 0 dd 5a 7d 60 0 0 0 0 8c e4 4 0 0 0 0 0 1 0 20 1 1 0 0 0
18 dd 5a 7d 60 0 0 0 0 8c e4 4 0 0 0 0 0 0 0 0 0 0 0 0 0
# 松开
30 e0 5a 7d 60 0 0 0 0 fb f0 2 0 0 0 0 0 4 0 4 0 1 0 9 0 e0 5a 7d 60 0 0 0 0 fb f0 2 0 0 0 0 0 1 0 20 1 0 0 0 0
18 e0 5a 7d 60 0 0 0 0 fb f0 2 0 0 0 0 0 0 0 0 0 0 0 0 0
全部的log
size:30 eb 5e 7d 60 0 0 0 0 8c 4a 3 0 0 0 0 0 4 0 4 0 1 0 9 0 eb 5e 7d 60 0 0 0 0 8c 4a 3 0 0 0 0 0 1 0 20 1 1 0 0 0
size:18 eb 5e 7d 60 0 0 0 0 8c 4a 3 0 0 0 0 0 0 0 0 0 0 0 0 0
size:30 eb 5e 7d 60 0 0 0 0 40 46 9 0 0 0 0 0 4 0 4 0 1 0 9 0 eb 5e 7d 60 0 0 0 0 40 46 9 0 0 0 0 0 1 0 20 1 0 0 0 0
size:18 eb 5e 7d 60 0 0 0 0 40 46 9 0 0 0 0 0 0 0 0 0 0 0 0 0
size:30 ef 5e 7d 60 0 0 0 0 56 a8 3 0 0 0 0 0 4 0 4 0 1 0 9 0 ef 5e 7d 60 0 0 0 0 56 a8 3 0 0 0 0 0 1 0 20 1 1 0 0 0
size:18 ef 5e 7d 60 0 0 0 0 56 a8 3 0 0 0 0 0 0 0 0 0 0 0 0 0
size:30 ef 5e 7d 60 0 0 0 0 2c 2c 8 0 0 0 0 0 4 0 4 0 1 0 9 0 ef 5e 7d 60 0 0 0 0 2c 2c 8 0 0 0 0 0 1 0 20 1 0 0 0 0
size:18 ef 5e 7d 60 0 0 0 0 2c 2c 8 0 0 0 0 0 0 0 0 0 0 0 0 0
size:30 f2 5e 7d 60 0 0 0 0 9c 51 7 0 0 0 0 0 4 0 4 0 1 0 9 0 f2 5e 7d 60 0 0 0 0 9c 51 7 0 0 0 0 0 1 0 20 1 1 0 0 0
size:18 f2 5e 7d 60 0 0 0 0 9c 51 7 0 0 0 0 0 0 0 0 0 0 0 0 0
size:30 f2 5e 7d 60 0 0 0 0 e1 97 b 0 0 0 0 0 4 0 4 0 1 0 9 0 f2 5e 7d 60 0 0 0 0 e1 97 b 0 0 0 0 0 1 0 20 1 0 0 0 0
size:18 f2 5e 7d 60 0 0 0 0 e1 97 b 0 0 0 0 0 0 0 0 0 0 0 0 0
size:30 f3 5e 7d 60 0 0 0 0 2e 34 c 0 0 0 0 0 4 0 4 0 1 0 9 0 f3 5e 7d 60 0 0 0 0 2e 34 c 0 0 0 0 0 1 0 20 1 1 0 0 0
size:18 f3 5e 7d 60 0 0 0 0 2e 34 c 0 0 0 0 0 0 0 0 0 0 0 0 0
size:30 f3 5e 7d 60 0 0 0 0 2c 66 e 0 0 0 0 0 4 0 4 0 1 0 9 0 f3 5e 7d 60 0 0 0 0 2c 66 e 0 0 0 0 0 1 0 20 1 0 0 0 0
size:18 f3 5e 7d 60 0 0 0 0 2c 66 e 0 0 0 0 0 0 0 0 0 0 0 0 0
要做消抖处理,在读到有数据值后,开启定时器,并检到松开,是一个完整的事件被触发。
3.2 Makefile
TBD.
3.3 测试程序
驱动加载到内核:
# xxxxxxx.ko是你编写的驱动程序
insmod xxxxxxx.ko
系统日志相关命令:
# 查看系统日志
dmesg
# 清理系统日志文件
dmesg -c
4. 参考资料
【1】Ubuntu搭建驱动开发环境
【2】Ubuntu搭建驱动开发环境
【3】【转载】Ubuntu 14.04上驱动开发环境配置,及最简单一个驱动编写。
【4】Ubuntu18.04.4下载编译内核源码
【5】Linux usb 驱动程序范例
【6】如何编写Linux设备驱动程序以及测试详细流程(附实例)
【7】Linux设备驱动之HID驱动—非常全面而且深刻
【8】Linux的文件I/O概述
【9】linux 处理键盘 鼠标事件