Skip to content

Commit

Permalink
feat: Add support for 4232HA
Browse files Browse the repository at this point in the history
Co-authored-by: Alex Martens <alex@thinglab.org>
  • Loading branch information
kiranshila and newAM committed Aug 20, 2024
1 parent f273f4c commit b2de799
Show file tree
Hide file tree
Showing 4 changed files with 105 additions and 11 deletions.
4 changes: 4 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@ 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).

## [Unreleased]
### Added
- Added support for the 4232HA

## [0.32.4] - 2024-03-04
### Added
- Added EEPROM implementations for the 232R.
Expand Down
87 changes: 81 additions & 6 deletions src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -341,7 +341,7 @@ pub fn list_devices() -> Result<Vec<DeviceInfo>, FtStatus> {
/// Lists FTDI devices using the Linux file system.
///
/// There is a bug in the vendor driver where the `serial_number` and
/// `description` fields may be blank on the FT4232H and FT2232H when only
/// `description` fields may be blank on the FT4232H(A) FT2232H when only
/// some of the ports are unbound from the `ftdi_sio` linux kernel module.
///
/// This will not work if you have a custom VID/PID programmed onto your FTDI
Expand Down Expand Up @@ -426,7 +426,7 @@ pub fn list_devices_fs() -> io::Result<Vec<DeviceInfo>> {

let port_letters: Option<&'static [char]> = match device_type {
DeviceType::FT2232H => Some(&['A', 'B']),
DeviceType::FT4232H => Some(&['A', 'B', 'C', 'D']),
DeviceType::FT4232H | DeviceType::FT4232HA => Some(&['A', 'B', 'C', 'D']),
_ => None,
};

Expand Down Expand Up @@ -546,7 +546,7 @@ pub struct Ft232r {
/// ```no_run
/// use libftd2xx::{Ft2232h, Ftdi};
///
/// let ft4232h: Ft2232h = Ftdi::new()?.try_into()?;
/// let ft2232h: Ft2232h = Ftdi::new()?.try_into()?;
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
/// ```
#[derive(Debug)]
Expand All @@ -571,6 +571,23 @@ pub struct Ft4232h {
ftdi: Ftdi,
}

/// FT4232HA device.
///
/// # Example
///
/// Converting from an unknown FTDI device.
///
/// ```no_run
/// use libftd2xx::{Ft4232ha, Ftdi};
///
/// let ft4232ha: Ft4232ha = Ftdi::new()?.try_into()?;
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
/// ```
#[derive(Debug)]
pub struct Ft4232ha {
ftdi: Ftdi,
}

/// FTD2XX functions common to all devices.
pub trait FtdiCommon {
/// FTDI device type.
Expand Down Expand Up @@ -622,6 +639,7 @@ pub trait FtdiCommon {
0x1800 => Ok(DeviceType::FT4222H_0),
0x1900 => Ok(DeviceType::FT4222H_1_2),
0x2100 => Ok(DeviceType::FT4222_PROG),
0x3600 => Ok(DeviceType::FT4232HA),
_ => Err(FtStatus::OTHER_ERROR),
}
}
Expand Down Expand Up @@ -1642,7 +1660,7 @@ pub trait FtdiCommon {
/// It is the responsibility of the application to close the handle after
/// successfully calling this method.
///
/// For FT4232H, FT2232H and FT2232 devices, `cycle_port` will only work
/// For FT4232H(A), FT2232H and FT2232 devices, `cycle_port` will only work
/// under Windows XP and later.
///
/// # Example
Expand Down Expand Up @@ -1857,7 +1875,7 @@ pub trait FtdiEeprom<
///
/// # Example
///
/// This example uses the FT232H.
/// This example uses the FT4232H.
///
/// ```no_run
/// use libftd2xx::{Ft4232h, Ftdi, FtdiEeprom};
Expand Down Expand Up @@ -2061,7 +2079,7 @@ impl Ftdi {
}

impl Ft232h {
/// Open a `Ft4232h` device and initialize the handle.
/// Open a `Ft232h` device and initialize the handle.
///
/// # Safety
///
Expand Down Expand Up @@ -2272,6 +2290,59 @@ impl Ft4232h {
}
}

impl Ft4232ha {
/// Open a `Ft4232ha` device and initialize the handle.
///
/// # Safety
///
/// This is **unchecked** meaning a device type check will not be performed.
/// Methods that require this specific device type may fail in unexpected
/// ways if the wrong device is used.
///
/// # Example
///
/// ```no_run
/// use libftd2xx::Ft4232ha;
///
/// let mut ft = unsafe { Ft4232ha::with_serial_number_unchecked("FT4PWSEOA")? };
/// # Ok::<(), libftd2xx::FtStatus>(())
/// ```
pub unsafe fn with_serial_number_unchecked(serial_number: &str) -> Result<Ft4232ha, FtStatus> {
let handle = ft_open_ex(serial_number, FT_OPEN_BY_SERIAL_NUMBER)?;
Ok(Ft4232ha {
ftdi: Ftdi { handle },
})
}

/// Open a `Ft4232ha` device and initialize the handle.
///
/// # Example
///
/// ```no_run
/// use libftd2xx::Ft4232ha;
///
/// Ft4232ha::with_serial_number("FT4PWSEOA")?;
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
/// ```
pub fn with_serial_number(serial_number: &str) -> Result<Ft4232ha, DeviceTypeError> {
Ftdi::with_serial_number(serial_number)?.try_into()
}

/// Open a `Ft4232ha` device by its device description.
///
/// # Example
///
/// ```no_run
/// use libftd2xx::Ft4232ha;
///
/// Ft4232ha::with_description("Quad RS232-HS A")?;
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
/// ```
pub fn with_description(description: &str) -> Result<Ft4232ha, DeviceTypeError> {
Ftdi::with_description(description)?.try_into()
}
}

impl FtdiCommon for Ftdi {
const DEVICE_TYPE: DeviceType = DeviceType::Unknown;

Expand Down Expand Up @@ -2351,11 +2422,13 @@ impl_boilerplate_for!(Ft232h, DeviceType::FT232H);
impl_boilerplate_for!(Ft232r, DeviceType::FT232R);
impl_boilerplate_for!(Ft2232h, DeviceType::FT2232H);
impl_boilerplate_for!(Ft4232h, DeviceType::FT4232H);
impl_boilerplate_for!(Ft4232ha, DeviceType::FT4232HA);

impl_try_from_for!(Ft232h);
impl_try_from_for!(Ft232r);
impl_try_from_for!(Ft2232h);
impl_try_from_for!(Ft4232h);
impl_try_from_for!(Ft4232ha);

impl FtdiEeprom<FT_EEPROM_232H, Eeprom232h> for Ft232h {}
impl FtdiEeprom<FT_EEPROM_232R, Eeprom232r> for Ft232r {}
Expand All @@ -2366,6 +2439,8 @@ impl FtdiMpsse for Ft232h {}
impl FtdiMpsse for Ft232r {}
impl FtdiMpsse for Ft2232h {}
impl FtdiMpsse for Ft4232h {}
impl FtdiMpsse for Ft4232ha {}
impl Ftx232hMpsse for Ft232h {}
impl Ftx232hMpsse for Ft2232h {}
impl Ftx232hMpsse for Ft4232h {}
impl Ftx232hMpsse for Ft4232ha {}
17 changes: 14 additions & 3 deletions src/mpsse.rs
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,7 @@ fn clock_divisor(device: DeviceType, frequency: u32) -> (u32, Option<bool>) {
check_limits(device, frequency, 6_000_000);
(6_000_000 / frequency - 1, None)
}
DeviceType::FT2232H | DeviceType::FT4232H | DeviceType::FT232H => {
DeviceType::FT2232H | DeviceType::FT4232H | DeviceType::FT4232HA | DeviceType::FT232H => {
check_limits(device, frequency, 30_000_000);
if frequency <= 6_000_000 {
(6_000_000 / frequency - 1, Some(true))
Expand Down Expand Up @@ -80,7 +80,18 @@ mod clock_divisor {
6_000_001,
(3, Some(false))
);
pos!(max, DeviceType::FT4232H, 30_000_000, (0, Some(false)));
pos!(
ft4232h_max,
DeviceType::FT4232H,
30_000_000,
(0, Some(false))
);
pos!(
ft4232ha_max,
DeviceType::FT4232HA,
30_000_000,
(0, Some(false))
);

neg!(panic_unknown, DeviceType::Unknown, 1_000);
neg!(panic_ft232c_min, DeviceType::FT2232C, 91);
Expand Down Expand Up @@ -424,7 +435,7 @@ pub trait FtdiMpsse: FtdiCommon {
}

/// This contains MPSSE commands that are only available on the the FT232H,
/// FT2232H, and FT4232H devices.
/// FT2232H, and FT4232H(A) devices.
///
/// For details about the MPSSE read the [FTDI MPSSE Basics].
///
Expand Down
8 changes: 6 additions & 2 deletions src/types.rs
Original file line number Diff line number Diff line change
Expand Up @@ -237,7 +237,7 @@ pub enum DeviceType {
impl DeviceType {
/// Get a device type with a USB product ID.
///
/// This is not entirely accurate since soem devices share the same PID.
/// This is not entirely accurate since some devices share the same PID.
///
/// # Example
///
Expand All @@ -254,6 +254,8 @@ impl DeviceType {
Some(DeviceType::FT2232H)
} else if pid == 0x6011 {
Some(DeviceType::FT4232H)
} else if pid == 0x6048 {
Some(DeviceType::FT4232HA)
} else if pid == 0x6014 {
Some(DeviceType::FT232H)
} else if pid == 0x6015 {
Expand Down Expand Up @@ -281,6 +283,7 @@ impl From<u32> for DeviceType {
DEVICE_232R => DeviceType::FT232R,
DEVICE_2232H => DeviceType::FT2232H,
DEVICE_4232H => DeviceType::FT4232H,
DEVICE_4232HA => DeviceType::FT4232HA,
DEVICE_232H => DeviceType::FT232H,
DEVICE_X_SERIES => DeviceType::FT_X_SERIES,
DEVICE_4222H_0 => DeviceType::FT4222H_0,
Expand Down Expand Up @@ -433,7 +436,7 @@ pub enum BitMode {
Reset = FT_BITMODE_RESET as u8,
/// Asynchronous bit bang.
AsyncBitbang = FT_BITMODE_ASYNC_BITBANG as u8,
/// MPSSE (FT2232, FT2232H, FT4232H and FT232H devices only)
/// MPSSE (FT2232, FT2232H, FT4232H(A) and FT232H devices only)
Mpsse = FT_BITMODE_MPSSE as u8,
/// Synchronous Bit Bang
/// (FT232R, FT245R,FT2232, FT2232H, FT4232H and FT232H devices only)
Expand Down Expand Up @@ -606,6 +609,7 @@ pub struct DeviceInfo {
/// * `0x6001` FT232AM/FT232BM/FT232R
/// * `0x6010` FT2232C/FT2232D/FT2232H
/// * `0x6011` FT4232/FT4232H
/// * `0x6048` FT4232HA
/// * `0x6014` FT232H
/// * `0x6015` FT230X/FT231X/FT234X
pub product_id: u16,
Expand Down

0 comments on commit b2de799

Please sign in to comment.