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指向的结构体中
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值