Skip to content

Commit b2de799

Browse files
kiranshilanewAM
andcommitted
feat: Add support for 4232HA
Co-authored-by: Alex Martens <[email protected]>
1 parent f273f4c commit b2de799

File tree

4 files changed

+105
-11
lines changed

4 files changed

+105
-11
lines changed

CHANGELOG.md

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ All notable changes to this project will be documented in this file.
44
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
55
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
66

7+
## [Unreleased]
8+
### Added
9+
- Added support for the 4232HA
10+
711
## [0.32.4] - 2024-03-04
812
### Added
913
- Added EEPROM implementations for the 232R.

src/lib.rs

Lines changed: 81 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -341,7 +341,7 @@ pub fn list_devices() -> Result<Vec<DeviceInfo>, FtStatus> {
341341
/// Lists FTDI devices using the Linux file system.
342342
///
343343
/// There is a bug in the vendor driver where the `serial_number` and
344-
/// `description` fields may be blank on the FT4232H and FT2232H when only
344+
/// `description` fields may be blank on the FT4232H(A) FT2232H when only
345345
/// some of the ports are unbound from the `ftdi_sio` linux kernel module.
346346
///
347347
/// This will not work if you have a custom VID/PID programmed onto your FTDI
@@ -426,7 +426,7 @@ pub fn list_devices_fs() -> io::Result<Vec<DeviceInfo>> {
426426

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

@@ -546,7 +546,7 @@ pub struct Ft232r {
546546
/// ```no_run
547547
/// use libftd2xx::{Ft2232h, Ftdi};
548548
///
549-
/// let ft4232h: Ft2232h = Ftdi::new()?.try_into()?;
549+
/// let ft2232h: Ft2232h = Ftdi::new()?.try_into()?;
550550
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
551551
/// ```
552552
#[derive(Debug)]
@@ -571,6 +571,23 @@ pub struct Ft4232h {
571571
ftdi: Ftdi,
572572
}
573573

574+
/// FT4232HA device.
575+
///
576+
/// # Example
577+
///
578+
/// Converting from an unknown FTDI device.
579+
///
580+
/// ```no_run
581+
/// use libftd2xx::{Ft4232ha, Ftdi};
582+
///
583+
/// let ft4232ha: Ft4232ha = Ftdi::new()?.try_into()?;
584+
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
585+
/// ```
586+
#[derive(Debug)]
587+
pub struct Ft4232ha {
588+
ftdi: Ftdi,
589+
}
590+
574591
/// FTD2XX functions common to all devices.
575592
pub trait FtdiCommon {
576593
/// FTDI device type.
@@ -622,6 +639,7 @@ pub trait FtdiCommon {
622639
0x1800 => Ok(DeviceType::FT4222H_0),
623640
0x1900 => Ok(DeviceType::FT4222H_1_2),
624641
0x2100 => Ok(DeviceType::FT4222_PROG),
642+
0x3600 => Ok(DeviceType::FT4232HA),
625643
_ => Err(FtStatus::OTHER_ERROR),
626644
}
627645
}
@@ -1642,7 +1660,7 @@ pub trait FtdiCommon {
16421660
/// It is the responsibility of the application to close the handle after
16431661
/// successfully calling this method.
16441662
///
1645-
/// For FT4232H, FT2232H and FT2232 devices, `cycle_port` will only work
1663+
/// For FT4232H(A), FT2232H and FT2232 devices, `cycle_port` will only work
16461664
/// under Windows XP and later.
16471665
///
16481666
/// # Example
@@ -1857,7 +1875,7 @@ pub trait FtdiEeprom<
18571875
///
18581876
/// # Example
18591877
///
1860-
/// This example uses the FT232H.
1878+
/// This example uses the FT4232H.
18611879
///
18621880
/// ```no_run
18631881
/// use libftd2xx::{Ft4232h, Ftdi, FtdiEeprom};
@@ -2061,7 +2079,7 @@ impl Ftdi {
20612079
}
20622080

20632081
impl Ft232h {
2064-
/// Open a `Ft4232h` device and initialize the handle.
2082+
/// Open a `Ft232h` device and initialize the handle.
20652083
///
20662084
/// # Safety
20672085
///
@@ -2272,6 +2290,59 @@ impl Ft4232h {
22722290
}
22732291
}
22742292

2293+
impl Ft4232ha {
2294+
/// Open a `Ft4232ha` device and initialize the handle.
2295+
///
2296+
/// # Safety
2297+
///
2298+
/// This is **unchecked** meaning a device type check will not be performed.
2299+
/// Methods that require this specific device type may fail in unexpected
2300+
/// ways if the wrong device is used.
2301+
///
2302+
/// # Example
2303+
///
2304+
/// ```no_run
2305+
/// use libftd2xx::Ft4232ha;
2306+
///
2307+
/// let mut ft = unsafe { Ft4232ha::with_serial_number_unchecked("FT4PWSEOA")? };
2308+
/// # Ok::<(), libftd2xx::FtStatus>(())
2309+
/// ```
2310+
pub unsafe fn with_serial_number_unchecked(serial_number: &str) -> Result<Ft4232ha, FtStatus> {
2311+
let handle = ft_open_ex(serial_number, FT_OPEN_BY_SERIAL_NUMBER)?;
2312+
Ok(Ft4232ha {
2313+
ftdi: Ftdi { handle },
2314+
})
2315+
}
2316+
2317+
/// Open a `Ft4232ha` device and initialize the handle.
2318+
///
2319+
/// # Example
2320+
///
2321+
/// ```no_run
2322+
/// use libftd2xx::Ft4232ha;
2323+
///
2324+
/// Ft4232ha::with_serial_number("FT4PWSEOA")?;
2325+
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
2326+
/// ```
2327+
pub fn with_serial_number(serial_number: &str) -> Result<Ft4232ha, DeviceTypeError> {
2328+
Ftdi::with_serial_number(serial_number)?.try_into()
2329+
}
2330+
2331+
/// Open a `Ft4232ha` device by its device description.
2332+
///
2333+
/// # Example
2334+
///
2335+
/// ```no_run
2336+
/// use libftd2xx::Ft4232ha;
2337+
///
2338+
/// Ft4232ha::with_description("Quad RS232-HS A")?;
2339+
/// # Ok::<(), libftd2xx::DeviceTypeError>(())
2340+
/// ```
2341+
pub fn with_description(description: &str) -> Result<Ft4232ha, DeviceTypeError> {
2342+
Ftdi::with_description(description)?.try_into()
2343+
}
2344+
}
2345+
22752346
impl FtdiCommon for Ftdi {
22762347
const DEVICE_TYPE: DeviceType = DeviceType::Unknown;
22772348

@@ -2351,11 +2422,13 @@ impl_boilerplate_for!(Ft232h, DeviceType::FT232H);
23512422
impl_boilerplate_for!(Ft232r, DeviceType::FT232R);
23522423
impl_boilerplate_for!(Ft2232h, DeviceType::FT2232H);
23532424
impl_boilerplate_for!(Ft4232h, DeviceType::FT4232H);
2425+
impl_boilerplate_for!(Ft4232ha, DeviceType::FT4232HA);
23542426

23552427
impl_try_from_for!(Ft232h);
23562428
impl_try_from_for!(Ft232r);
23572429
impl_try_from_for!(Ft2232h);
23582430
impl_try_from_for!(Ft4232h);
2431+
impl_try_from_for!(Ft4232ha);
23592432

23602433
impl FtdiEeprom<FT_EEPROM_232H, Eeprom232h> for Ft232h {}
23612434
impl FtdiEeprom<FT_EEPROM_232R, Eeprom232r> for Ft232r {}
@@ -2366,6 +2439,8 @@ impl FtdiMpsse for Ft232h {}
23662439
impl FtdiMpsse for Ft232r {}
23672440
impl FtdiMpsse for Ft2232h {}
23682441
impl FtdiMpsse for Ft4232h {}
2442+
impl FtdiMpsse for Ft4232ha {}
23692443
impl Ftx232hMpsse for Ft232h {}
23702444
impl Ftx232hMpsse for Ft2232h {}
23712445
impl Ftx232hMpsse for Ft4232h {}
2446+
impl Ftx232hMpsse for Ft4232ha {}

src/mpsse.rs

Lines changed: 14 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -30,7 +30,7 @@ fn clock_divisor(device: DeviceType, frequency: u32) -> (u32, Option<bool>) {
3030
check_limits(device, frequency, 6_000_000);
3131
(6_000_000 / frequency - 1, None)
3232
}
33-
DeviceType::FT2232H | DeviceType::FT4232H | DeviceType::FT232H => {
33+
DeviceType::FT2232H | DeviceType::FT4232H | DeviceType::FT4232HA | DeviceType::FT232H => {
3434
check_limits(device, frequency, 30_000_000);
3535
if frequency <= 6_000_000 {
3636
(6_000_000 / frequency - 1, Some(true))
@@ -80,7 +80,18 @@ mod clock_divisor {
8080
6_000_001,
8181
(3, Some(false))
8282
);
83-
pos!(max, DeviceType::FT4232H, 30_000_000, (0, Some(false)));
83+
pos!(
84+
ft4232h_max,
85+
DeviceType::FT4232H,
86+
30_000_000,
87+
(0, Some(false))
88+
);
89+
pos!(
90+
ft4232ha_max,
91+
DeviceType::FT4232HA,
92+
30_000_000,
93+
(0, Some(false))
94+
);
8495

8596
neg!(panic_unknown, DeviceType::Unknown, 1_000);
8697
neg!(panic_ft232c_min, DeviceType::FT2232C, 91);
@@ -424,7 +435,7 @@ pub trait FtdiMpsse: FtdiCommon {
424435
}
425436

426437
/// This contains MPSSE commands that are only available on the the FT232H,
427-
/// FT2232H, and FT4232H devices.
438+
/// FT2232H, and FT4232H(A) devices.
428439
///
429440
/// For details about the MPSSE read the [FTDI MPSSE Basics].
430441
///

src/types.rs

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -237,7 +237,7 @@ pub enum DeviceType {
237237
impl DeviceType {
238238
/// Get a device type with a USB product ID.
239239
///
240-
/// This is not entirely accurate since soem devices share the same PID.
240+
/// This is not entirely accurate since some devices share the same PID.
241241
///
242242
/// # Example
243243
///
@@ -254,6 +254,8 @@ impl DeviceType {
254254
Some(DeviceType::FT2232H)
255255
} else if pid == 0x6011 {
256256
Some(DeviceType::FT4232H)
257+
} else if pid == 0x6048 {
258+
Some(DeviceType::FT4232HA)
257259
} else if pid == 0x6014 {
258260
Some(DeviceType::FT232H)
259261
} else if pid == 0x6015 {
@@ -281,6 +283,7 @@ impl From<u32> for DeviceType {
281283
DEVICE_232R => DeviceType::FT232R,
282284
DEVICE_2232H => DeviceType::FT2232H,
283285
DEVICE_4232H => DeviceType::FT4232H,
286+
DEVICE_4232HA => DeviceType::FT4232HA,
284287
DEVICE_232H => DeviceType::FT232H,
285288
DEVICE_X_SERIES => DeviceType::FT_X_SERIES,
286289
DEVICE_4222H_0 => DeviceType::FT4222H_0,
@@ -433,7 +436,7 @@ pub enum BitMode {
433436
Reset = FT_BITMODE_RESET as u8,
434437
/// Asynchronous bit bang.
435438
AsyncBitbang = FT_BITMODE_ASYNC_BITBANG as u8,
436-
/// MPSSE (FT2232, FT2232H, FT4232H and FT232H devices only)
439+
/// MPSSE (FT2232, FT2232H, FT4232H(A) and FT232H devices only)
437440
Mpsse = FT_BITMODE_MPSSE as u8,
438441
/// Synchronous Bit Bang
439442
/// (FT232R, FT245R,FT2232, FT2232H, FT4232H and FT232H devices only)
@@ -606,6 +609,7 @@ pub struct DeviceInfo {
606609
/// * `0x6001` FT232AM/FT232BM/FT232R
607610
/// * `0x6010` FT2232C/FT2232D/FT2232H
608611
/// * `0x6011` FT4232/FT4232H
612+
/// * `0x6048` FT4232HA
609613
/// * `0x6014` FT232H
610614
/// * `0x6015` FT230X/FT231X/FT234X
611615
pub product_id: u16,

0 commit comments

Comments
 (0)