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 //! usb
16 #![allow(missing_docs)]
17
18 use super::base;
19
20 use crate::config;
21 use crate::serializer;
22 use crate::serializer::native_struct::UsbHead;
23 use crate::serializer::pack_struct::UsbHeadPack;
24 use crate::serializer::serialize::Serialization;
25 use crate::serializer::serialize::SerializedBuffer;
26 use crate::utils;
27 #[allow(unused)]
28 use crate::utils::hdc_log::*;
29
30 #[cfg(not(target_os = "windows"))]
31 use std::ffi::{CStr, CString};
32 use std::io::{self, Error, ErrorKind};
33
34 use libc::{fcntl, F_SETFD, FD_CLOEXEC};
35
36 #[repr(C)]
37 pub struct PersistBuffer {
38 pub ptr: *const libc::c_char,
39 pub size: libc::c_ulonglong,
40 }
41
buf_to_vec(buf: PersistBuffer) -> Vec<u8>42 pub fn buf_to_vec(buf: PersistBuffer) -> Vec<u8> {
43 let slice =
44 unsafe { std::slice::from_raw_parts(buf.ptr as *const libc::c_uchar, buf.size as usize) };
45 slice.to_vec()
46 }
47
48 #[allow(unused)]
49 extern "C" {
access(_name: *const libc::c_char, _type: i32) -> i3250 fn access(_name: *const libc::c_char, _type: i32) -> i32;
free(ptr: *const libc::c_void)51 fn free(ptr: *const libc::c_void);
52
ConfigEpPointEx(path: *const libc::c_char) -> i3253 fn ConfigEpPointEx(path: *const libc::c_char) -> i32;
OpenEpPointEx(path: *const libc::c_char) -> i3254 fn OpenEpPointEx(path: *const libc::c_char) -> i32;
CloseUsbFdEx(fd: i32) -> i3255 fn CloseUsbFdEx(fd: i32) -> i32;
CloseEndPointEx(bulkIn: i32, bulkOut: i32, ctrlEp: i32, closeCtrlEp: u8)56 fn CloseEndPointEx(bulkIn: i32, bulkOut: i32, ctrlEp: i32, closeCtrlEp: u8);
57 #[cfg(not(target_os = "windows"))]
WriteUsbDevEx(bulkOut: i32, buf: SerializedBuffer) -> i3258 fn WriteUsbDevEx(bulkOut: i32, buf: SerializedBuffer) -> i32;
59 #[cfg(not(target_os = "windows"))]
ReadUsbDevEx(bulkIn: i32, buf: *mut u8, size: usize) -> usize60 fn ReadUsbDevEx(bulkIn: i32, buf: *mut u8, size: usize) -> usize;
GetDevPathEx(path: *const libc::c_char) -> *const libc::c_char61 fn GetDevPathEx(path: *const libc::c_char) -> *const libc::c_char;
62
SerializeUsbHead(value: *const UsbHeadPack) -> SerializedBuffer63 fn SerializeUsbHead(value: *const UsbHeadPack) -> SerializedBuffer;
ParseUsbHead(value: *mut UsbHeadPack, buf: SerializedBuffer) -> libc::c_uchar64 fn ParseUsbHead(value: *mut UsbHeadPack, buf: SerializedBuffer) -> libc::c_uchar;
65 }
66
67 #[cfg(not(target_os = "windows"))]
usb_init() -> io::Result<(i32, i32, i32)>68 pub fn usb_init() -> io::Result<(i32, i32, i32)> {
69 crate::info!("opening usb fd...");
70 let path = CString::new(config::USB_FFS_BASE).unwrap();
71
72 let base_path = unsafe {
73 let p = GetDevPathEx(path.as_ptr());
74 let c_str = CStr::from_ptr(p);
75 c_str.to_str().unwrap().to_string()
76 };
77 // let c_str: &CStr = unsafe { CStr::from_ptr(p) };
78 // c_str.to_str().unwrap().to_string()
79 // let base_path = serializer::ptr_to_string(unsafe { GetDevPathEx(path.as_ptr()) });
80 let ep0 = CString::new(base_path.clone() + "/ep0").unwrap();
81 let ep1 = CString::new(base_path.clone() + "/ep1").unwrap();
82 let ep2 = CString::new(base_path + "/ep2").unwrap();
83 if unsafe { access(ep0.as_ptr(), 0) } != 0 {
84 return Err(utils::error_other("cannot access usb path".to_string()));
85 }
86
87 let config_fd = unsafe { ConfigEpPointEx(ep0.as_ptr()) };
88 if config_fd < 0 {
89 return Err(utils::error_other("cannot open usb ep0".to_string()));
90 }
91
92 let bulkin_fd = unsafe { OpenEpPointEx(ep1.as_ptr()) };
93 if bulkin_fd < 0 {
94 return Err(utils::error_other("cannot open usb ep1".to_string()));
95 }
96
97 let bulkout_fd = unsafe { OpenEpPointEx(ep2.as_ptr()) };
98 if bulkout_fd < 0 {
99 return Err(utils::error_other("cannot open usb ep2".to_string()));
100 }
101
102 unsafe{
103 // cannot open with O_CLOEXEC, must fcntl
104 fcntl(config_fd, F_SETFD, FD_CLOEXEC);
105 fcntl(bulkin_fd, F_SETFD, FD_CLOEXEC);
106 fcntl(bulkout_fd, F_SETFD, FD_CLOEXEC);
107 }
108
109 crate::info!("usb fd: {config_fd}, {bulkin_fd}, {bulkout_fd}");
110
111 Ok((config_fd, bulkin_fd, bulkout_fd))
112 }
113
114 #[cfg(not(target_os = "windows"))]
usb_close(config_fd: i32, bulkin_fd: i32, bulkout_fd: i32)115 pub fn usb_close(config_fd: i32, bulkin_fd: i32, bulkout_fd: i32) {
116 crate::info!("closing usb fd...");
117 unsafe {
118 CloseUsbFdEx(config_fd);
119 CloseUsbFdEx(bulkin_fd);
120 CloseUsbFdEx(bulkout_fd);
121 }
122 }
123
124 pub struct UsbReader {
125 pub fd: i32,
126 }
127 pub struct UsbWriter {
128 pub fd: i32,
129 }
130
131 impl base::Reader for UsbReader {
132 // 屏蔽window编译报错
133 #[cfg(not(target_os = "windows"))]
read_frame(&self, expect: usize) -> io::Result<Vec<u8>>134 fn read_frame(&self, expect: usize) -> io::Result<Vec<u8>> {
135 let mut buf :Vec<u8> = Vec::with_capacity(expect);
136 unsafe {
137 let readed = ReadUsbDevEx(self.fd, buf.as_mut_ptr() as *mut libc::uint8_t, expect);
138 if readed != expect {
139 Err(
140 utils::error_other(
141 format!(
142 "usb read error, usb read failed: expect: {} acture: {}",
143 expect,
144 readed,
145 )
146 )
147 )
148 } else {
149 buf.set_len(readed);
150 Ok(buf)
151 }
152 }
153 }
154
155 // 屏蔽window编译报错
156 #[cfg(target_os = "windows")]
read_frame(&self, _expected_size: usize) -> io::Result<Vec<u8>>157 fn read_frame(&self, _expected_size: usize) -> io::Result<Vec<u8>> {
158 Err(utils::error_other("usb read error".to_string()))
159 }
160
check_protocol_head(&mut self) -> io::Result<(u32, u32, u32)>161 fn check_protocol_head(&mut self) -> io::Result<(u32, u32, u32)> {
162 let buf = self.read_frame(serializer::USB_HEAD_SIZE)?;
163 if buf[..config::USB_PACKET_FLAG.len()] != config::USB_PACKET_FLAG[..] {
164 return Err(Error::new(
165 ErrorKind::Other,
166 format!("USB_PACKET_FLAG incorrect, content: {:#?}", buf),
167 ));
168 }
169 let mut head = serializer::native_struct::UsbHead::default();
170
171 if let Err(e) = head.parse(buf) {
172 crate::warn!("parse usb head error: {}", e.to_string());
173 return Err(e);
174 }
175 Ok((u32::from_be(head.data_size), 0, u32::to_be(head.session_id)))
176 }
177 }
178
179 impl base::Writer for UsbWriter {
180 // 屏蔽window编译报错
181 #[cfg(not(target_os = "windows"))]
write_all(&self, data: Vec<u8>) -> io::Result<i32>182 fn write_all(&self, data: Vec<u8>) -> io::Result<i32> {
183 let buf = SerializedBuffer {
184 ptr: data.as_ptr() as *const libc::c_char,
185 size: data.len() as u64,
186 };
187 let ret = unsafe { WriteUsbDevEx(self.fd, buf) } as i32;
188 if ret < 0 {
189 Err(utils::error_other("usb write failed".to_string()))
190 } else {
191 Ok(ret)
192 }
193 }
194
195 // 屏蔽window编译报错
196 #[cfg(target_os = "windows")]
write_all(&self, _data: Vec<u8>) -> io::Result<i32>197 fn write_all(&self, _data: Vec<u8>) -> io::Result<i32> {
198 Ok(0)
199 }
200 }
201
build_header(session_id: u32, option: u8, length: usize) -> Vec<u8>202 pub fn build_header(session_id: u32, option: u8, length: usize) -> Vec<u8> {
203 UsbHead {
204 session_id: u32::to_be(session_id),
205 flag: [config::USB_PACKET_FLAG[0], config::USB_PACKET_FLAG[1]],
206 option,
207 data_size: u32::to_be(length as u32),
208 }
209 .serialize()
210 }
211