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 18use super::base; 19 20use crate::config; 21use crate::serializer; 22use crate::serializer::native_struct::UsbHead; 23use crate::serializer::pack_struct::UsbHeadPack; 24use crate::serializer::serialize::Serialization; 25use crate::serializer::serialize::SerializedBuffer; 26use crate::utils; 27#[allow(unused)] 28use crate::utils::hdc_log::*; 29 30#[cfg(not(target_os = "windows"))] 31use std::ffi::{CStr, CString}; 32use std::io::{self, Error, ErrorKind}; 33#[cfg(not(feature = "host"))] 34use libc::{fcntl, F_SETFD, FD_CLOEXEC}; 35 36#[repr(C)] 37pub struct PersistBuffer { 38 pub ptr: *const libc::c_char, 39 pub size: libc::c_ulonglong, 40} 41 42pub 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)] 49extern "C" { 50 fn access(_name: *const libc::c_char, _type: i32) -> i32; 51 fn free(ptr: *const libc::c_void); 52 53 fn ConfigEpPointEx(path: *const libc::c_char) -> i32; 54 fn OpenEpPointEx(path: *const libc::c_char) -> i32; 55 fn CloseUsbFdEx(fd: i32) -> i32; 56 fn CloseEndPointEx(bulkIn: i32, bulkOut: i32, ctrlEp: i32, closeCtrlEp: u8); 57 #[cfg(not(target_os = "windows"))] 58 fn WriteUsbDevEx(bulkOut: i32, buf: SerializedBuffer) -> i32; 59 #[cfg(not(target_os = "windows"))] 60 fn ReadUsbDevEx(bulkIn: i32, buf: *mut u8, size: usize) -> usize; 61 fn GetDevPathEx(path: *const libc::c_char) -> *const libc::c_char; 62 63 fn SerializeUsbHead(value: *const UsbHeadPack) -> SerializedBuffer; 64 fn ParseUsbHead(value: *mut UsbHeadPack, buf: SerializedBuffer) -> libc::c_uchar; 65} 66 67#[cfg(not(target_os = "windows"))] 68pub 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 #[cfg(not(feature = "host"))] 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"))] 115pub 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 124pub struct UsbReader { 125 pub fd: i32, 126} 127pub struct UsbWriter { 128 pub fd: i32, 129} 130 131impl base::Reader for UsbReader { 132 // 屏蔽window编译报错 133 #[cfg(not(target_os = "windows"))] 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")] 157 fn read_frame(&self, _expected_size: usize) -> io::Result<Vec<u8>> { 158 Err(utils::error_other("usb read error".to_string())) 159 } 160 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#[cfg(not(target_os = "windows"))] 180pub fn usb_write_all(fd: i32, data: Vec<u8>) -> io::Result<i32> { 181 let buf = SerializedBuffer { 182 ptr: data.as_ptr() as *const libc::c_char, 183 size: data.len() as u64, 184 }; 185 let ret = unsafe { WriteUsbDevEx(fd, buf) } as i32; 186 if ret < 0 { 187 Err(utils::error_other("usb write failed".to_string())) 188 } else { 189 Ok(ret) 190 } 191} 192impl base::Writer for UsbWriter { 193 // 屏蔽window编译报错 194 #[cfg(not(target_os = "windows"))] 195 #[allow(unused)] 196 fn write_all(&self, data: Vec<u8>) -> io::Result<i32> { 197 let buf = SerializedBuffer { 198 ptr: data.as_ptr() as *const libc::c_char, 199 size: data.len() as u64, 200 }; 201 let ret = unsafe { WriteUsbDevEx(self.fd, buf) } as i32; 202 if ret < 0 { 203 Err(utils::error_other("usb write failed".to_string())) 204 } else { 205 Ok(ret) 206 } 207 } 208 209 // 屏蔽window编译报错 210 #[cfg(target_os = "windows")] 211 fn write_all(&self, _data: Vec<u8>) -> io::Result<i32> { 212 Ok(0) 213 } 214} 215 216pub fn build_header(session_id: u32, option: u8, length: usize) -> Vec<u8> { 217 UsbHead { 218 session_id: u32::to_be(session_id), 219 flag: [config::USB_PACKET_FLAG[0], config::USB_PACKET_FLAG[1]], 220 option, 221 data_size: u32::to_be(length as u32), 222 } 223 .serialize() 224} 225