xref: /developtools/hdc/hdc_rust/src/transfer/uart.rs (revision cc290419)
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
18use super::base;
19
20use super::uart_wrapper;
21use crate::config;
22use crate::serializer;
23#[allow(unused)]
24use crate::serializer::native_struct::UartHead;
25use crate::serializer::serialize::Serialization;
26use crate::serializer::serialize::SerializedBuffer;
27use crate::utils;
28#[allow(unused)]
29use crate::utils::hdc_log::*;
30
31#[cfg(not(target_os = "windows"))]
32use std::ffi::CString;
33use std::io::{self, Error, ErrorKind};
34
35#[cfg(feature = "host")]
36extern crate ylong_runtime_static as ylong_runtime;
37use ylong_runtime::task::JoinHandle;
38
39#[allow(unused)]
40extern "C" {
41    fn access(_name: *const libc::c_char, _type: i32) -> i32;
42    fn free(ptr: *const libc::c_void);
43
44    #[cfg(not(target_os = "windows"))]
45    fn GetUartSpeedExt(speed: i32) -> i32;
46    #[cfg(not(target_os = "windows"))]
47    fn GetUartBitsExt(bits: i32) -> i32;
48    fn OpenSerialPortExt(port: *const libc::c_char) -> i32;
49    fn SetSerialExt(fd: i32, speed: i32, bits: i32, event: u8, stop: i32) -> i32;
50    fn ReadUartDevExt(fd: i32, size: i32) -> SerializedBuffer;
51    fn WriteUartDevExt(fd: i32, buf: SerializedBuffer) -> i32;
52    fn CloseSerialPortExt(fd: i32) -> u8;
53}
54
55#[cfg(not(target_os = "windows"))]
56pub 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
82pub 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
91pub struct UartReader {
92    pub fd: i32,
93    pub head: Option<UartHead>,
94}
95
96pub struct UartWriter {
97    pub fd: i32,
98}
99
100impl base::Reader for UartReader {
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
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)]
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
157impl base::Writer for UartWriter {
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
174pub 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
187pub 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