• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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