xref: /developtools/hdc/hdc_rust/src/transfer/usb.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//! 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