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::{
|
use ftdi_vcp_sys::{
|
||||||
FT_Close, FT_GetBitMode, FT_GetComPortNumber, FT_OpenEx, FT_SetBitMode, FT_Write, DWORD,
|
FT_Close, FT_GetBitMode, FT_GetComPortNumber, FT_OpenEx, FT_Purge, FT_ResetDevice,
|
||||||
FT_HANDLE, FT_OPEN_BY_DESCRIPTION, FT_STATUS, LONG, LPDWORD, LPVOID, PVOID, UCHAR,
|
FT_SetBitMode, FT_Write, DWORD, FT_HANDLE, FT_OPEN_BY_DESCRIPTION, FT_STATUS, LONG, LPDWORD,
|
||||||
|
LPVOID, PVOID, UCHAR,
|
||||||
};
|
};
|
||||||
use std::convert::TryInto;
|
use std::convert::TryInto;
|
||||||
use std::ffi::CString;
|
use std::ffi::CString;
|
||||||
use std::mem::MaybeUninit;
|
|
||||||
use std::io::{Read, Write};
|
use std::io::{Read, Write};
|
||||||
|
use std::mem::MaybeUninit;
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
pub enum BitMode {
|
pub enum BitMode {
|
||||||
@ -77,6 +78,10 @@ pub enum Error {
|
|||||||
OtherError,
|
OtherError,
|
||||||
DeviceListNotReady,
|
DeviceListNotReady,
|
||||||
NoComPortAssigned,
|
NoComPortAssigned,
|
||||||
|
|
||||||
|
/// The provided string contained at least one NULL byte
|
||||||
|
StringContainsNullByte,
|
||||||
|
|
||||||
// UnknownBitMode(u8),
|
// UnknownBitMode(u8),
|
||||||
UnknownError(FT_STATUS),
|
UnknownError(FT_STATUS),
|
||||||
}
|
}
|
||||||
@ -124,7 +129,7 @@ pub struct VCP {
|
|||||||
|
|
||||||
impl VCP {
|
impl VCP {
|
||||||
pub fn new_from_name(name: &str) -> Result<VCP, Error> {
|
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 mut handle = MaybeUninit::<FT_HANDLE>::uninit();
|
||||||
let result = Error::from(unsafe {
|
let result = Error::from(unsafe {
|
||||||
FT_OpenEx(
|
FT_OpenEx(
|
||||||
@ -165,9 +170,30 @@ impl VCP {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// Set the given signals to "OUTPUT". All other signals will be "INPUT".
|
/// 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 {
|
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 {
|
if result != Error::NoError {
|
||||||
Err(result)
|
Err(result)
|
||||||
@ -206,8 +232,7 @@ impl Write for VCP {
|
|||||||
FT_Write(
|
FT_Write(
|
||||||
self.handle,
|
self.handle,
|
||||||
buf.as_ptr() as LPVOID,
|
buf.as_ptr() as LPVOID,
|
||||||
buf
|
buf.len()
|
||||||
.len()
|
|
||||||
.try_into()
|
.try_into()
|
||||||
.expect("couldn't convert buffer length to DWORD"),
|
.expect("couldn't convert buffer length to DWORD"),
|
||||||
bytes_written.as_mut_ptr() as LPDWORD,
|
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"
|
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
|
AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
extern crate winapi;
|
extern crate winapi;
|
||||||
// use winapi::um::winnt::{PVOID, ULONG, DWORD};
|
// 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};
|
pub use winapi::shared::ntdef::{LONG, PVOID, ULONG};
|
||||||
|
|
||||||
#[allow(non_camel_case_types)]
|
#[allow(non_camel_case_types)]
|
||||||
@ -54,13 +54,19 @@ pub enum FtStatus {
|
|||||||
// FT_FLAGS_HISPEED = 2,
|
// 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_SERIAL_NUMBER: DWORD = 1;
|
||||||
pub const FT_OPEN_BY_DESCRIPTION: DWORD = 2;
|
pub const FT_OPEN_BY_DESCRIPTION: DWORD = 2;
|
||||||
pub const FT_OPEN_BY_LOCATION: DWORD = 4;
|
pub const FT_OPEN_BY_LOCATION: DWORD = 4;
|
||||||
|
|
||||||
pub const FT_LIST_NUMBER_ONLY: DWORD = 0x80000000;
|
pub const FT_LIST_NUMBER_ONLY: DWORD = 0x8000_0000;
|
||||||
pub const FT_LIST_BY_INDEX: DWORD = 0x40000000;
|
pub const FT_LIST_BY_INDEX: DWORD = 0x4000_0000;
|
||||||
pub const FT_LIST_ALL: DWORD = 0x20000000;
|
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);
|
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;
|
) -> FT_STATUS;
|
||||||
pub fn FT_SetBitMode(ftHandle: FT_HANDLE, ucMask: UCHAR, ucEnable: UCHAR) -> 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_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> {
|
pub fn create_device_info_list() -> Result<usize, usize> {
|
||||||
@ -165,7 +176,7 @@ mod tests {
|
|||||||
for ch in item.Description.iter() {
|
for ch in item.Description.iter() {
|
||||||
print!(" {:02x}", ch);
|
print!(" {:02x}", ch);
|
||||||
}
|
}
|
||||||
println!("");
|
println!();
|
||||||
println!("ftHandle: {:08x}", item.ftHandle as usize);
|
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)
|
#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::thread::sleep;
|
||||||
use std::time::Duration;
|
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");
|
let mut vcp = VCP::new_from_name("iCEBreaker V1.0e A").expect("couldn't open vcp");
|
||||||
println!("Opened VCP: {:?}", 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 {
|
for i in 0..10 {
|
||||||
if i & 1 != 0 {
|
if i & 1 != 0 {
|
||||||
vcp.write(&[0x80]).expect("couldn't set all 1");
|
vcp.write(&[0x80])?;
|
||||||
} else {
|
} else {
|
||||||
vcp.write(&[0x00]).expect("couldn't set all 1");
|
vcp.write(&[0x00])?;
|
||||||
}
|
}
|
||||||
sleep(Duration::from_millis(500));
|
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