<div dir="ltr"><div><div><div><div><div><div><div>Hello,<br><br>I am building a USB gadget with a HexWax ExpandIO-USB chip, here: <a href="http://hexwax.com/Products/expandIO-USB/" target="_blank">http://hexwax.com/Products/expandIO-USB/</a><br>
<br></div>The device is working fine (lsusb shows it) and so I thought
that in the name of continued training and doing things the hard way,
that I would use Haskell to talk to it!<br>I have only ever done USB with 'C' in the past and I am now stuck fighting the type checker.<br>
<br></div>Here is my full code so far, it works in so far as it finds
the device, opens and closes a connection and prints out some stuff. I
then wanted to send four NUL bytes which elicits the same as a response
according to the documentation but I cannot get it to compile. Apologies
for it in advance, it's the journey you know, not the arrival, anyway,
here it is...<br>
</div><br><span style="font-family:courier new,monospace">module Main where<br><br>import Data.ByteString.Char8 as BS hiding (putStrLn)<br>import Data.Word (Word16)<br>import Data.Vector as V (filterM, null, (!)) --as V hiding ((++)) <br>
import System.USB<br>import System.Environment<br><br><br>-- hexwax expandIO-USB default code: "0b40:0132" <br>main :: IO ()<br>main = do<br> findHexWax (0xb40,0x132) >>= \hw -><br>
case hw of<br> Just dev -> hexwaxGo dev<br> Nothing -> putStrLn "HexWax device not found"<br><br><br>findHexWax :: (Word16,Word16) -> IO (Maybe Device)<br>findHexWax (cVendor, cProd) = do<br>
usbCtx <- newCtx<br> usbDevs <- getDevices usbCtx<br> setDebug usbCtx PrintWarnings<br> boards <- V.filterM (isTarget (cVendor, cProd)) usbDevs<br> case V.null boards of<br> True -> return Nothing<br>
False -> return $ Just $ boards!0<br> where<br> isTarget :: (Word16, Word16) -> Device -> IO Bool<br> isTarget (cVendor, cProd) dev = do<br> info <- getDeviceDesc dev<br> let vid = deviceVendorId info<br>
let vpr = deviceProductId info<br> return $ ((vid, vpr) == (cVendor, cProd))<br><br><br>hexwaxGo :: Device -> IO ()<br>hexwaxGo dev = withDeviceHandle dev (testBoard dev)<br><br><br><br>testBoard :: Device -> DeviceHandle -> IO ()<br>
testBoard dev handle = do<br> putStrLn $ "Inspecting device: \"" ++ (show dev) ++ "\"\n"<br> -- write 0x00 0x00 0x00 0x00, get back same... <br>
let payload = pack "\x00\x00\x00\x00"<br> let endPoint = EndpointAddress 0 Out<br> action <- writeInterrupt handle endPoint<br> (size, status) <- action payload 1000<br> return ()</span><br><br></div>
And the error message:<br><br>Prelude> :r<br>[1 of 1] Compiling Main ( usb1.hs, interpreted )<br><br><font><span style="font-family:courier new,monospace">usb1.hs:60:13:<br> Couldn't match expected type `IO t0' with actual type `WriteAction'<br>
In the return type of a call of `writeInterrupt'<br> Probable cause: `writeInterrupt' is applied to too few arguments<br> In a stmt of a 'do' block: action <- writeInterrupt handle endPoint<br>
In the expression:<br> do { putStrLn $ "Inspecting device: \"" ++ (show dev) ++ "\"";<br> let payload = pack "\NUL\NUL\NUL\NUL";<br> let endPoint = EndpointAddress 0 Out;<br>
action <- writeInterrupt handle endPoint;<br> .... }<br>Failed, modules loaded: none.<br></span></font><br><br><br></div>I
have spent a few hours trying this and that, my Haskell is improving
but not much good if I can't compile my program now is it!<br>
<br>So, can anybody point out the error of my ways here please as I just can't see it!<br><br></div>Thanks,<br>Sean Charles.<br><br></div>PS:
Code style comments, alternative ways of making it more concise (but
still readable and understandable mind you) are also welcome.</div>