1 /*
2 * Copyright (C) 2023 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15 //! uart
16 #![allow(missing_docs)]
17
18 use super::base;
19
20 use super::uart_wrapper;
21 use crate::config;
22 use crate::serializer;
23 #[allow(unused)]
24 use crate::serializer::native_struct::UartHead;
25 use crate::serializer::serialize::Serialization;
26 use crate::serializer::serialize::SerializedBuffer;
27 use crate::utils;
28 #[allow(unused)]
29 use crate::utils::hdc_log::*;
30
31 #[cfg(not(target_os = "windows"))]
32 use std::ffi::CString;
33 use std::io::{self, Error, ErrorKind};
34
35 #[cfg(feature = "host")]
36 extern crate ylong_runtime_static as ylong_runtime;
37 use ylong_runtime::task::JoinHandle;
38
39 #[allow(unused)]
40 extern "C" {
access(_name: *const libc::c_char, _type: i32) -> i3241 fn access(_name: *const libc::c_char, _type: i32) -> i32;
free(ptr: *const libc::c_void)42 fn free(ptr: *const libc::c_void);
43
44 #[cfg(not(target_os = "windows"))]
GetUartSpeedExt(speed: i32) -> i3245 fn GetUartSpeedExt(speed: i32) -> i32;
46 #[cfg(not(target_os = "windows"))]
GetUartBitsExt(bits: i32) -> i3247 fn GetUartBitsExt(bits: i32) -> i32;
OpenSerialPortExt(port: *const libc::c_char) -> i3248 fn OpenSerialPortExt(port: *const libc::c_char) -> i32;
SetSerialExt(fd: i32, speed: i32, bits: i32, event: u8, stop: i32) -> i3249 fn SetSerialExt(fd: i32, speed: i32, bits: i32, event: u8, stop: i32) -> i32;
ReadUartDevExt(fd: i32, size: i32) -> SerializedBuffer50 fn ReadUartDevExt(fd: i32, size: i32) -> SerializedBuffer;
WriteUartDevExt(fd: i32, buf: SerializedBuffer) -> i3251 fn WriteUartDevExt(fd: i32, buf: SerializedBuffer) -> i32;
CloseSerialPortExt(fd: i32) -> u852 fn CloseSerialPortExt(fd: i32) -> u8;
53 }
54
55 #[cfg(not(target_os = "windows"))]
uart_init() -> io::Result<i32>56 pub fn uart_init() -> io::Result<i32> {
57 let name = CString::new(config::UART_NODE).unwrap();
58 let fd = unsafe {
59 if access(name.as_ptr(), 0) != 0 {
60 return Err(utils::error_other("cannot access uart node".to_string()));
61 }
62 let fd = OpenSerialPortExt(name.as_ptr());
63 if fd < 0 {
64 return Err(utils::error_other("cannot open uart node".to_string()));
65 }
66 if SetSerialExt(
67 fd,
68 config::UART_DEFAULT_BAUD_RATE,
69 config::UART_DEFAULT_BITS,
70 config::UART_EVENT,
71 1,
72 ) != 0
73 {
74 return Err(utils::error_other("set uart config failed".to_string()));
75 }
76 crate::debug!("uart init fd: {fd}");
77 fd
78 };
79 Ok(fd)
80 }
81
uart_close(_fd: i32)82 pub fn uart_close(_fd: i32) {
83 #[cfg(not(target_os = "windows"))]
84 unsafe {
85 CloseSerialPortExt(_fd);
86 }
87 #[cfg(target_os = "windows")]
88 return {};
89 }
90
91 pub struct UartReader {
92 pub fd: i32,
93 pub head: Option<UartHead>,
94 }
95
96 pub struct UartWriter {
97 pub fd: i32,
98 }
99
100 impl base::Reader for UartReader {
read_frame(&self, expected_size: usize) -> io::Result<Vec<u8>>101 fn read_frame(&self, expected_size: usize) -> io::Result<Vec<u8>> {
102 if expected_size == 0 {
103 return Ok(vec![]);
104 }
105 let mut data = vec![];
106 let mut index = 0;
107 while index < expected_size {
108 crate::trace!("before read {index} / {expected_size}");
109 let buf = unsafe {
110 let recv = ReadUartDevExt(self.fd, (expected_size - index) as i32);
111 let slice = std::slice::from_raw_parts(
112 recv.ptr as *const libc::c_uchar,
113 recv.size as usize,
114 );
115 index += recv.size as usize;
116 slice.to_vec()
117 };
118 data = [data, buf].concat();
119 }
120 Ok(data)
121 }
122
check_protocol_head(&mut self) -> io::Result<(u32, u32, u32)>123 fn check_protocol_head(&mut self) -> io::Result<(u32, u32, u32)> {
124 let buf = self.read_frame(serializer::UART_HEAD_SIZE)?;
125 if buf[..config::PACKET_FLAG.len()] != config::PACKET_FLAG[..] {
126 return Err(Error::new(
127 ErrorKind::Other,
128 format!("uart PACKET_FLAG incorrect, content: {:#?}", buf),
129 ));
130 }
131 let mut head = serializer::native_struct::UartHead::default();
132
133 if let Err(e) = head.parse(buf) {
134 log::warn!("parse uart head error: {}", e.to_string());
135 return Err(e);
136 }
137
138 self.head = Some(head.clone());
139
140 Ok((head.data_size, head.package_index, head.session_id))
141 }
142
143 #[allow(unused)]
process_head(&self) -> Option<JoinHandle<()>>144 fn process_head(&self) -> Option<JoinHandle<()>> {
145 let head = self.head.clone();
146 if let Some(head) = head {
147 let join_handle = utils::spawn(async move {
148 uart_wrapper::on_read_head(head).await;
149 });
150 Some(join_handle)
151 } else {
152 None
153 }
154 }
155 }
156
157 impl base::Writer for UartWriter {
write_all(&self, data: Vec<u8>) -> io::Result<i32>158 fn write_all(&self, data: Vec<u8>) -> io::Result<i32> {
159 let buf = SerializedBuffer {
160 ptr: data.as_ptr() as *const libc::c_char,
161 size: data.len() as u64,
162 };
163 crate::debug!("write all start, fd:{}...", self.fd);
164 let write_count = unsafe { WriteUartDevExt(self.fd, buf) } as i32;
165 crate::debug!("write count:{}", write_count);
166 if write_count < 0 {
167 Err(utils::error_other("uart write failed".to_string()))
168 } else {
169 Ok(write_count)
170 }
171 }
172 }
173
build_header(session_id: u32, option: u16, length: usize, package_index: u32) -> Vec<u8>174 pub fn build_header(session_id: u32, option: u16, length: usize, package_index: u32) -> Vec<u8> {
175 UartHead {
176 session_id: u32::to_le(session_id),
177 flag: [config::PACKET_FLAG[0], config::PACKET_FLAG[1]],
178 option,
179 data_size: u32::to_le(length as u32),
180 package_index,
181 data_checksum: 0,
182 head_checksum: 0,
183 }
184 .serialize()
185 }
186
build_header_obj( session_id: u32, option: u16, length: usize, package_index: u32, ) -> UartHead187 pub fn build_header_obj(
188 session_id: u32,
189 option: u16,
190 length: usize,
191 package_index: u32,
192 ) -> UartHead {
193 UartHead {
194 session_id: u32::to_le(session_id),
195 flag: [config::PACKET_FLAG[0], config::PACKET_FLAG[1]],
196 option,
197 data_size: u32::to_le(length as u32),
198 package_index,
199 data_checksum: 0,
200 head_checksum: 0,
201 }
202 }
203