start implementing vcp wrapper functions
Signed-off-by: Sean Cross <sean@xobs.io>
This commit is contained in:
parent
e3bacc1e32
commit
05230aa6c4
@ -1,11 +1,12 @@
|
||||
use ftdi_vcp_sys::{
|
||||
FT_Close, FT_GetBitMode, FT_GetComPortNumber, FT_OpenEx, FT_SetBitMode, FT_Write, DWORD,
|
||||
FT_HANDLE, FT_OPEN_BY_DESCRIPTION, FT_STATUS, LONG, LPDWORD, LPVOID, PVOID, UCHAR,
|
||||
FT_Close, FT_GetBitMode, FT_GetComPortNumber, FT_OpenEx, FT_Purge, FT_ResetDevice,
|
||||
FT_SetBitMode, FT_Write, DWORD, FT_HANDLE, FT_OPEN_BY_DESCRIPTION, FT_STATUS, LONG, LPDWORD,
|
||||
LPVOID, PVOID, UCHAR,
|
||||
};
|
||||
use std::convert::TryInto;
|
||||
use std::ffi::CString;
|
||||
use std::mem::MaybeUninit;
|
||||
use std::io::{Read, Write};
|
||||
use std::mem::MaybeUninit;
|
||||
|
||||
#[derive(Debug)]
|
||||
pub enum BitMode {
|
||||
@ -77,6 +78,10 @@ pub enum Error {
|
||||
OtherError,
|
||||
DeviceListNotReady,
|
||||
NoComPortAssigned,
|
||||
|
||||
/// The provided string contained at least one NULL byte
|
||||
StringContainsNullByte,
|
||||
|
||||
// UnknownBitMode(u8),
|
||||
UnknownError(FT_STATUS),
|
||||
}
|
||||
@ -124,7 +129,7 @@ pub struct VCP {
|
||||
|
||||
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 c_str = CString::new(name).or(Err(Error::StringContainsNullByte))?;
|
||||
let mut handle = MaybeUninit::<FT_HANDLE>::uninit();
|
||||
let result = Error::from(unsafe {
|
||||
FT_OpenEx(
|
||||
@ -165,9 +170,30 @@ impl VCP {
|
||||
}
|
||||
|
||||
/// Set the given signals to "OUTPUT". All other signals will be "INPUT".
|
||||
pub fn set_bit_mode(&mut self, outputs: u8) -> Result<(), Error> {
|
||||
pub fn set_bitmode(&mut self, outputs: u8, bitmode: BitMode) -> Result<(), Error> {
|
||||
let result = Error::from(unsafe { FT_SetBitMode(self.handle, outputs, bitmode.to_u8()) });
|
||||
if result != Error::NoError {
|
||||
Err(result)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn reset(&mut self) -> Result<(), Error> {
|
||||
let result = Error::from(unsafe { FT_ResetDevice(self.handle) });
|
||||
if result != Error::NoError {
|
||||
Err(result)
|
||||
} else {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
pub fn purge(&mut self) -> Result<(), Error> {
|
||||
let result = Error::from(unsafe {
|
||||
FT_SetBitMode(self.handle, outputs, BitMode::SyncBitbang.to_u8())
|
||||
FT_Purge(
|
||||
self.handle,
|
||||
ftdi_vcp_sys::FT_PURGE_RX | ftdi_vcp_sys::FT_PURGE_TX,
|
||||
)
|
||||
});
|
||||
if result != Error::NoError {
|
||||
Err(result)
|
||||
@ -206,8 +232,7 @@ impl Write for VCP {
|
||||
FT_Write(
|
||||
self.handle,
|
||||
buf.as_ptr() as LPVOID,
|
||||
buf
|
||||
.len()
|
||||
buf.len()
|
||||
.try_into()
|
||||
.expect("couldn't convert buffer length to DWORD"),
|
||||
bytes_written.as_mut_ptr() as LPDWORD,
|
||||
|
@ -1,6 +1,6 @@
|
||||
/*++
|
||||
|
||||
Copyright © 2001-2011 Future Technology Devices International Limited
|
||||
Copyright <EFBFBD> 2001-2011 Future Technology Devices International Limited
|
||||
|
||||
THIS SOFTWARE IS PROVIDED BY FUTURE TECHNOLOGY DEVICES INTERNATIONAL LIMITED "AS IS"
|
||||
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||
|
@ -2,7 +2,7 @@
|
||||
|
||||
extern crate winapi;
|
||||
// use winapi::um::winnt::{PVOID, ULONG, DWORD};
|
||||
pub use winapi::shared::minwindef::{DWORD, LPDWORD, LPLONG, LPVOID, UCHAR, PUCHAR};
|
||||
pub use winapi::shared::minwindef::{BOOL, DWORD, LPDWORD, LPLONG, LPVOID, PUCHAR, UCHAR};
|
||||
pub use winapi::shared::ntdef::{LONG, PVOID, ULONG};
|
||||
|
||||
#[allow(non_camel_case_types)]
|
||||
@ -54,13 +54,19 @@ pub enum FtStatus {
|
||||
// FT_FLAGS_HISPEED = 2,
|
||||
// }
|
||||
|
||||
//
|
||||
// Purge rx and tx buffers
|
||||
//
|
||||
pub const FT_PURGE_RX: DWORD = 1;
|
||||
pub const FT_PURGE_TX: DWORD = 2;
|
||||
|
||||
pub const FT_OPEN_BY_SERIAL_NUMBER: DWORD = 1;
|
||||
pub const FT_OPEN_BY_DESCRIPTION: DWORD = 2;
|
||||
pub const FT_OPEN_BY_LOCATION: DWORD = 4;
|
||||
|
||||
pub const FT_LIST_NUMBER_ONLY: DWORD = 0x80000000;
|
||||
pub const FT_LIST_BY_INDEX: DWORD = 0x40000000;
|
||||
pub const FT_LIST_ALL: DWORD = 0x20000000;
|
||||
pub const FT_LIST_NUMBER_ONLY: DWORD = 0x8000_0000;
|
||||
pub const FT_LIST_BY_INDEX: DWORD = 0x4000_0000;
|
||||
pub const FT_LIST_ALL: DWORD = 0x2000_0000;
|
||||
|
||||
pub const FT_LIST_MASK: DWORD = (FT_LIST_NUMBER_ONLY | FT_LIST_BY_INDEX | FT_LIST_ALL);
|
||||
|
||||
@ -102,6 +108,11 @@ extern "stdcall" {
|
||||
) -> FT_STATUS;
|
||||
pub fn FT_SetBitMode(ftHandle: FT_HANDLE, ucMask: UCHAR, ucEnable: UCHAR) -> FT_STATUS;
|
||||
pub fn FT_GetBitMode(ftHandle: FT_HANDLE, pucMode: PUCHAR) -> FT_STATUS;
|
||||
pub fn FT_SetLatencyTimer(ftHandle: FT_HANDLE, ucLatency: UCHAR) -> FT_STATUS;
|
||||
pub fn FT_GetLatencyTimer(ftHandle: FT_HANDLE, pucLatency: PUCHAR) -> FT_STATUS;
|
||||
pub fn FT_ResetDevice(ftHandle: FT_HANDLE) -> FT_STATUS;
|
||||
pub fn FT_Purge(ftHandle: FT_HANDLE, dwMask: ULONG) -> FT_STATUS;
|
||||
pub fn FT_W32_PurgeComm(ftHandle: FT_HANDLE, dwMask: DWORD) -> BOOL;
|
||||
}
|
||||
|
||||
pub fn create_device_info_list() -> Result<usize, usize> {
|
||||
@ -165,7 +176,7 @@ mod tests {
|
||||
for ch in item.Description.iter() {
|
||||
print!(" {:02x}", ch);
|
||||
}
|
||||
println!("");
|
||||
println!();
|
||||
println!("ftHandle: {:08x}", item.ftHandle as usize);
|
||||
}
|
||||
}
|
||||
|
15
src/main.rs
15
src/main.rs
@ -6,21 +6,24 @@
|
||||
|
||||
#define FT_LIST_MASK (FT_LIST_NUMBER_ONLY|FT_LIST_BY_INDEX|FT_LIST_ALL)
|
||||
*/
|
||||
use ftdi_vcp_rs::VCP;
|
||||
use ftdi_vcp_rs::{VCP, BitMode};
|
||||
use std::thread::sleep;
|
||||
use std::time::Duration;
|
||||
|
||||
fn main() {
|
||||
fn main() -> Result<(), ftdi_vcp_rs::Error> {
|
||||
let mut vcp = VCP::new_from_name("iCEBreaker V1.0e A").expect("couldn't open vcp");
|
||||
println!("Opened VCP: {:?}", vcp);
|
||||
vcp.set_bit_mode(0x80).expect("couldn't set bit mode");
|
||||
vcp.reset()?;
|
||||
vcp.set_bitmode(0x80, BitMode::SyncBitbang)?;
|
||||
|
||||
for i in 0..10 {
|
||||
if i & 1 != 0 {
|
||||
vcp.write(&[0x80]).expect("couldn't set all 1");
|
||||
vcp.write(&[0x80])?;
|
||||
} else {
|
||||
vcp.write(&[0x00]).expect("couldn't set all 1");
|
||||
vcp.write(&[0x00])?;
|
||||
}
|
||||
sleep(Duration::from_millis(500));
|
||||
}
|
||||
println!("VCP COM{}:", vcp.com_port().expect("couldn't get com port"));
|
||||
println!("VCP COM{}:", vcp.com_port()?);
|
||||
Ok(())
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user