Skip to content

A thin layer over USB to communicate with FTDI chips

License

Notifications You must be signed in to change notification settings

standardsemiconductor/ftdi

 
 

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 

History

83 Commits
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

FTDI

Haskell CI Hackage

This library enables you to communicate with FTDI USB devices. It is implemented as a lightweight wrapper around the usb library.

See bindings-libusb for instructions to install libusb.

Build Source (Ubuntu)

$ sudo apt install libusb-1.0-0-dev
$ git clone https://github.com/standardsemiconductor/ftdi.git
$ cd ftdi/
$ cabal build
$ cabal test

Sample Usage

Find the first USB device matching the vendor ID and product ID:

import qualified System.USB as USB
import qualified Data.Vector as V (toList)
import Data.List (find)
import System.FTDI

data Failure = FailureNotFound
             | FailureOther

findUSBDevice 
  :: USB.VendorId 
  -> USB.ProductId 
  -> IO (Either Failure (USB.Device, USB.Ctx))
findUSBDevice vendorId productId = do
  ctx <- USB.newCtx
  devDescs <- getDeviceDescs ctx
  return $ case fst <$> find (match . snd) devDescs of
    Nothing -> Left FailureNotFound
    Just dev -> Right (dev, ctx)
  where
    match :: USB.DeviceDesc -> Bool
    match devDesc =  USB.deviceVendorId  devDesc == vendorId
                  && USB.deviceProductId devDesc == productId

getDeviceDescs :: USB.Ctx -> IO [(USB.Device, USB.DeviceDesc)]
getDeviceDescs ctx = do
  devs <- V.toList <$> USB.getDevices ctx
  deviceDescs <- mapM USB.getDeviceDesc devs
  return $ zip devs deviceDescs

Setup an FT2232 FTDI device on interface A using MPSSE (Multi-Protocol Synchronous Serial Engine):

withFTDI 
  :: USB.VendorId 
  -> USB.productId
  -> (InterfaceHandle -> IO (Either Failure a) 
  -> IO (Either Failure a)
withFTDI vendorId productId action = findUSBDevice vendorId productId >>= \case
  Left failure -> return $ Left failure
  Right (usbDevice, ctx) -> do
    ftdiDevice <- fromUSBDevice usbDevice ChipType_2232H
    withDeviceHandle ftdiDevice $ \devHndl -> do
      resetUSB devHndl
      withDetachedKernelDriver devHndl Interface_A $
        withInterfaceHandle devHndl Interface_A $ \ifHndl -> do
          reset ifHndl
          purgeReadBuffer ifHndl
          purgeWriteBuffer ifHndl
          setLatencyTimer ifHndl 1
          setBitMode ifHndl 0xFF BitMode_MPSSE
          action ifHndl

References