Skip to content

Commit

Permalink
Change read/write methods to return number of bytes.
Browse files Browse the repository at this point in the history
  • Loading branch information
newAM committed Dec 28, 2020
1 parent 5148d93 commit aded8f1
Show file tree
Hide file tree
Showing 6 changed files with 125 additions and 84 deletions.
11 changes: 10 additions & 1 deletion CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,14 @@ All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).

## [0.24.0] - 2020-12-28
### Changed
- **BREAKING CHANGE** `read` and `write` methods now return
`Result<usize, FtStatus>` where `usize` is the the number of bytes read or
written.
Previous `read` and `write` functionality that returned
`Result<(), TimeoutError>` is replaced by `read_all` and `write_all`.

## [0.23.0] - 2020-10-23
### Changed
- `synchronize_mpsse` will now timeout if no read data is received and a read
Expand Down Expand Up @@ -56,7 +64,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
## Prior releases
A changelog was not kept for prior releases.

[Unreleased]: https://github.com/newAM/libftd2xx-rs/compare/0.23.0...HEAD
[Unreleased]: https://github.com/newAM/libftd2xx-rs/compare/0.24.0...HEAD
[0.24.0]: https://github.com/newAM/libftd2xx-rs/releases/tag/0.24.0
[0.23.0]: https://github.com/newAM/libftd2xx-rs/releases/tag/0.23.0
[0.22.0]: https://github.com/newAM/libftd2xx-rs/releases/tag/0.22.0
[0.21.1]: https://github.com/newAM/libftd2xx-rs/releases/tag/0.21.1
Expand Down
2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[package]
name = "libftd2xx"
version = "0.23.0" # remember to update html_root_url
version = "0.24.0" # remember to update html_root_url
authors = ["Alex M. <[email protected]>"]
edition = "2018"
description = "Rust safe wrapper around the libftd2xx-ffi crate."
Expand Down
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ permission from FTDI.

```toml
[dependencies]
libftd2xx = "~0.23.0"
libftd2xx = "~0.24.0"
```

This is a basic example to get your started.
Expand Down
6 changes: 3 additions & 3 deletions src/errors.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,10 +18,10 @@ use libftd2xx_ffi::{

/// FTDI timeout errors.
///
/// This is used by the [`read`] and [`write`] functions.
/// This is used by the [`read_all`] and [`write_all`] methods.
///
/// [`read`]: trait.FtdiCommon.html#method.read
/// [`write`]: trait.FtdiCommon.html#method.read
/// [`read_all`]: trait.FtdiCommon.html#method.read_all
/// [`write_all`]: trait.FtdiCommon.html#method.read_all
#[derive(Debug, Copy, Clone, Eq, PartialEq)]
pub enum TimeoutError {
/// FTDI status errors.
Expand Down
119 changes: 75 additions & 44 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
//!
//! ```toml
//! [dependencies]
//! libftd2xx = "~0.23.0"
//! libftd2xx = "~0.24.0"
//! ```
//!
//! This is a basic example to get your started.
Expand Down Expand Up @@ -74,7 +74,7 @@
//! [libftd2xx-ffi]: https://github.com/newAM/libftd2xx-ffi-rs
//! [setup executable]: https://www.ftdichip.com/Drivers/CDM/CDM21228_Setup.zip
//! [udev]: https://en.wikipedia.org/wiki/Udev
#![doc(html_root_url = "https://docs.rs/libftd2xx/0.23.0")]
#![doc(html_root_url = "https://docs.rs/libftd2xx/0.24.0")]
#![deny(missing_docs)]

mod errors;
Expand Down Expand Up @@ -1226,20 +1226,53 @@ pub trait FtdiCommon {
)
}

/// Read data from the device, returning the number of bytes read.
///
/// See [`read_all`] for more information about reading from the device.
///
/// # Example
///
/// ```no_run
/// use libftd2xx::{Ftdi, FtdiCommon};
///
/// const BUF_SIZE: usize = 256;
/// let mut buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
/// let mut ft = Ftdi::new()?;
/// let bytes_read: usize = ft.read(&mut buf)?;
/// assert_eq!(bytes_read, BUF_SIZE);
/// # Ok::<(), libftd2xx::FtStatus>(())
/// ```
///
/// [`read_all`]: #method.read_all
fn read(&mut self, buf: &mut [u8]) -> Result<usize, FtStatus> {
let mut bytes_returned: u32 = 0;
let len: u32 = u32::try_from(buf.len()).unwrap();
trace!("FT_Read({:?}, _, {}, _)", self.handle(), len);
let status: FT_STATUS = unsafe {
FT_Read(
self.handle(),
buf.as_mut_ptr() as *mut c_void,
len,
&mut bytes_returned,
)
};
ft_result(usize::try_from(bytes_returned).unwrap(), status)
}

/// Read data from the device.
///
/// This method does not return until the buffer has been filled, if no
/// timeout has been set.
/// The number of bytes in the receive queue can be determined by calling
/// [`queue_status`], and then an buffer equal to the length of that
/// value can be passed to [`read`] so that the function reads the device
/// and returns immediately.
/// value can be passed to [`read_all`] so that the function reads the
/// device and returns immediately.
///
/// When a read timeout value has been specified in a previous call to
/// [`set_timeouts`], [`read`] returns when the timer expires or when the
/// buffer has been filled, whichever occurs first.
/// If the timeout occurred, [`read`] reads available data into the buffer
/// and returns [`TimeoutError`] error.
/// [`set_timeouts`], [`read_all`] returns when the timer expires or when
/// the buffer has been filled, whichever occurs first.
/// If the timeout occurred, [`read_all`] reads available data into the
/// buffer and returns the [`TimeoutError`] error.
///
/// # Examples
///
Expand All @@ -1253,7 +1286,7 @@ pub trait FtdiCommon {
/// let rx_bytes = ft.queue_status()?;
///
/// if rx_bytes > 0 {
/// ft.read(&mut buf[0..rx_bytes])?;
/// ft.read_all(&mut buf[0..rx_bytes])?;
/// }
/// # Ok::<(), libftd2xx::TimeoutError>(())
/// ```
Expand All @@ -1270,7 +1303,7 @@ pub trait FtdiCommon {
///
/// ft.set_timeouts(Duration::from_millis(5000), Duration::from_millis(0))?;
///
/// let valid_data = match ft.read(&mut buf) {
/// let valid_data = match ft.read_all(&mut buf) {
/// Err(e) => match e {
/// TimeoutError::Timeout {
/// actual: actual,
Expand All @@ -1288,28 +1321,12 @@ pub trait FtdiCommon {
/// # Ok::<(), libftd2xx::TimeoutError>(())
/// ```
///
/// [`read`]: #method.read
/// [`read_all`]: #method.read_all
/// [`queue_status`]: #method.queue_status
/// [`set_timeouts`]: #method.set_timeouts
/// [`TimeoutError`]: ./enum.TimeoutError.html
fn read(&mut self, buf: &mut [u8]) -> Result<(), TimeoutError> {
let mut bytes_returned: u32 = 0;
let len: u32 = u32::try_from(buf.len()).unwrap();
trace!("FT_Read({:?}, _, {}, _)", self.handle(), len);
let status: FT_STATUS = unsafe {
FT_Read(
self.handle(),
buf.as_mut_ptr() as *mut c_void,
len,
&mut bytes_returned,
)
};

if status != 0 {
return Err(TimeoutError::FtStatus(status.into()));
}

let num_read = usize::try_from(bytes_returned).unwrap();
fn read_all(&mut self, buf: &mut [u8]) -> Result<(), TimeoutError> {
let num_read = self.read(buf)?;
if num_read != buf.len() {
Err(TimeoutError::Timeout {
expected: buf.len(),
Expand All @@ -1330,10 +1347,36 @@ pub trait FtdiCommon {
/// const BUF_SIZE: usize = 256;
/// let buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
/// let mut ft = Ftdi::new()?;
/// ft.write(&buf)?;
/// ft.write_all(&buf)?;
/// # Ok::<(), libftd2xx::TimeoutError>(())
/// ```
fn write(&mut self, buf: &[u8]) -> Result<(), TimeoutError> {
fn write_all(&mut self, buf: &[u8]) -> Result<(), TimeoutError> {
let num_written = self.write(buf)?;
if num_written != buf.len() {
Err(TimeoutError::Timeout {
expected: buf.len(),
actual: num_written,
})
} else {
Ok(())
}
}

/// Write data to the device, returning how many bytes were written.
///
/// # Example
///
/// ```no_run
/// use libftd2xx::{Ftdi, FtdiCommon};
///
/// const BUF_SIZE: usize = 256;
/// let buf: [u8; BUF_SIZE] = [0; BUF_SIZE];
/// let mut ft = Ftdi::new()?;
/// let bytes_written: usize = ft.write(&buf)?;
/// assert_eq!(bytes_written, BUF_SIZE);
/// # Ok::<(), libftd2xx::FtStatus>(())
/// ```
fn write(&mut self, buf: &[u8]) -> Result<usize, FtStatus> {
let mut bytes_written: u32 = 0;
let len: u32 = u32::try_from(buf.len()).unwrap();
trace!("FT_Write({:?}, _, {}, _)", self.handle(), len);
Expand All @@ -1345,19 +1388,7 @@ pub trait FtdiCommon {
&mut bytes_written,
)
};
if status != 0 {
return Err(TimeoutError::FtStatus(status.into()));
}

let num_written = usize::try_from(bytes_written).unwrap();
if num_written != buf.len() {
Err(TimeoutError::Timeout {
expected: buf.len(),
actual: num_written,
})
} else {
Ok(())
}
ft_result(usize::try_from(bytes_written).unwrap(), status)
}

/// This function purges the transmit buffers in the device.
Expand Down
Loading

0 comments on commit aded8f1

Please sign in to comment.