The London Perl and Raku Workshop takes place on 26th Oct 2024. If your company depends on Perl, please consider sponsoring and/or attending.

NAME

Win32::FTDI::FTD2XX - PERL5 interface to FTDI's D2XX Direct USB Drivers

SYNOPSIS

  use Win32::FTDI::FTD2XX qw(:DEFAULT
        $FT_BAUD_38400 $FT_BITS_8 $FT_STOP_BITS_1 $FT_PARITY_NONE
        $FT_FLOW_RTS_CTS $PFT_MODEM_STATUS_CTS
        );

  my $FTD = Win32::FTDI::FTD2XX->new();
  unless( $FTD->PFT_STATUS() == $FT_OK )
    {
    printf( STDERR "FTD2XX::new() failed: %s (%s)\n", 
            $FTD->PFT_STATUS_MSG(), $FTD->PFT_ERROR() );
    exit( 1 );
    } 
  printf( "FTD2XX::new() allocated PFT_HANDLE: %d\n", $FTD->PFT_HANDLE() );

  my $numDevices = $FTD->GetNumDevices();
  unless( $FTD->PFT_STATUS() == $FT_OK )
    {
    printf( STDERR "FTD2XX::GetNumDevices() failed: %s (%s)\n",  
            $FTD->PFT_STATUS_MSG(), $FTD->PFT_ERROR() );
    exit( 1 );
    } 
  printf( "Found $numDevices FTDI devices connected!\n" );

DESCRIPTION

Win32::FTDI::FTD2XX provides a Perl5 interface to FTDI's D2XX Direct USB Drivers (CDM 2.04.06 as of this writing). It comes in two major components, the FTD2XX.pm module and an encapsulation and abstraction library, called P5FTD2XX.DLL, which wraps the FTDI FTD2XX.DLL, providing a cleaner interface which works better with Win32::API.

For instance, the simpler parameter passing mechanisms of Win32::API were never meant to handle things like (de)referencing and passing of pointers to pointers to buffers etc. The native FT_Open() driver function requires this to open the device handle, which then becomes the primary identifier for the connection to the rest of the API routines. Even when trying to pass the returned pointer around as an opaque datatype when returned through Win32::API, it fails to be recognized as a valid handle by the FT library, since the underlying pointer type's value/meaning gets mangled.

The P5FTD2XX Windows DLL abstracts the more complicated API calls and datatypes (like wrapping 'FT_HANDLE' with 'PFT_HANDLE') and provides other extensions to allow Perl to more conveniently interact with the FTDI devices using the native CDM drivers instead of the Virtual Comm Port (VCP), which can be problematic on Windows when trying to use older interfaces like Win32::CommPort or Win32::Serial.

The Win32::FTDI Perl object further abstracts and extends the API to make it most convenient for the Perl programming space, and looks after allocating & deallocating the PFT_HANDLEs and packed datatypes for parameter passing. In general, any export (see EXPORTS below) beginning with 'FT' is a direct Perl derivative of the original typedef's and #define's from the FTD2XX.H file. Any export prefixed with 'PFT' is an extension provided by the Win32::FTDI::FTD2Xxx.pm/P5FTD2XX DLL package.

Many of the native FT API's have been completely preserved, such as '(P)FT_SetDataCharacteristics', others, like the multi-function 'FT_Open', have been divided into simpler dedicated interfaces as 'PFT_OpenBySerial' and 'PFT_OpenByIndex' (Note: The object interface methods do not require the 'PFT_' prefix, except where noted). Other convenience methods have been added, like 'waitForModem( bitmask )' and the 'crack...' methods which extract bit fields from FT status bytes for you if you don't care to use the values directly.

Note: For performance gains at load time, each object method is autosplit/ autoloaded on demand, at which time each API Method also imports the actual API function from the DLL.

The entire package was developed and tested using an FTDI UM232R USB to Serial Bridge device, with an Atmel ATmegaX8 AVR microcontroller backend.

EXPORTS

The $FT_OK status variable is the only default export, as it is the basis for testing even the object's new() call. The other symbol exports may be chosen as desired on the 'use Win32::FTDI::FTD2XX' line as shown in the synopsis. See the FTD2XX.H header file and the FTD2XX Programmer's Guide for more information on their values. The PFT specific symbols are explained in the METHODS section.

The full list of available exports is: $FT_OK $FT_INVALID_HANDLE $FT_DEVICE_NOT_FOUND $FT_DEVICE_NOT_OPENED $FT_IO_ERROR $FT_INSUFFICIENT_RESOURCES $FT_INVALID_PARAMETER $FT_INVALID_BAUD_RATE $FT_DEVICE_NOT_OPENED_FOR_ERASE $FT_DEVICE_NOT_OPENED_FOR_WRITE $FT_FAILED_TO_WRITE_DEVICE $FT_EEPROM_READ_FAILED $FT_EEPROM_WRITE_FAILED $FT_EEPROM_ERASE_FAILED $FT_EEPROM_NOT_PRESENT $FT_EEPROM_NOT_PROGRAMMED $FT_INVALID_ARGS $FT_NOT_SUPPORTED $FT_OTHER_ERROR $FT_DEVICE_LIST_NOT_READY $PFTE_INVALID_API $PFTE_MAX_HANDLES $PFTE_INVALID_HANDLE $PFTE_WAIT_TIMEOUT $FT_BAUD_300 $FT_BAUD_600 $FT_BAUD_1200 $FT_BAUD_2400 $FT_BAUD_4800 $FT_BAUD_9600 $FT_BAUD_14400 $FT_BAUD_19200 $FT_BAUD_38400 $FT_BAUD_57600 $FT_BAUD_115200 $FT_BAUD_230400 $FT_BAUD_460800 $FT_BAUD_921600 $FT_BITS_8 $FT_BITS_7 $FT_BITS_6 $FT_BITS_5 $FT_STOP_BITS_1 $FT_STOP_BITS_1_5 $FT_STOP_BITS_2 $FT_PARITY_NONE $FT_PARITY_ODD $FT_PARITY_EVEN $FT_PARITY_MARK $FT_PARITY_SPACE $FT_FLOW_NONE $FT_FLOW_RTS_CTS $FT_FLOW_DTR_DSR $FT_FLOW_XON_XOFF $FT_PURGE_RX $FT_PURGE_TX $FT_DEFAULT_RX_TIMEOUT $FT_DEFAULT_TX_TIMEOUT $FT_DEVICE_BM $FT_DEVICE_AM $FT_DEVICE_100AX $FT_DEVICE_UNKNOWN $FT_DEVICE_2232C $FT_DEVICE_232R $PFT_FLOW_XonChar $PFT_FLOW_XoffChar $PFT_MODEM_STATUS_CTS $PFT_MODEM_STATUS_DSR $PFT_MODEM_STATUS_RI $PFT_MODEM_STATUS_DCD $PFT_MAX_SERIAL $PFT_MAX_DESCR $PFT_MAX_HANDLES

SEE ALSO

You'll probably want a copy of the FTDI D2XX Programmer's Guide to reference the corresponding API descriptions ...

http://www.ftdichip.com

OBJECT METHODS

The following methods have been provided for interaction with the P5FTD2XX and FTD2XX libraries. All methods set an internal status of type PFT_STATUS, which will include the values given in the standard FT_STATUS set (i.e. $FT_OK etc), as well as PFT specific values, (i.e. PFTE_INVALID_HANDLE). In some cases, if the method doesn't return some other specific value(s), it will generally return TRUE or FALSE (or undef) to indicate failure. Note: TRUE and FALSE are loosely bound to 1 and 0 respectively. On failure, the PFT_STATUS() accessor method can be used to query the PFT/FT_STATUS error value. PFT_ERROR_MSG() provides a quick string based translation of the error.

Standard parameter conventions apply: {required}, [optional], ...

In most cases, all numeric parameters are automatically packed and unpacked between their scalar and binary equivalents for passing into and out of the APIs. Only specific cases require the application to pack or unpack some datatypes, and will be covered in those methods.

New
      Parameters: [PFT_DEBUG => {FALSE|TRUE}]
      Returns: Object Reference (use PFT_STATUS method to check for errors)
      Purpose: Extension Method - Instanciates the FTDI perl object, loads the P5FTD2XX DLL
      and (as a dependency) the FTD2XX DLL. It will immediately import the PFT_New() and 
      PFT_Free() API's as a bare minimum, allocating a PFT_HANDLE type, which is this object
      instance's identifier to the P5FTD2XX library for its lifespan. PFT_HANDLE is synonymous
      with FT_HANDLE, and provides one per object instance. You may allocate a maximum of 
      $PFT_MAX_HANDLES objects. 
    
      The object includes an auto DESTROY method that will close any open FTDI device handle
      and deallocate the PFT_HANDLE in the P5FTD2XX interface, when it gets garbage collected
      by Perl.
    
      For a description of optional PFT_DEBUG parameter, see the PFT_DEBUG Accessor Method.
GetNumDevices
      Parameters: None
      Return Success: $numDevices 
      Return Failure: undef
      Purpose: Abstraction Method - Returns the number of connected FTDI devices. 
      See FT_ListDevices().
Rescan
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_Rescan()
    
      Note: As with other bus controls, there is a wait period of 3-5 seconds after
      a USB bus scan where any API call that requires direct connection to the device, 
      like GetSerialByIndex() etc, will fail with FT_INVALID_HANDLE until it has 
      completely stabilized. The application should account for this wait period, or
      setup a polling loop to detect the change in return status.
Reload
      Parameters: {$devVID, $devPID}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_Reload()
ResetPort
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_ResetPort()
ResetDevice
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_ResetDevice()
CyclePort
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_CyclePort()
      
      Note: As with other bus controls, there is a wait period of 5-8 seconds after
      a CyclePort where any API call that requires direct connection to the device, 
      like GetSerialByIndex() etc, will fail with FT_INVALID_HANDLE until it has 
      completely stabilized. The application should account for this wait period, or
      setup a polling loop to detect the change in return status.
GetDriverVersion
      Parameters: None
      Return Success: $driverVersion
      Return Failure: undef
      Purpose: API Method - See FT_GetDriverVersion()
crackDriverVersion
      Parameters: [$driverVersion]
      Return Success: $driverVersionDotNotation
      Return Failure: undef
      Purpose: Convenience method - translates the numeric DWORD from the driver to
      the equivalent dot notation (ie. "00020405" -> "2.04.05"). 
      If $driverVersion is supplied, it should be of the form returned by GetDriverVersion.
      If $driverVersion is undefined, GetDriverVersion will be called first to get the value.
GetLibraryVersion
      Parameters: None
      Return Success: $libraryVersion
      Return Failure: undef
      Purpose: API Method - See FT_GetLibraryVersion()
crackLibraryVersion
      Parameters: [$libraryVersion]
      Return Success: $libraryVersionDotNotation
      Return Failure: undef
      Purpose: Convenience method - translates the numeric DWORD from the library to
      the equivalent dot notation (ie. "00030115" -> "3.01.15"). 
      If $libraryVersion is supplied, it should be of the form returned by GetLibraryVersion.
      If $libraryVersion is undefined, GetLibraryVersion will be called first to get the value.
GetSerialByIndex
      Parameters: {$devIndex}
      Return Success: $devSerial
      Return Failure: undef
      Purpose: Abstraction Method - Returns the serial string of the connected FTDI device
      at the given index. See FT_ListDevices().
GetDescrByIndex
      Parameters: {$devIndex}
      Return Success: $devDescription
      Return Failure: undef
      Purpose: Abstraction Method - Returns the description string of the connected FTDI device
      at the given index. See FT_ListDevices().
GetDeviceInfo
      Parameters: {$devIndex}
      Return Success: $devInfo
      Return Failure: undef
      Purpose: Abstraction Method - See FT_GetDeviceInfo(). Returns all the description strings
      via a hash reference of the form:
        $devInfo->{TypeID};  # raw numeric device type ID
        $devInfo->{TypeNm};  # translated TypeID name string
        $devInfo->{VID};     # device's VID
        $devInfo->{PID};     # device's PID
        $devInfo->{Serial};  # serial number string
        $devInfo->{Descr};   # description string
OpenBySerial
      Parameters: {$devSerial}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: Abstraction Method - Opens a connection to the device based on serial number.
      See FT_Open(). Note: The object's Close() method should be called to free any previously
      opened FT_HANDLE.
OpenByIndex
      Parameters: {$devIndex}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: Abstraction Method - Opens a connection to the device based on index number.
      See FT_Open(). Note: The object's Close() method should be called to free any previously
      opened FT_HANDLE.
Close
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_Close().
SetBaudRate
      Parameters: {$baudRate}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetBaudRate().
SetDivisor
      Parameters: {$divisor}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetDivisor().
SetDataCharacteristics
      Parameters: {$dataBits, $stopBits, $parityBits}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetDataCharacteristics().
SetFlowControl
      Parameters: {$flowCtrl} [, $XonChar, $XoffChar]
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetFlowControl(). 
      Note: The ANSI standard Xon/Xoff characters have been defined in 
      $PFT_FLOW_XonChar (0x11), and $PFT_FLOW_XoffChar (0x13).
SetTimeouts
      Parameters: {$readTimeout, $writeTimeout}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetTimeouts(). 
GetTimeouts
      Parameters: None
      Return Success: $readTimeout, $writeTimeout
      Return Failure: undef
      Purpose: Extension Method - query the current timeout values, as previously set
      in SetTimeouts().
SetReadTimeout
      Parameters: {$readTimeout}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: Extension Method - Sets the read timeout without disturbing the current
      write timeout value.
GetReadTimeout
      Parameters: None
      Return Success: $readTimeout
      Return Failure: undef
      Purpose: Extension Method - Gets the current read timeout value.
SetWriteTimeout
      Parameters: {$writeTimeout}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: Extension Method - Sets the write timeout without disturbing the current
      read timeout value.
GetWriteTimeout
      Parameters: None
      Return Success: $writeTimeout
      Return Failure: undef
      Purpose: Extension Method - Gets the current write timeout value.
SetDtr
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetDtr().
ClrDtr
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_ClrDtr().
SetRts
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetRts().
ClrRts
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_ClrRts().
SetBreakOn
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetBreakOn().
SetBreakOff
      Parameters: None
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_SetBreakOff().
GetStatus
      Parameters: None
      Return Success: $amountInRxQueue, $amountInTxQueue, $eventStatus
      Return Failure: undef
      Purpose: API Method - See FT_GetStatus().
GetQueueStatus
      Parameters: None
      Return Success: $amountInRxQueue
      Return Failure: undef
      Purpose: API Method - See FT_GetQueueStatus().
GetModemStatus
      Parameters: None
      Return Success: $modemStatus
      Return Failure: undef
      Purpose: API Method - See FT_GetModemStatus().
crackModemStatus
      Parameters: {$modemStatusBitmask}
      Return Success: $statusCTS, $statusDSR, $statusRI, $statusDCD
      Return Failure: undef
      Purpose: Convenience Method - Based on the provided bitmask, sets each value in the returning
      array to TRUE if bit is set, FALSE otherwise. See FT_GetModemStatus().
waitForModem
      Parameters: {$modemStatusBitmask} [, $timeout] [, $pollTm]
      Return Success: TRUE
      Return Failure: FALSE (Check PFT_STATUS - FT API failure or $PFTE_WAIT_TIMEOUT set)
      Purpose: Extension Method - since the event API's are unimplemented, this method may be used
      to suspend program execution until one or more of the modem status bits is set (see
      GetModemStatus). 
    
      The modemStatusBitmask is formed using the $PFT_MODEM_STATUS_xxx bit definitions. i.e.:
        $FTD->waitForModem( $PFT_MODEM_STATUS_CTS, 3 );
      would wait max 3 seconds for the device's CTS signal to assert itself.
    
      The optional $timeout provides a limiting timeframe to wait, in seconds. Fractional seconds,
      i.e. 0.5 (500ms) are allowed. The timeout is infinite if undefined. 
    
      The optional $pollTm is the time in seconds between polls of the device. The default is 0.25
      (250ms). 
    
      Note: the timeout is NOT implemented in real time clock fassion, so it should not be used for
      critical timing sequences, but is accurate enough for most uses. When setting $timeout and/or
      $pollTm, $timeout should be an even multiple of $pollTm, or if not, the overlap in timing should
      be accounted for if neccessary. 
Purge
      Parameters: {$mask}
      Return Success: TRUE
      Return Failure: FALSE
      Purpose: API Method - See FT_Purge().
Read
      Parameters: {$bytesToRead}
      Return Success: $bytesReturned, $readBuffer
      Return Failure: undef
      Purpose: API Method - See FT_Read().
      Note: The method treats the returned buffer content as an opaque scalar value. Any translation
      of strings or unpacking of binary content must be done by the application.
Write
      Parameters: {$writeBuffer} [, $bytesToWrite]
      Return Success: $bytesWritten
      Return Failure: undef
      Purpose: API Method - See FT_Write().
      Note: The method treats the write buffer content as an opaque scalar value. Any translation
      of strings or packing of binary content must be done by the application.
      If $bytesToWrite is not specified, the method will use the return of 'length($writeBuffer)'.
      If $bytesToWrite is specified, it allows sending a full or partial buffer; however, the result
      of sending more bytes than are in the buffer is undefined.
P5VERSION
      Parameters: None
      Return Success: $PFT_DLL_VERSION
      Return Failure: undef
      Purpose: Accesor Method - returns the version of the P5FTD2XX DLL in use.
VERSION
      Parameters: None
      Return Success: $FTD2XX_MODULE_VERSION
      Return Failure: undef
      Purpose: Accesor Method - returns the version of the FTD2XX.pm in use.
PFT_HANDLE
      Parameters: None
      Return Success: $PFT_HANDLE
      Return Failure: undef
      Purpose: Accesor Method - returns the numeric PFT_HANDLE allocated by the 
      P5FTD2XX library which identifies the object's unique connection and state
      information store.
PFT_STATUS
      Parameters: None
      Return Success: $PFT_STATUS
      Return Failure: undef
      Purpose: Accesor Method - returns the enumerated status/error values of the last
      method call (see FT and PFTE extensions in EXPORTS). In addition to the FT status
      types, the PFT specific error types are: 
      $PFTE_INVALID_API - Requested API not in P5FTD2XX.DLL - usually a bug on my part, or the
        P5FTD2XX.DLL can't be found in the system PATH (default: "%SystemRoot%\System32")
      $PFTE_INVALID_HANDLE - The PFT_HANDLE passed is not valid (also usually a bug on my part)
      $PFTE_MAX_HANDLES - You've allocated max objects/PFT_HANDLES from the P5FTD2XX interface
      $PFTE_WAIT_TIMEOUT - error type for 'waitForModem' method on timeout only
PFT_STATUS_MSG
      Parameters: $PFT_STATUS
      Return Success: $PFT_STATUS_MSG
      Return Failure: undef
      Purpose: Accesor Method - translates the enumerated FT_STATUS/PFT_STATUS values into
      text equivalent for ease of generating error output.
PFT_ERROR
      Parameters: None
      Return Success: $PFT_ERROR
      Return Failure: undef
      Purpose: Accesor Method - some methods may have extended error information regarding the
      failure reported in the (P)FT_STATUS types, and are returned here. 
PFT_DEBUG
      Parameters: {TRUE|FALSE}
      Return Success: $previousState
      Return Failure: undef
      Purpose: Accesor Method - some methods may have extended runtime debug information that
      can be sent to STDERR when this variable is set to TRUE.

DEPENDENCIES

The FTDI/FTD2XX Drivers, at least CDM 2.04.06, must be installed in conjunction with this module for it to be functional (and, obviously, to get very far, you'll need an FTDI device plugged into your USB bus...)

The perl object uses Win32::API (v0.55 on my ActiveState 5.8.8 build) to interface with the P5FTD2XX DLL.

BUGS and THINGS TO DO

Please report bugs to me at my email address below.

See the BUGS file in the distribution for known issues and their status.

Things to Do

1) The FT_EVENT features have not been ported, and may or may not be, depending on demand (see the 'waitForModem' method instead for now).

2) Complete the EEPROM API interface.

3) Possibly complete the Extended API Function interfaces.

4) Win the lottery, buy an island and retire ...

AND... if anyone is really just peeing their pants for a particular function that I haven't provided or ported yet, let me know and I'll see what I can do with the time I have.

AUTHOR

Scott K. MacPherson <skmacphe@cpan.org>

COPYRIGHT AND LICENSE

Copyright (C) 2008 by Scott K. MacPherson, Akron, Ohio

This library is free software; you can redistribute it and/or modify it under the same terms as Perl itself, either Perl version 5.8.8 or, at your option, any later version of Perl 5 you may have available.