I'm using usb-1.3.0.4 / System.USB. Having scanned and selected a relevant serial USB device, how do I find the corresponding serial port (e.g. COM3 on Windows)?
Here is an example of what I'm after:
module Main (main) where
import System.USB
import System.Hardware.Serialport
import qualified Data.Vector as V
import Data.Maybe
main :: IO ()
main = do
devicePort 0x2341 0x0043 >>= either putStrLn usePort
where usePort p = do
s <- openSerial p defaultSerialSettings
putStrLn $ "opened serial port " ++ p
closeSerial s
-- | Find port for attached USB serial device
devicePort :: VendorId -> ProductId -> IO (Either String FilePath)
devicePort vid pid = do
ctx <- newCtx
findDevice ctx vid pid >>= \md -> case md of
Just dev -> fmap (maybe (Left "not a serial device") Right) $ serialPort dev
Nothing -> return $ Left "device not found"
-- | Scan for first device with given vendor and product identifiers
findDevice :: Ctx -> VendorId -> ProductId -> IO (Maybe Device)
findDevice ctx vid pid = fmap (listToMaybe . V.toList) $ V.filterM p =<< getDevices ctx
where p x = do
d <- getDeviceDesc x
return $ deviceVendorId d == vid && deviceProductId d == pid
serialPort :: Device -> IO (Maybe FilePath)
serialPort dev = undefined
What is a possible implementation of the last function?
You need to search for your device in the registry. Under the key HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum
there are multiple keys (in most cases its USB but sometimes the drivers install it in a different subkey) which themselves contain keys in the format VID_xxxx&PID_xxxx
. You have to find this key first. It will be most likely something like HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Enum\USB\VID_xxxx&PID_xxxx
.
This key contains itself new subkeys. And these subkeys contain a key called Device Parameters
which contains the needed key value pair PortName
with the port something like COM3.
Sadly I have no idea how this is done in Haskell.