messy commit: start implementing ftdi-vcp-rs

Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
2020-03-30 17:56:40 +08:00
parent 52fa59d4ac
commit 22528a892f
197 changed files with 201 additions and 163 deletions

37
ftdi-vcp-rs/Cargo.lock generated Normal file
View File

@ -0,0 +1,37 @@
# This file is automatically @generated by Cargo.
# It is not intended for manual editing.
[[package]]
name = "ftdi-vcp-rs"
version = "0.1.0"
dependencies = [
"ftdi-vcp-sys",
]
[[package]]
name = "ftdi-vcp-sys"
version = "0.1.0"
dependencies = [
"winapi",
]
[[package]]
name = "winapi"
version = "0.3.8"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8093091eeb260906a183e6ae1abdba2ef5ef2257a21801128899c3fc699229c6"
dependencies = [
"winapi-i686-pc-windows-gnu",
"winapi-x86_64-pc-windows-gnu",
]
[[package]]
name = "winapi-i686-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6"
[[package]]
name = "winapi-x86_64-pc-windows-gnu"
version = "0.4.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f"

10
ftdi-vcp-rs/Cargo.toml Normal file
View File

@ -0,0 +1,10 @@
[package]
name = "ftdi-vcp-rs"
version = "0.1.0"
authors = ["Sean Cross <sean@xobs.io>"]
edition = "2018"
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
[dependencies]
ftdi-vcp-sys = { path = "../ftdi-vcp-sys" }

120
ftdi-vcp-rs/src/lib.rs Normal file
View File

@ -0,0 +1,120 @@
use ftdi_vcp_sys::{
FT_Close, FT_GetComPortNumber, FT_OpenEx, FT_HANDLE, FT_OPEN_BY_DESCRIPTION, FT_STATUS, LONG,
PVOID,
};
use std::ffi::CString;
use std::mem::MaybeUninit;
use std::convert::TryInto;
#[derive(PartialEq, Debug)]
pub enum Error {
NoError,
InvalidHandle,
DeviceNotFound,
DeviceNotOpened,
IoError,
InsufficientResources,
InvalidParameter,
InvalidBaudRate,
DeviceNotOpenedForErase,
DeviceNotOpenedForWrite,
FailedToWriteDevice,
EepromReadFailed,
EepromWriteFailed,
EepromEraseFailed,
EepromNotPresent,
EepromNotProgrammed,
InvalidArgs,
NotSupported,
OtherError,
DeviceListNotReady,
NoComPortAssigned,
UnknownError(FT_STATUS),
}
impl From<FT_STATUS> for Error {
fn from(src: FT_STATUS) -> Self {
match src {
0 => Error::NoError,
1 => Error::InvalidHandle,
2 => Error::DeviceNotFound,
3 => Error::DeviceNotOpened,
4 => Error::IoError,
5 => Error::InsufficientResources,
6 => Error::InvalidParameter,
7 => Error::InvalidBaudRate,
8 => Error::DeviceNotOpenedForErase,
9 => Error::DeviceNotOpenedForWrite,
10 => Error::FailedToWriteDevice,
11 => Error::EepromReadFailed,
12 => Error::EepromWriteFailed,
13 => Error::EepromEraseFailed,
14 => Error::EepromNotPresent,
15 => Error::EepromNotProgrammed,
16 => Error::InvalidArgs,
17 => Error::NotSupported,
18 => Error::OtherError,
19 => Error::DeviceListNotReady,
x => Error::UnknownError(x),
}
}
}
pub struct VCP {
handle: FT_HANDLE,
}
impl VCP {
pub fn new_from_name(name: &str) -> Result<VCP, Error> {
let c_str = CString::new(name).expect("string already contained null bytes");
let mut handle = MaybeUninit::<FT_HANDLE>::uninit();
let result = Error::from(unsafe {
FT_OpenEx(
c_str.as_ptr() as PVOID,
FT_OPEN_BY_DESCRIPTION,
handle.as_mut_ptr(),
)
});
if result != Error::NoError {
Err(result)
} else {
Ok(VCP {
handle: unsafe { handle.assume_init() },
})
}
}
pub fn com_port(&self) -> Result<usize, Error> {
let mut com_port_number = MaybeUninit::<LONG>::uninit();
let result = Error::from(unsafe {
FT_GetComPortNumber(self.handle, com_port_number.as_mut_ptr())
});
if result != Error::NoError {
Err(result)
} else {
let com_port_number = unsafe { com_port_number.assume_init() };
if let Ok(e) = com_port_number.try_into() {
Ok(e)
} else {
Err(Error::NoComPortAssigned)
}
}
}
}
impl Drop for VCP {
fn drop(&mut self) {
let result = Error::from(unsafe { FT_Close(self.handle) });
if result != Error::NoError {
panic!("unable to close device: {:?}", result);
}
}
}
#[cfg(test)]
mod tests {
#[test]
fn it_works() {
assert_eq!(2 + 2, 4);
}
}