diff --git a/serial.h b/serial.h
index f75afd9..0949d8e 100644
--- a/serial.h
+++ b/serial.h
@@ -1,5 +1,9 @@
 #include <windows.h>
 static void NullifyParams(struct _DCB *params) {
+/*	LPCTSTR str = "baud=115200 parity=N data=8 stop=1";
+
+	BuildCommDCB(str,params);
+*/
     params->fBinary       = TRUE;
     params->fNull         = FALSE;
     params->fErrorChar    = FALSE;
diff --git a/serial_posix.go b/serial_posix.go
index 24fc2f6..eb5e5b3 100644
--- a/serial_posix.go
+++ b/serial_posix.go
@@ -6,6 +6,7 @@ import "C"
 
 import (
 	"os"
+	"io"
 	"fmt"
 	"syscall"
 	//"unsafe"
@@ -19,7 +20,7 @@ func (e SError) String() string {
 	return e.msg
 }
 
-func OpenPort(name string, baud int) (f *os.File, err os.Error) {
+func OpenPort(name string, baud int) (f io.ReadWriteCloser, err os.Error) {
 	f, err = os.Open(name, os.O_RDWR|os.O_NOCTTY|os.O_NONBLOCK, 0666)
 	if err != nil {
 		return
diff --git a/serial_windows.go b/serial_windows.go
index 14b34b8..5e6e0ca 100644
--- a/serial_windows.go
+++ b/serial_windows.go
@@ -1,15 +1,21 @@
 package serial
 
 // #include <windows.h>
-// #include "serial.h"
 import "C"
 import (
 	"os"
+	"io"
 	"fmt"
 	"unsafe"
 )
 
-func OpenPort(name string, baud int) (*os.File, os.Error) {
+type serialPort struct {
+	f *os.File
+}
+
+const EV_RXCHAR = 0x0001
+
+func OpenPort(name string, baud int) (io.ReadWriteCloser, os.Error) {
 	f, err := os.Open(name, os.O_RDWR|os.O_NDELAY, 0666)
 	if err != nil {
 		return nil, err
@@ -21,18 +27,16 @@ func OpenPort(name string, baud int) (*os.File, os.Error) {
 	handle = hp(unsafe.Pointer(&fd))
 	var params C.struct__DCB
 	params.DCBlength = C.DWORD(unsafe.Sizeof(params))
-	/*if ok, err := C.GetCommState(*handle, &params); ok == C.FALSE {
-		f.Close()
-		return nil, err
-	}
-	*/
+	
+	params.XonLim = 0
+	params.XoffLim = 0
+	
 	params.BaudRate      = C.DWORD(baud)
 	params.ByteSize      = 8
 	params.StopBits      = C.ONESTOPBIT
-	params.Parity        = C.NOPARITY
-	C.NullifyParams(&params)
+	params.Parity        = C.NOPARITY
 
-	fmt.Println(params)
+	//fmt.Printf("%#v %v\n", params, params)
 
 	if ok, err := C.SetCommState(*handle, &params); ok == C.FALSE {
 		f.Close()
@@ -46,12 +50,56 @@ func OpenPort(name string, baud int) (*os.File, os.Error) {
 	}
 	
 	var timeouts C.struct__COMMTIMEOUTS
-	timeouts.ReadIntervalTimeout = 1
+	const DWORDMAX = 1<<32 - 1
+	timeouts.ReadIntervalTimeout = DWORDMAX
+	timeouts.ReadTotalTimeoutConstant = 0
 	if ok, err := C.SetCommTimeouts(*handle, &timeouts); ok == C.FALSE {
 		f.Close()
 		return nil, err
 	}
-	fmt.Println(timeouts)
+	//fmt.Printf("%#v\n", timeouts)
+
+	if ok, err := C.SetCommMask(*handle, EV_RXCHAR); ok == C.FALSE {
+		f.Close()
+		return nil, err
+	}
+
+	port := serialPort{f}
+
+	return &port, nil
+}
+
+func (p *serialPort) Close() os.Error {
+	return p.f.Close()
+}
+
+func (p *serialPort) Write(buf []byte) (int, os.Error) {
+	return p.f.Write(buf)
+}
+
+func (p *serialPort) Read(buf []byte) (int, os.Error) {
+	type hp *C.HANDLE
+	var handle *C.HANDLE
+	fd := p.f.Fd()
+	handle = hp(unsafe.Pointer(&fd))
+
+	var events C.DWORD
+	var overlapped *C.struct__OVERLAPPED
+
+loop:
+	if ok, err := C.WaitCommEvent(*handle, &events, overlapped); ok == C.FALSE {
+		fmt.Printf("%v, 0x%04x\n", err, events)
+		return 0, err
+	}
+	// There is a small race window here between returning from WaitCommEvent and reading from the file.
+	// If we receive data in this window, we will read that data, but the RXFLAG will still be set
+	// and next time the WaitCommEvent() will return but we will have already read the data.  That's
+	// why we have the stupid goto loop on EOF.
+	n, err := p.f.Read(buf)
+	if err == os.EOF && n == 0 {
+		//fmt.Printf("%v, %v, %v, 0x%04x\n", err, n, len(buf), events)
+		goto loop
+	}
 
-	return f, nil
+	return n, err
 }