Serial Communications in Haskell

I'm on a Windows box and I'm looking for a way to talk to a serial port (for example, RS-232) from Haskell. I couldn't find a library to do this, so I am wondering how to create one. I have a fairly thorough understanding of how to open and use a serial port with the Windows API. In particular, to open a serial port, I have to use CreateFile, which is the same API call that opens files. In fact, if I call openFile from GHC, and pass "COM1:" as the filename, then I can get a writable serial port.
module Serial where import System.IO
main = do h <- openFile "COM1:" ReadWriteMode hPutStrLn h "Hello World"
I can't read from the port (I always get an immediate EOF), and I have no way of configuring things like the baud rate or the parity settings. Nevertheless, this demonstrates that openFile can at least open the serial port. What I would like to do is create some functions that would allow me to open and configure a serial port, and get a Handle back so that I can use the existing IO functions like hGetChar and hPutChar. I am assuming that hGetChar eventually calls win32::ReadFile and hPutChar eventually calls win32::WriteFile. These same two API calls would work for serial ports. In Windows, there are 23 API functions that apply specifically to serial ports. Out of these 23 functions, only a few of them are actually necessary if I just want to send and receive data. Of course, I don't know how to call Windows API functions from Haskell, and I have no idea how to hook things to the IO library so that I can use a Handle for a serial port. I'm looking for some advice on how to proceed. -- Ron

Hi!
Of course, I don't know how to call Windows API functions from Haskell, and I have no idea how to hook things to the IO library so that I can use a Handle for a serial port. I'm looking for some advice on how to proceed.
You can check how I did this in my Lego Mindstorms NXT interface, pre-beta version: http://www.forzanka.si/files/NXT.tgz It is for UNIX (POSIX?) systems but I had similar problems so I had to use FFI (foreign function interface) to setup a link. You will probably just have to replace that with Windows API calls. I hope. Mitar

mmitar:
Hi!
Of course, I don't know how to call Windows API functions from Haskell, and I have no idea how to hook things to the IO library so that I can use a Handle for a serial port. I'm looking for some advice on how to proceed.
You can check how I did this in my Lego Mindstorms NXT interface, pre-beta version:
http://www.forzanka.si/files/NXT.tgz
It is for UNIX (POSIX?) systems but I had similar problems so I had to use FFI (foreign function interface) to setup a link. You will probably just have to replace that with Windows API calls. I hope.
That's really cool! I hope you can upload this to hackage soon. -- Don

Hi!
You can check how I did this in my Lego Mindstorms NXT interface, pre-beta version:
That's really cool! I hope you can upload this to hackage soon.
I do not think it is ready yet. It is working but it is missing extensive testing (making some bigger programs in practice, to see how it behaves and to see if the API is sane) and of course documentation (how to use it, examples, tutorials ...). I will continue with this project in a few months. (The main reason is that I do not have any experience with Hackage and Cabal nor I have time now for this. But if anybody wants to help ...) I am using it in my AI robot research project where I am using Lego Mindstorms NXT unit and communicating with it over Bluetooth. And the AI is made in Haskell. :-) Mitar

On 8/29/07, Ronald Guida
I'm on a Windows box and I'm looking for a way to talk to a serial port (for example, RS-232) from Haskell. I couldn't find a library to do this, so I am wondering how to create one.
I have a fairly thorough understanding of how to open and use a serial port with the Windows API. In particular, to open a serial port, I
At the moment, I think it is easier to just use the same Windows API directly, rather than try to bend GHC's IO system to do it "right".
have to use CreateFile, which is the same API call that opens files. In fact, if I call openFile from GHC, and pass "COM1:" as the filename, then I can get a writable serial port.
module Serial where import System.IO
main = do h <- openFile "COM1:" ReadWriteMode hPutStrLn h "Hello World"
I can't read from the port (I always get an immediate EOF), and I have no way of configuring things like the baud rate or the parity settings. Nevertheless, this demonstrates that openFile can at least open the serial port.
What I would like to do is create some functions that would allow me to open and configure a serial port, and get a Handle back so that I can use the existing IO functions like hGetChar and hPutChar. I am assuming that hGetChar eventually calls win32::ReadFile and hPutChar eventually calls win32::WriteFile. These same two API calls would work for serial ports.
Unfortunately, it goes via extra hoops and uses c runtime instead of Windows API directly. This extra layer makes sure it's hard to predict exactly what gets done (and with what options) sometimes. And even if it did, it'd probably use overlapping io, does that work with COM ports?
In Windows, there are 23 API functions that apply specifically to serial ports. Out of these 23 functions, only a few of them are actually necessary if I just want to send and receive data.
Of course, I don't know how to call Windows API functions from Haskell, and I have no idea how to hook things to the IO library so that I can use a Handle for a serial port. I'm looking for some advice on how to proceed.
I haven't done much work on COM ports, but the little I did, I used bindings in Win32 and probably some of my own, and didn't use System.IO/Handle at all. Maybe problems with GHC's IO system are easy to solve, but I have no idea and wasn't inclined to find out. Best regards, Esa

On 8/29/07, Esa Ilari Vuokko
On 8/29/07, Ronald Guida
wrote: I'm on a Windows box and I'm looking for a way to talk to a serial port (for example, RS-232) from Haskell. I couldn't find a library to do this, so I am wondering how to create one.
I have a fairly thorough understanding of how to open and use a serial port with the Windows API. In particular, to open a serial port, I
At the moment, I think it is easier to just use the same Windows API directly, rather than try to bend GHC's IO system to do it "right".
have to use CreateFile, which is the same API call that opens files. In fact, if I call openFile from GHC, and pass "COM1:" as the filename, then I can get a writable serial port.
module Serial where import System.IO
main = do h <- openFile "COM1:" ReadWriteMode hPutStrLn h "Hello World"
I can't read from the port (I always get an immediate EOF), and I have no way of configuring things like the baud rate or the parity settings. Nevertheless, this demonstrates that openFile can at least open the serial port.
What I would like to do is create some functions that would allow me to open and configure a serial port, and get a Handle back so that I can use the existing IO functions like hGetChar and hPutChar. I am assuming that hGetChar eventually calls win32::ReadFile and hPutChar eventually calls win32::WriteFile. These same two API calls would work for serial ports.
Unfortunately, it goes via extra hoops and uses c runtime instead of Windows API directly. This extra layer makes sure it's hard to predict exactly what gets done (and with what options) sometimes.
And even if it did, it'd probably use overlapping io, does that work with COM ports?
In Windows, there are 23 API functions that apply specifically to serial ports. Out of these 23 functions, only a few of them are actually necessary if I just want to send and receive data.
Of course, I don't know how to call Windows API functions from Haskell, and I have no idea how to hook things to the IO library so that I can use a Handle for a serial port. I'm looking for some advice on how to proceed.
I haven't done much work on COM ports, but the little I did, I used bindings in Win32 and probably some of my own, and didn't use System.IO/Handle at all. Maybe problems with GHC's IO system are easy to solve, but I have no idea and wasn't inclined to find out.
Best regards, Esa _______________________________________________ Haskell-Cafe mailing list Haskell-Cafe@haskell.org http://www.haskell.org/mailman/listinfo/haskell-cafe
Ideally, we would have something like pyserial ( http://pyserial.sourceforge.net ) for Haskell. It provides a nice portable abstraction over serial communication. See for example the windows binding: http://pyserial.cvs.sourceforge.net/pyserial/pyserial/serial/serialwin32.py?... regards, Bas van Dijk

On 8/28/07, Ronald Guida wrote:
I'm on a Windows box and I'm looking for a way to talk to a serial port (for example, RS-232) from Haskell. I couldn't find a library to do this, so I am wondering how to create one.
I figured out FFI and marshaling, and I got my serial port to work in Haskell. See http://ronguida.home.mindspring.com/ for a simple demonstration. To test this program, I connected my COM1 and COM2 ports with a null-modem cable and I used Hyperterminal to talk to COM2. The demo only does a few things: open a serial port, configure it, write to it, and read from it. I have some questions regarding this demonstration: 1. In the DCB and COMMTIMEOUTS datatypes and their marshaling code, is it better to convert Win32 datatypes to Haskell equivalents (e.g. DWORD to Int), like I did with DCB, or is it better to leave things in machine types like I did with COMMTIMEOUTS (e.g. DWORD to Word32) ? 2. Can anyone tell me whether I am making proper use of unsafeInterleaveIO in my implementation of getContentsSerialPort? I am interested in creating a library for serial ports under Win32, and I'm wondering, how should I proceed? -- Ron
participants (5)
-
Bas van Dijk
-
dons@cse.unsw.edu.au
-
Esa Ilari Vuokko
-
Mitar
-
Ronald Guida