ftdi_sio驱动学习笔记 1 - 注册与注销

目录

1. usb串口驱动模块

2. usb串口驱动数组ftdi_device

2.1 设备驱动属性

2.2 描述符

2.3 端口配置

2.4 操作接口函数


ftdi_sio是Linux内核中对FTDI设备的USB转串口的驱动程序。该源代码可以通过Linux源码下载,例如6.10.9版本的下载地址:

serial - drivers/usb/serial - Linux source code (v6.10.9) - Bootlin

和ftdi_sio有关的源文件是:ftdi_sio.c、ftdi_sio.h和ftdi_sio_ids.h。可以新建一个makefile文件

ifeq ($(KERNELRELEASE), )
KERNELDIR := /lib/modules/$(shell uname -r)/build
PWD :=$(shell pwd)
default:
	$(MAKE) -C $(KERNELDIR)  M=$(PWD)  
clean:
	rm -rf *.mk .tmp_versions Module.symvers *.mod.c *.o *.ko .*.cmd Module.markers modules.order *.a *.mod
load:
	insmod ftdi_sio.ko
unload:
	rmmod ftdi_sio
install: default
	rmmod ftdi_sio || true
	mkdir -p /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
	cp -f ./ftdi_sio.ko /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ || true
	modprobe ftdi_sio || true
#	depmod -a
uninstall:
	rmmod ftdi_sio || true
	rm -rf /lib/modules/$(shell uname -r)/kernel/drivers/usb/serial/ftdi_sio.ko || true
#	depmod -a
else
	obj-m := ftdi_sio.o
endif

命令make是编译生成ftdi_sio.ko,sudo make install是安装。

1. usb串口驱动模块

程序不是直接通过xxx_init和xxx_exit注册和注销的。它是通过通用usb串口设备的接口函数实现的。

module_usb_serial_driver(serial_drivers, id_table_combined);

在内核里面定义的这个接口module_usb_serial_driver和常规的驱动的实现方式是一样的。

#define usb_serial_module_driver(__name, __serial_drivers, __ids)	\
static int __init usb_serial_module_init(void)				\
{									\
	return usb_serial_register_drivers(__serial_drivers,		\
					   __name, __ids);		\
}									\
module_init(usb_serial_module_init);					\
static void __exit usb_serial_module_exit(void)				\
{									\
	usb_serial_deregister_drivers(__serial_drivers);		\
}									\
module_exit(usb_serial_module_exit);

对于参数__serial_drivers是一个串口驱动数组

static struct usb_serial_driver * const serial_drivers[] = {
	&ftdi_device, NULL
};

这里只有ftdi一种驱动,NULL则表示这个串口驱动数组的结尾。 

而参数__ids是USB设备的VID和PID数组。

2. usb串口驱动数组ftdi_device

static struct usb_serial_driver ftdi_device

这个结构体描述FTDI USB串行设备的属性和操作函数指针。它包含了设备的描述信息、端口数量、数据缓冲区大小等硬件特性,以及设备插拔、打开、关闭、控制信号等操作的函数指针。

所有的串口属性和操作都是这个结构体实现的,所以是重点学习的对象。

2.1 设备驱动属性

.driver = {
	.owner =	THIS_MODULE,
	.name =		"ftdi_sio",
	.dev_groups =	ftdi_groups,
},

这段代码是Linux设备驱动程序的一部分,用于注册一个名为"ftdi_sio"的设备驱动程序。其中,.owner字段表示该驱动程序所属的模块,.name字段指定了驱动程序的名称,.dev_groups字段指定了该设备支持的权限组。

static const struct attribute_group ftdi_group = {
	.attrs		= ftdi_attrs,
	.is_visible	= ftdi_is_visible,
};

static const struct attribute_group *ftdi_groups[] = {
	&ftdi_group,
	NULL
};

在 Linux 内核的设备模型中,`attribute_group` 结构体用于组织一组可被用户空间程序访问的设备属性。

  • attrs成员

每个 `attribute` 结构体代表一个可读或可写的设备属性,例如设备的状态、配置参数等。这些属性可以通过 `/sys/class/` 目录下的相应文件来访问。

static struct attribute *ftdi_attrs[] = {
	&dev_attr_event_char.attr,
	&dev_attr_latency_timer.attr,
	NULL
};

数组中的每个元素都是一个指向struct attribute结构体的指针。ftdi_attrs数组包含了两个设备属性:event_charlatency_timer,以及一个空指针NULL作为结束标志。

这2个属性的定义:

static DEVICE_ATTR_WO(event_char);
static DEVICE_ATTR_RW(latency_timer);

static DEVICE_ATTR_WO(event_char);:这行代码定义了一个名为event_char的只写设备属性。DEVICE_ATTR_WO宏创建了一个只能写入而不能读取的设备属性

static DEVICE_ATTR_RW(latency_timer);:这行代码定义了一个名为latency_timer的读写设备属性。DEVICE_ATTR_RW宏创建了一个可以读取和写入的设备属性。

  • is_visible成员

当用户尝试访问设备的属性时,内核会调用 `is_visible` 函数检查这些属性是否应该显示给用户。

总结来说,`ftdi_group` 定义了 FTDI 设备的一组属性及其可见性规则,使得用户空间程序能够通过 sysfs 文件系统接口安全地读取或修改设备状态。

在Ubuntu中可以查到这个设备的这些属性,如下图中的event_char和latency_timer。

:/sys/class/tty/ttyUSB0/device$ ls
driver  event_char  latency_timer  port_number  power  subsystem  tty  uevent

2.2 描述符

.description =		"FTDI USB Serial Device",

这是一串字符串,当设备插入和移除时在系统log中使用,例如输入命令"sudo dmesg | grep ftdi":

[ 7316.555196] ftdi_sio 2-1:1.0: FTDI USB Serial Device converter detected
[ 7316.564388] ftdi_sio 2-1:1.1: FTDI USB Serial Device converter detected
[ 7316.573474] ftdi_sio 2-1:1.2: FTDI USB Serial Device converter detected
[ 7316.582621] ftdi_sio 2-1:1.3: FTDI USB Serial Device converter detected

可以改一下这个字符串看一下效果。

2.3 端口配置

.num_ports =		1,
.bulk_in_size =		512,
.bulk_out_size =	256,
  • num_ports设定设备将拥有的不同端口的数量。这通常指的是USB设备上可连接外设的物理接口数量。
  • bulk_in_size设定每个批量输入端点的缓冲区大小,单位为字节。如果设置为0,则表示使用端点本身的默认大小。
  • bulk_out_size设定每个批量输出端点的缓冲区大小,单位为字节。同样,如果设置为0,则表示使用端点本身的默认大小。

2.4 操作接口函数

这些函数分2种情况,一种是使用usb串口标准的函数实现,而其他大部分函数是FTDI设备需要实现的。usb串口标准的函数实现有下面4种:

.throttle =		usb_serial_generic_throttle,
.unthrottle =		usb_serial_generic_unthrottle,
.tiocmiwait =		usb_serial_generic_tiocmiwait,
.get_icount =		usb_serial_generic_get_icount,
  • throttle: 数据流控制函数
  • unthrottle: 取消数据流控制
  • tiocmiwait: 等待调制解调器状态变化
  • get_icount: 获取串口的中断计数信息,并将这些信息存储在icount指向的结构体中

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mfbz.cn/a/882384.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Netty笔记10-Netty参数调优

文章目录 一、CONNECT_TIMEOUT_MILLISCONNECT_TIMEOUT_MILLIS设置为1秒超时CONNECT_TIMEOUT_MILLIS设置为5秒超时注意事项 二、SO_BACKLOG代码示例注意事项 三、ulimit -n(文件描述符)设置文件描述符限制在注意事项 四、TCP_NODELAY使用 TCP_NODELAY 的场景注意事项 五、SO_SND…

JavaWeb--纯小白笔记03:servlet入门---动态网页的创建

笔记:index.html在tomcat中为默认的名字,html里面的语法不严谨。改配置文件要小心,不然容易删掉其他 Servlet:服务器端小程序,写动态网页需要用Servlet,普通的java类通过继承HttpServlet,可以响…

【重学 MySQL】三十一、字符串函数

【重学 MySQL】三十一、字符串函数 函数名称用法描述ASCII(S)返回字符串S中的第一个字符的ASCII码值CHAR_LENGTH(s)返回字符串s的字符数,与CHARACTER_LENGTH(s)相同LENGTH(s)返回字符串s的字节数,和字符集有关CONCAT(s1,s2,…,sn)连接s1,s2,…,sn为一个字…

Docker + Win 10 学习记录

下载Docker Release notes | Docker Docs 推荐使用4.33版本,最新的Docker版本在win10 22H2无法安装。需要升级到win11. 查看Win10版本是否与最新版的Docker兼容 运行 win R, 然后输入winver 如果你的Docker版本无法在当前的win10安装,请更…

828华为云征文|华为云Flexus云服务器X实例部署Xnote笔记应用

828华为云征文|华为云Flexus云服务器X实例部署Xnote笔记应用 前言一、Flexus云服务器X实例介绍1.1 Flexus云服务器X实例简介1.2 Flexus云服务器X实例特点1.3 Flexus云服务器X实例使用场景 二、Note Mark 介绍2.1 Xnote简介2.2 Xnote特点2.3 主要使用场景 三、本次实…

豆包Python SDK接入流程

模型与价格 豆包的模型介绍可以看豆包大模型介绍,模型价格可以看豆包定价文档里的“模型推理” - “大语言模型” - “字节跳动”部分。 推荐使用以下模型: Doubao-lite-32k:每百万 token 的输入价格为 0.3 元,输出价格为 0.6 元…

JavaEE: 深入探索TCP网络编程的奇妙世界(六)

文章目录 TCP核心机制TCP核心机制九: 面向字节流TCP核心机制十: 异常处理 小小的补充(URG 和 PSH)~TCP小结TCP/UDP 对比用UDP实现可靠传输(经典面试题) 结尾 TCP核心机制 上一篇文章JavaEE: 深入探索TCP网络编程的奇妙世界(五) 书接上文~ TCP核心机制九: 面向字节流 TCP是面…

桶排序和计数排序(非比较排序算法)

桶排序 桶排序是一种基于分配的排序算法,特别适合用来排序均匀分布的数据。它的基本思想是将输入的数据分到有限数量的桶里,然后对每个桶内的数据分别进行排序,最后再将各个桶内的数据合并得到最终的排序结果。(通常用于浮点数,因…

Linux:RPM软件包管理以及yum软件包仓库

挂载光驱设备 RPM软件包管理 RPM软件包简介 区分软件名和软件包名 软件名:firefox 软件包名:firefox-52.7.0-1.el7.centos.x86_64.rpm 查询软件信息 查询软件(参数为软件名) ]# rpm -qa #当前系统中所有已安装的软件包 ]# r…

WebGL颜色与纹理

WEBGL中的着色器变量包括以下种类: 属性变量(Attribute Variables):这些变量用于接收从应用程序中传递的顶点数据,比如顶点位置和颜色,是只读的不可修改。统一变量(Uniform Variables&#xff…

AI浪潮新崛起:借助AI+实景/视频直播创新魅力,开启无人自动直播新时代!

AI浪潮新崛起:借助AI实景/视频直播创新魅力,开启无人自动直播新时代! 在科技日新月异的今天,人工智能(AI)已不再仅仅是科幻电影中的桥段,它正以不可阻挡之势渗透到我们生活的方方面面&#xff…

力扣718-最长重复子数组(Java详细题解)

题目链接:718. 最长重复子数组 - 力扣(LeetCode) 前情提要: 因为本人最近都来刷dp类的题目所以该题就默认用dp方法来做。 dp五部曲。 1.确定dp数组和i下标的含义。 2.确定递推公式。 3.dp初始化。 4.确定dp的遍历顺序。 5…

【编程底层原理】Java常用读写锁的使用和原理

一、引言 在Java的并发世界中,合理地管理对共享资源的访问是至关重要的。读写锁(ReadWriteLock)正是一种能让多个线程同时读取共享资源,而写入资源时需要独占访问的同步工具。本文将带你了解读写锁的使用方法、原理以及它如何提高…

这8款AI论文工具帮你一键搞定!ai论文一键生成任务书

在当今学术研究和论文写作领域,AI技术的应用已经成为一种趋势。通过智能算法和大数据分析,AI工具能够帮助学者和学生提高写作效率、优化内容结构,并确保论文的原创性和质量。以下是8款值得推荐的AI论文工具,其中特别推荐千笔-AIPa…

选择排序(C语言实现)

目录 1.基本思想 2.代码实现 代码思路 代码实现 代码测试 3.复杂度分析 1)时间复杂度 2)空间复杂度 4.特性总结 1.基本思想 选择排序是一种简单直观的比较排序算法。该算法的基本思想是在每一轮中选出当前未排序部分的最小(或最大&a…

通过 LabVIEW 正则表达式读取数值(整数或小数)

在LabVIEW开发中,字符串处理是一个非常常见的需求,尤其是在处理包含复杂格式的数字时。本文通过一个具体的例子来说明如何利用 Match Regular Expression Function 和 Match Pattern Function 读取并解析字符串中的数字,并重点探讨这两个函数…

日期和时间类【Date】【Calendar日历类】【LocalDate】Date-Time API详解

我们先来介绍一下与时间相关的基础知识。 GMT - 格林尼治标准时间(Greenwich Mean Time),简称GMT,实际上与世界时UT(universal time )基本一致。 UTC - 协调世界时(Universal Time Coordinated&…

matlab恢复默认窗口布局

1.点击主页,选择布局 2.选择默认,即可恢复到默认的窗口布局

Linux系统上搭建Vulhub靶场

Linux系统上搭建Vulhub靶场 ​vulhub​ 是一个开源的漏洞靶场,它提供了各种易受攻击的服务和应用程序,供安全研究人员和学习者测试和练习。要在 Linux 系统上安装和运行 vulhub​,可以按照以下步骤进行: 1. 安装 Docker 和 Docke…

C#软键盘设计字母数字按键处理相关事件函数

应用场景:便携式设备和检测设备等小型设备经常使用触摸屏来代替键盘鼠标的使用,因此在查询和输入界面的文本或者数字输入控件中使用软件盘来代替真正键盘的输入。 软键盘界面:软键盘界面实质上就是一个普通的窗体上面摆放了很多图片按钮&…