ftdi_sio驱动学习笔记 5 - 读写操作

目录

1. ftdi_prepare_write_buffer

2. ftdi_process_read_urb


读写相关操作对应的函数:

.process_read_urb =	ftdi_process_read_urb,
.prepare_write_buffer =	ftdi_prepare_write_buffer,

实际读写并不是ftdi_sio操作的,是通过内核标准的usb serial实现。

1. ftdi_prepare_write_buffer

static int ftdi_prepare_write_buffer(struct usb_serial_port *port,void *dest, size_t size)

参数dest是目标缓冲区的地址,用于存放准备好的数据。size是该数据的长度。这个函数用于准备一个USB数据包以便通过FTDI芯片发送到串口或其他异步通信端口。这个函数并不是直接发送数据,而是为数据发送做准备。

这个函数是把写入的数据更新到port->write_fifo,但是分2种情况,如果是非SIO的设备,比较简单,直接拷贝就可以了。

count = kfifo_out_locked(&port->write_fifo, dest, size, &port->lock);
port->icount.tx += count;

而对于SIO的设备,需要每个packet的第一个字节特殊处理,该字节的位0为1,位1为0,位2-7为该packet内数据的长度。

unsigned char *buffer = dest;
int i, len, c;count = 0;
spin_lock_irqsave(&port->lock, flags);
for (i = 0; i < size - 1; i += priv->max_packet_size) {len = min_t(int, size - i, priv->max_packet_size) - 1;c = kfifo_out(&port->write_fifo, &buffer[i + 1], len);if (!c)break;port->icount.tx += c;buffer[i] = (c << 2) + 1;count += c + 1;
}
spin_unlock_irqrestore(&port->lock, flags);

真正写数据是标准的usb写,所以在ftdi_sio中没有处理。

2. ftdi_process_read_urb

static void ftdi_process_read_urb(struct urb *urb)

当 URB 完成从 FTDI 芯片读取数据后,ftdi_process_read_urb将被调用来解析和处理这些数据。它会检查读取的数据并将其适当地传递给更高层的串行通信协议栈。

数据在urb->transfer_buffer

for (i = 0; i < urb->actual_length; i += priv->max_packet_size) {len = min_t(int, urb->actual_length - i, priv->max_packet_size);count += ftdi_process_packet(port, priv, &data[i], len);
}

而tty_flip_buffer_push是通知tty去线路规程获取从串口过来的数据

if (count)tty_flip_buffer_push(&port->port);

对于ftdi_process_packet,这个函数用于处理FTDI芯片的USB串口数据包。该数据包分3个部分。

  • 第一个字节的处理:
#define FTDI_STATUS_B0_MASK	(FTDI_RS0_CTS | FTDI_RS0_DSR | FTDI_RS0_RI | FTDI_RS0_RLSD)status = buf[0] & FTDI_STATUS_B0_MASK;
if (status != priv->prev_status) {char diff_status = status ^ priv->prev_status;if (diff_status & FTDI_RS0_CTS)port->icount.cts++;if (diff_status & FTDI_RS0_DSR)port->icount.dsr++;if (diff_status & FTDI_RS0_RI)port->icount.rng++;if (diff_status & FTDI_RS0_RLSD) {struct tty_struct *tty;port->icount.dcd++;tty = tty_port_tty_get(&port->port);if (tty)usb_serial_handle_dcd_change(port, tty,status & FTDI_RS0_RLSD);tty_kref_put(tty);}wake_up_interruptible(&port->port.delta_msr_wait);priv->prev_status = status;
}

如果状态发生变化,则根据变化的状态值更新相应的计数器(如CTS、DSR、RI和DCD)。如果RLSD状态发生变化,则进一步处理DCD状态的变化,包括更新计数器和调用处理函数。最后,唤醒等待状态变化的进程,并更新之前的状志值。

  • 第二个字节的处理:
/* save if the transmitter is empty or not */
if (buf[1] & FTDI_RS_TEMT)priv->transmit_empty = 1;
elsepriv->transmit_empty = 0;if (len == 2)return 0;	/* status only */

检查FTDI设备的发送缓冲区是否为空,并设置相应的状态标志。

#define FTDI_RS_ERR_MASK (FTDI_RS_BI | FTDI_RS_PE | FTDI_RS_FE | FTDI_RS_OE)if (buf[1] & FTDI_RS_ERR_MASK) {/** Break takes precedence over parity, which takes precedence* over framing errors. Note that break is only associated* with the last character in the buffer and only when it's a* NUL.*/if (buf[1] & FTDI_RS_BI && buf[len - 1] == '\0') {port->icount.brk++;brkint = true;}if (buf[1] & FTDI_RS_PE) {flag = TTY_PARITY;port->icount.parity++;} else if (buf[1] & FTDI_RS_FE) {flag = TTY_FRAME;port->icount.frame++;}/* Overrun is special, not associated with a char */if (buf[1] & FTDI_RS_OE) {port->icount.overrun++;tty_insert_flip_char(&port->port, 0, TTY_OVERRUN);}
}

这里是处理串口通信数据错误的。它根据buf[1]中的位来判断出现了哪种错误:break(断路)、parity(奇偶校验错误)、framing(帧错误)或overrun(缓冲区溢出错误)。每种错误都有相应的处理方式,如计数器增加或插入特定字符到缓冲区。其中,break错误仅在最后一个字符为NUL时才被计数。

  • 其他数据
if (brkint || port->sysrq) {for (i = 2; i < len; i++) {if (brkint && i == len - 1) {if (usb_serial_handle_break(port))return len - 3;flag = TTY_BREAK;}if (usb_serial_handle_sysrq_char(port, buf[i]))continue;tty_insert_flip_char(&port->port, buf[i], flag);}
} else {tty_insert_flip_string_fixed_flag(&port->port, buf + 2, flag,len - 2);
}

根据条件处理USB串行端口的数据,并将其插入到tty flip缓冲区中。如果brkintport->sysrq为真,则对每个字符进行特殊处理;否则,直接将数据插入到缓冲区。在特殊处理过程中,如果遇到特定条件,会调用usb_serial_handle_break函数处理中断,或调用usb_serial_handle_sysrq_char函数处理系统请求字符。最终,数据通过tty_insert_flip_char函数插入到缓冲区中。

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

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

黑芝麻A1000-Ubuntu20.04(九)yolov5从训练到板端运行过程详解

宿主机&#xff1a;台式电脑 Ubuntu20.04 开发板&#xff1a;A1000&#xff08;烧录版本SDK v2.3.1.2&#xff09; 模型转换容器&#xff1a;bsnn-tools-container-stk-4.2.0 编译容器&#xff1a;a1000b-sdk-fad-2.3.1.2 yolov5使用工程&#xff1a;黑芝麻根据https://github.…

高性能分布式搜索引擎Elasticsearch详解

♥️作者&#xff1a;小宋1021 &#x1f935;‍♂️个人主页&#xff1a;小宋1021主页 ♥️坚持分析平时学习到的项目以及学习到的软件开发知识&#xff0c;和大家一起努力呀&#xff01;&#xff01;&#xff01; &#x1f388;&#x1f388;加油&#xff01; 加油&#xff01…

[vulnhub] Jarbas-Jenkins

靶机链接 https://www.vulnhub.com/entry/jarbas-1,232/ 主机发现端口扫描 扫描网段存活主机&#xff0c;因为主机是我最后添加的&#xff0c;所以靶机地址是135的 nmap -sP 192.168.75.0/24 // Starting Nmap 7.93 ( https://nmap.org ) at 2024-09-21 14:03 CST Nmap scan…

【Linux】Linux基本命令

目录 文件和目录操作&#xff1a; ls cd pwd cp mv rm mkdir rmdir touch clear history which/whereis 文件查看和编辑&#xff1a; cat less head tail vi 或 vim sz/rz echo 系统信息和管理&#xff1a; su uname hostname df free top ps ki…

2025台球展,2025河南台球及配套设施展览会3月举办

阳春三月&#xff0c;年度招商季&#xff0c;壹肆柒中国国际台球产业博览会助力全国台球企业拓市场&#xff1b; 2025中国&#xff08;郑州&#xff09;国际台球产业博览会&#xff08;壹肆柒台球展&#xff09; The 2025 China (Zhengzhou) International Billiards Industry…

C++:采用模板封装顺序表,栈,队列

1.顺序表&#xff1a; list.hpp #ifndef LIST_HPP #define LIST_HPP #include <iostream>using namespace std;template <class L>class Seqlist { private:L *ptr;L size;L len0;public:void init(L n){//堆区申请空间&#xff08;大小为n&#xff09;this->…

博主回归!数据结构篇启动

目录 1>>闲话 2>>数据结构前言 3>>复杂度的概念 4>>时间复杂度 5>>大O渐进表示法 6>>总结 1>>闲话 家人们好久不见&#xff0c;小编军训终于是结束了&#xff0c;大一事情太多了&#xff0c;这几天没时间健身&#xff0c;没时间…

2024.9.26 作业 +思维导图

一、作业 1、什么是虚函数&#xff1f;什么是纯虚函数 虚函数&#xff1a;函数前加关键字virtual&#xff0c;就定义为虚函数&#xff0c;虚函数能够被子类中相同函数名的函数重写 纯虚函数&#xff1a;把虚函数的函数体去掉然后加0&#xff1b;就能定义出一个纯虚函数。 2、基…

el-table+el-form实现表单校验和解决不垂直居中导致的问题

el-tableel-form实现表单校验 1.实现el-table的表单校验 关键点123 2.解决不垂直居中导致的问题 问题效果图 解决方案 .item-align-center {display: inline-flex; }

数据定义语言CREATE的应用

新书速览|SQL Server 2022从入门到精通&#xff1a;视频教学超值版_sql server 2022 出版社-CSDN博客 《SQL Server 2022从入门到精通&#xff08;视频教学超值版&#xff09;&#xff08;数据库技术丛书&#xff09;》(王英英)【摘要 书评 试读】- 京东图书 (jd.com) SQL Se…

IGZO基底无电容DRAM单元前景看好

1.DRAM技术简介 DRAM&#xff08;Dynamic Random Access Memory&#xff0c;动态随机存取存储器&#xff09;是一种用于计算机和其他电子设备中的主存储器类型&#xff0c;其主要由存储单元阵列构成&#xff0c;而每一个存储单元由一个电容器和一个晶体管组成&#xff0c;如图…

EasyAR自定义相机RTSP视频流(CustomCamera)

EasyAR可以使用视频源作为输入源&#xff0c;官方给出了示例和文档&#xff0c;但是对于大部分Unity开发人员来说看了文档还是一头雾水。 在Android Studio中将custom-camera.jar添加libs中&#xff0c;就可以查看源代码了 分析其源代码&#xff0c;主要是ExternalCameraSampl…

AI数字人直播爆火,数字人虚拟主播成品牌闲时直播最佳选择!

近年来&#xff0c;随着互联网的普及和发展&#xff0c;电商和直播平台在我国迅速崛起。根据中国网络信息中心的数据显示&#xff0c;我国直播用户7.5亿&#xff0c;使用率已经超过70%&#xff0c;直播已经成为企业重要的营销和销售通道。 一、在经历了几年的爆发式增长后&…

日期类的实现- 计算日期之间相差多少天-解决单参数构造

个人主页&#xff1a;Jason_from_China-CSDN博客 所属栏目&#xff1a;C系统性学习_Jason_from_China的博客-CSDN博客 所属栏目&#xff1a;C知识点的补充_Jason_from_China的博客-CSDN博客 这里有坑&#xff0c;这里有坑&#xff0c;这里有坑 首选我们直接上代码&#xff0c;因…

Unity场景内画车道线(根据五阶曲线系数)

之前做过使用Dreamteck Splines插件构建车道线之前需求是给定车道线的点位&#xff0c;根据点位来进行构建。 由于AI识别出来的点位不线性&#xff0c;画出来的车道线经常是歪七扭八&#xff0c;所以使用五阶曲线系数进行构建。 使用在线图形计算器进行测试构建&#xff0c;公式…

【C++】STL标准模板库容器set

&#x1f984;个人主页:修修修也 &#x1f38f;所属专栏:C ⚙️操作环境:Visual Studio 2022 目录 &#x1f4cc;关联式容器set(集合)简介 &#x1f4cc;set(集合)的使用 &#x1f38f;set(集合)的模板参数列表 &#x1f38f;set(集合)的构造函数 &#x1f38f;set(集合)的迭代…

Vue 项目实战4-无缝轮播图

养成好习惯&#xff0c;先赞后看&#xff0c;感谢对作者大大的支持 一、话不多说&#xff0c;直接上效果图&#xff1a; 完整视频展示链接如下&#xff1a; https://item.taobao.com/item.htm?ftt&id833405684191 二、实现思路 HTML结构 文档头部设置&#xff1a;定义…

C# 委托(Delegate)二

一.委托的多播&#xff08;Multicasting of a Delegate&#xff09;&#xff1a; 委托对象&#xff0c;使用 "" 运算符进行合并&#xff0c;一个合并委托调用它所合并的两个委托。使用"-" 运算符从合并的委托中移除组件委托。 注&#xff1a;只有相同类型…

C语言编译和链接详解(通俗易懂,深入本质)

我们平时所说的程序,是指双击后就可以直接运行的程序,这样的程序被称为可执行程序(Executable Program)。在 Windows 下,可执行程序的后缀有.exe和.com(其中.exe比较常见);在类 UNIX 系统(Linux、Mac OS 等)下,可执行程序没有特定的后缀,系统根据文件的头部信息来判…

小小扑克牌算法

1.定义一个扑克牌类Card&#xff1a; package democard; public class Card {public String suit;//表示花色public int rank;//表示牌点数Overridepublic String toString() {return "{"suit rank"}";}//实例方法&#xff0c;初始化牌的点数和花色public…