更新日期: 2022/06/01 来源: https://gitee.com/weharmony/kernel_liteos_a_note
virtual_serial.c 文件参考

浏览源代码.

函数

UINT32 SerialTypeGet (VOID)
 
STATIC VOID SerialTypeSet (const CHAR *deviceName)
 设置串口类型,从这里看鸿蒙暂时支持两种串口 更多...
 
STATIC INT32 SerialOpen (struct file *filep)
 打开串口设备 更多...
 
STATIC INT32 SerialClose (struct file *filep)
 关闭串口设备 更多...
 
STATIC ssize_t SerialRead (struct file *filep, CHAR *buffer, size_t bufLen)
 读取串口数据,参数 filep 是由 /dev/serial 打开获得的文件 更多...
 
STATIC ssize_t SerialWrite (struct file *filep, const CHAR *buffer, size_t bufLen)
 写入串口数据 更多...
 
STATIC INT32 SerialIoctl (struct file *filep, INT32 cmd, unsigned long arg)
 控制串口设备 更多...
 
STATIC INT32 SerialPoll (struct file *filep, poll_table *fds)
 事件查询, UartHostPollEvent(Uart) --> Hi35xxPollEvent --> poll_wait 更多...
 
INT32 virtual_serial_init (const CHAR *deviceName)
 虚拟串口初始化,注册驱动程序 ,例如 : deviceName = "/dev/uartdev-0" 更多...
 
INT32 virtual_serial_deinit (VOID)
 串口设备去初始化,其实就是注销驱动程序 更多...
 

变量

STATIC volatile UINT32 g_serialType = 0
 
STATIC struct file g_serialFilep
 
STATIC const struct file_operations_vfs g_serialDevOps
 

函数说明

◆ SerialClose()

STATIC INT32 SerialClose ( struct file filep)

关闭串口设备

在文件 virtual_serial.c106 行定义.

107{
108 (VOID)filep;
109
110 if (g_serialType == SERIAL_TYPE_UART_DEV) {//如果是UART驱动
111 HalIrqMask(NUM_HAL_INTERRUPT_UART);//设置中断屏蔽
112 }
113#if defined(LOSCFG_DRIVERS_USB_SERIAL_GADGET) || defined(LOSCFG_DRIVERS_USB_ETH_SER_GADGET)
114 else if (g_serialType == SERIAL_TYPE_USBTTY_DEV) {//如果是USB驱动
115 userial_mask_set(0);//设置USB掩码为 0
116 }
117#endif
118
119 return ENOERR;
120}
VOID HalIrqMask(UINT32 vector)
屏蔽中断
Definition: gic_v2.c:77
STATIC volatile UINT32 g_serialType
函数调用图:

◆ SerialIoctl()

STATIC INT32 SerialIoctl ( struct file filep,
INT32  cmd,
unsigned long  arg 
)

控制串口设备

在文件 virtual_serial.c175 行定义.

176{
177 INT32 ret;
178 struct file *privFilep = NULL;
179 const struct file_operations_vfs *fileOps = NULL;
180
181 ret = GetFilepOps(filep, &privFilep, &fileOps);//获取操作文件的驱动程序
182 if (ret != ENOERR) {
183 ret = -EINVAL;
184 goto ERROUT;
185 }
186
187 ret = FilepIoctl(privFilep, fileOps, cmd, arg);
188 if (ret < 0) {
189 goto ERROUT;
190 }
191 return ret;
192
193ERROUT:
194 set_errno(-ret);
195 return VFS_ERROR;
196}
INT32 GetFilepOps(const struct file *filep, struct file **privFilep, const struct file_operations_vfs **filepOps)
Definition: console.c:93
INT32 FilepIoctl(struct file *filep, const struct file_operations_vfs *fops, INT32 cmd, unsigned long arg)
Definition: console.c:560
signed int INT32
Definition: los_typedef.h:60
函数调用图:

◆ SerialOpen()

STATIC INT32 SerialOpen ( struct file filep)

打开串口设备

在文件 virtual_serial.c78 行定义.

79{
80 INT32 ret;
81 struct file *privFilep = NULL;
82 const struct file_operations_vfs *fileOps = NULL;
83
84 ret = GetFilepOps(filep, &privFilep, &fileOps);
85 if (ret != ENOERR) {
86 ret = EINVAL;
87 goto ERROUT;
88 }
89
90 ret = FilepOpen(privFilep, fileOps);
91 if (ret < 0) {
92 ret = EPERM;
93 goto ERROUT;
94 }
95
96 if (g_serialType == SERIAL_TYPE_UART_DEV) {
97 HalIrqUnmask(NUM_HAL_INTERRUPT_UART);
98 }
99 return ENOERR;
100
101ERROUT:
102 set_errno(ret);
103 return VFS_ERROR;
104}
INT32 FilepOpen(struct file *filep, const struct file_operations_vfs *fops)
打开串口或远程登录
Definition: console.c:337
VOID HalIrqUnmask(UINT32 vector)
撤销中断屏蔽
Definition: gic_v2.c:86
函数调用图:

◆ SerialPoll()

STATIC INT32 SerialPoll ( struct file filep,
poll_table *  fds 
)

事件查询, UartHostPollEvent(Uart) --> Hi35xxPollEvent --> poll_wait

在文件 virtual_serial.c198 行定义.

199{
200 INT32 ret;
201 struct file *privFilep = NULL;
202 const struct file_operations_vfs *fileOps = NULL;
203
204 ret = GetFilepOps(filep, &privFilep, &fileOps);
205 if (ret != ENOERR) {
206 ret = -EINVAL;
207 goto ERROUT;
208 }
209 ret = FilepPoll(privFilep, fileOps, fds);
210 if (ret < 0) {
211 goto ERROUT;
212 }
213 return ret;
214
215ERROUT:
216 set_errno(-ret);
217 return VFS_ERROR;
218}
INT32 FilepPoll(struct file *filep, const struct file_operations_vfs *fops, poll_table *fds)
Definition: console.c:571
函数调用图:

◆ SerialRead()

STATIC ssize_t SerialRead ( struct file filep,
CHAR buffer,
size_t  bufLen 
)

读取串口数据,参数 filep 是由 /dev/serial 打开获得的文件

在文件 virtual_serial.c122 行定义.

123{
124 INT32 ret;
125 struct file *privFilep = NULL;
126 const struct file_operations_vfs *fileOps = NULL;
127
128 ret = GetFilepOps(filep, &privFilep, &fileOps);//通过文件获取更底层设备的文件和驱动,例如 /dev/serial ---> /dev/uart
129 /*以 register_driver(SERIAL, &g_serialDevOps, DEFFILEMODE, &g_serialFilep);为例
130 privFilep = g_serialFilep
131 fileOps = g_serialDevOps
132 */
133
134 if (ret != ENOERR) {
135 ret = -EINVAL;
136 goto ERROUT;
137 }
138 //@note_thinking 觉得这里实现的有点饶,容易把人看懵逼,里面存在一个再次调用SerialRead的问题
139 //privFilep 可能是由 /dev/uartdev-0 或者 /dev/ttyGS0 打开的文件
140 ret = FilepRead(privFilep, fileOps, buffer, bufLen);//从USB或者UART 读buf
141 if (ret < 0) {
142 goto ERROUT;
143 }
144 return ret;
145
146ERROUT:
147 set_errno(-ret);
148 return VFS_ERROR;
149}
INT32 FilepRead(struct file *filep, const struct file_operations_vfs *fops, CHAR *buffer, size_t bufLen)
从串口或远程登录中读数据
Definition: console.c:517
函数调用图:

◆ SerialTypeGet()

UINT32 SerialTypeGet ( VOID  )

在文件 virtual_serial.c64 行定义.

65{
66 return g_serialType;
67}
这是这个函数的调用关系图:

◆ SerialTypeSet()

STATIC VOID SerialTypeSet ( const CHAR deviceName)

设置串口类型,从这里看鸿蒙暂时支持两种串口

dev/uartdev-0

在文件 virtual_serial.c69 行定义.

70{///dev/uartdev-0
71 if (!strncmp(deviceName, SERIAL_UARTDEV, strlen(SERIAL_UARTDEV))) {
72 g_serialType = SERIAL_TYPE_UART_DEV;
73 } else if (!strncmp(deviceName, SERIAL_TTYGS0, strlen(SERIAL_TTYGS0))) {
74 g_serialType = SERIAL_TYPE_USBTTY_DEV;
75 }
76}
这是这个函数的调用关系图:

◆ SerialWrite()

STATIC ssize_t SerialWrite ( struct file filep,
const CHAR buffer,
size_t  bufLen 
)

写入串口数据

在文件 virtual_serial.c152 行定义.

153{
154 INT32 ret;
155 struct file *privFilep = NULL;
156 const struct file_operations_vfs *fileOps = NULL;
157
158 ret = GetFilepOps(filep, &privFilep, &fileOps);//获取COM口在内核的file实例
159 if (ret != ENOERR) {
160 ret = -EINVAL;
161 goto ERROUT;
162 }
163
164 ret = FilepWrite(privFilep, fileOps, buffer, bufLen);//向控制台文件写入数据
165 if (ret < 0) {
166 goto ERROUT;
167 }
168 return ret;
169
170ERROUT:
171 set_errno(-ret);
172 return VFS_ERROR;
173}
INT32 FilepWrite(struct file *filep, const struct file_operations_vfs *fops, const CHAR *buffer, size_t bufLen)
写数据到串口或远程登录
Definition: console.c:533
函数调用图:

◆ virtual_serial_deinit()

INT32 virtual_serial_deinit ( VOID  )

串口设备去初始化,其实就是注销驱动程序

在文件 virtual_serial.c324 行定义.

325{
326 return unregister_driver(SERIAL);//注销驱动程序
327}

◆ virtual_serial_init()

INT32 virtual_serial_init ( const CHAR deviceName)

虚拟串口初始化,注册驱动程序 ,例如 : deviceName = "/dev/uartdev-0"

在文件 virtual_serial.c282 行定义.

283{
284 INT32 ret;
285 struct Vnode *vnode = NULL;
286
287 if (deviceName == NULL) {
288 ret = EINVAL;
289 goto ERROUT;
290 }
291
292 SerialTypeSet(deviceName);//例如: /dev/uartdev-0 为 UART串口
293
294 VnodeHold();
295 ret = VnodeLookup(deviceName, &vnode, V_DUMMY);//由deviceName查询vnode节点
296 if (ret != LOS_OK) {
297 ret = EACCES;
298 goto ERROUT;
299 }
300 //接着是 vnode < -- > file 的绑定操作
301 (VOID)memset_s(&g_serialFilep, sizeof(struct file), 0, sizeof(struct file));//文件的内核层表现file为fd背后的内容
302 g_serialFilep.f_oflags = O_RDWR;//可读可写
303 g_serialFilep.f_vnode = vnode; //绑定索引节点
304 g_serialFilep.ops = ((struct drv_data *)vnode->data)->ops;//这里代表 访问 /dev/serial 意味着是访问 /dev/uartdev-0
305
306 if (g_serialFilep.ops->open != NULL) {//用于检测是否有默认的驱动程序
307 (VOID)g_serialFilep.ops->open(&g_serialFilep);
308 } else {
309 ret = EFAULT;
310 PRINTK("virtual_serial_init %s open is NULL\n", deviceName);
311 goto ERROUT;
312 }
313 (VOID)register_driver(SERIAL, &g_serialDevOps, DEFFILEMODE, &g_serialFilep);//注册虚拟串口驱动程序
314 //g_serialFilep作为私有数据给了 (drv_data)data->priv = g_serialFilep
315 VnodeDrop();
316 return ENOERR;
317
318ERROUT:
319 VnodeDrop();
320 set_errno(ret);
321 return VFS_ERROR;
322}
vnode并不包含文件名,因为 vnode和文件名是 1:N 的关系
Definition: vnode.h:164
void * data
Definition: vnode.h:176
int f_oflags
int VnodeDrop(void)
归还锁
Definition: vnode.c:292
int VnodeHold(void)
拿锁,封装互斥量
Definition: vnode.c:283
int VnodeLookup(const char *path, struct Vnode **vnode, uint32_t flags)
通过路径查询vnode节点
Definition: vnode.c:491
STATIC VOID SerialTypeSet(const CHAR *deviceName)
设置串口类型,从这里看鸿蒙暂时支持两种串口
STATIC const struct file_operations_vfs g_serialDevOps
STATIC struct file g_serialFilep
函数调用图:

变量说明

◆ g_serialDevOps

STATIC const struct file_operations_vfs g_serialDevOps
初始值:
= {
NULL,
NULL,
#ifndef CONFIG_DISABLE_POLL
#endif
NULL,
}
STATIC ssize_t SerialRead(struct file *filep, CHAR *buffer, size_t bufLen)
读取串口数据,参数 filep 是由 /dev/serial 打开获得的文件
STATIC INT32 SerialClose(struct file *filep)
关闭串口设备
STATIC INT32 SerialPoll(struct file *filep, poll_table *fds)
事件查询, UartHostPollEvent(Uart) --> Hi35xxPollEvent --> poll_wait
STATIC INT32 SerialOpen(struct file *filep)
打开串口设备
STATIC INT32 SerialIoctl(struct file *filep, INT32 cmd, unsigned long arg)
控制串口设备
STATIC ssize_t SerialWrite(struct file *filep, const CHAR *buffer, size_t bufLen)
写入串口数据

串口实现VFS接口, 以hi35xx为例,列出底层路径 调用读/写的过程如下,一直调到UART最底层驱动 g_consoleDevOps(上级) g_serialDevOps(本级) g_uartDevFops g_uartHostMethod Pl011Read (读) memcpy_s(buf,rxTransfer->data, ... ) g_pl011Uops (写) Pl011StartTx UartPutsReg 控制函数实现 static int32_t UartDevIoctl(struct file *filep, int32_t cmd, unsigned long arg) { int32_t ret = HDF_FAILURE; struct UartHost *host = NULL; if (filep == NULL || filep->f_vnode == NULL) { return HDF_ERR_INVALID_PARAM; } struct drv_data *drv = (struct drv_data *)filep->f_vnode->data; host = (struct UartHost *)drv->priv;

switch (cmd) { case UART_CFG_BAUDRATE: ret = UartHostSetBaud(host, arg); break; case UART_CFG_RD_BLOCK: if (arg == UART_RD_BLOCK) { ret = UartHostSetTransMode(host, UART_MODE_RD_BLOCK); } else if (arg == UART_RD_NONBLOCK) { ret = UartHostSetTransMode(host, UART_MODE_RD_NONBLOCK); } break; case UART_CFG_ATTR: ret = UartCfgAttr(host, arg); break; case TIOCGWINSZ: /* Simply support ioctl(f->fd, TIOCGWINSZ, &wsz) system call, and the detailed design will be done later * / ret = LOS_OK; break; default: HDF_LOGE("%s cmd %d not support", func, cmd); ret = HDF_ERR_NOT_SUPPORT; break; } return ret; }

在文件 virtual_serial.c268 行定义.

◆ g_serialFilep

STATIC struct file g_serialFilep

在文件 virtual_serial.c61 行定义.

◆ g_serialType

STATIC volatile UINT32 g_serialType = 0

在文件 virtual_serial.c60 行定义.