Removed cgo dependency from windows implementation

This commit is contained in:
Cristian Maglie
2014-12-31 00:27:28 +01:00
parent 3415c57d6a
commit 9e85415532
2 changed files with 36 additions and 58 deletions

View File

@@ -14,77 +14,45 @@ package serial // import "go.bug.st/serial"
// Arduino Playground article on serial communication with Windows API: // Arduino Playground article on serial communication with Windows API:
// http://playground.arduino.cc/Interfacing/CPPWindows // http://playground.arduino.cc/Interfacing/CPPWindows
#include <stdlib.h>
#include <windows.h>
//HANDLE invalid = INVALID_HANDLE_VALUE;
HKEY INVALID_PORT_LIST = 0;
HKEY openPortList() {
HKEY handle;
LPCSTR lpSubKey = "HARDWARE\\DEVICEMAP\\SERIALCOMM\\";
DWORD res = RegOpenKeyExA(HKEY_LOCAL_MACHINE, lpSubKey, 0, KEY_READ, &handle);
if (res != ERROR_SUCCESS)
return INVALID_PORT_LIST;
else
return handle;
}
int countPortList(HKEY handle) {
int count = 0;
for (;;) {
char name[256];
DWORD nameSize = 256;
DWORD res = RegEnumValueA(handle, count, name, &nameSize, NULL, NULL, NULL, NULL);
if (res != ERROR_SUCCESS)
return count;
count++;
}
}
char *getInPortList(HKEY handle, int i) {
byte *data = (byte *) malloc(256);
DWORD dataSize = 256;
char name[256];
DWORD nameSize = 256;
DWORD res = RegEnumValueA(handle, i, name, &nameSize, NULL, NULL, data, &dataSize);
if (res != ERROR_SUCCESS) {
free(data);
return NULL;
}
return data;
}
void closePortList(HKEY handle) {
CloseHandle(handle);
}
*/ */
import "C"
import "syscall" import "syscall"
import "unsafe"
// opaque type that implements SerialPort interface for Windows // opaque type that implements SerialPort interface for Windows
type windowsSerialPort struct { type windowsSerialPort struct {
Handle syscall.Handle Handle syscall.Handle
} }
//sys RegEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) = advapi32.RegEnumValueW
func GetPortsList() ([]string, error) { func GetPortsList() ([]string, error) {
portList := C.openPortList() subKey, err := syscall.UTF16PtrFromString("HARDWARE\\DEVICEMAP\\SERIALCOMM\\")
if portList == C.INVALID_PORT_LIST { if err != nil {
return nil, &SerialPortError{code: ERROR_ENUMERATING_PORTS} return nil, &SerialPortError{code: ERROR_ENUMERATING_PORTS}
} }
n := C.countPortList(portList)
list := make([]string, n) var h syscall.Handle
for i := range list { if syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, subKey, 0, syscall.KEY_READ, &h) != nil {
portName := C.getInPortList(portList, C.int(i)) return nil, &SerialPortError{code: ERROR_ENUMERATING_PORTS}
list[i] = C.GoString(portName) }
C.free(unsafe.Pointer(portName)) defer syscall.RegCloseKey(h)
var valuesCount uint32
if syscall.RegQueryInfoKey(h, nil, nil, nil, nil, nil, nil, &valuesCount, nil, nil, nil, nil) != nil {
return nil, &SerialPortError{code: ERROR_ENUMERATING_PORTS}
} }
C.closePortList(portList) list := make([]string, valuesCount)
for i := range list {
var data [1024]uint16
dataSize := uint32(len(data))
var name [1024]uint16
nameSize := uint32(len(name))
if RegEnumValue(h, uint32(i), &name[0], &nameSize, nil, nil, &data[0], &dataSize) != nil {
return nil, &SerialPortError{code: ERROR_ENUMERATING_PORTS}
}
list[i] = syscall.UTF16ToString(data[:])
}
return list, nil return list, nil
} }

View File

@@ -1,4 +1,4 @@
// go build mksyscall_windows.go && ./mksyscall_windows native_windows.go // go build mksyscall_windows.go && ./mksyscall_windows serial_windows.go
// MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT // MACHINE GENERATED BY THE COMMAND ABOVE; DO NOT EDIT
package serial package serial
@@ -7,13 +7,23 @@ import "unsafe"
import "syscall" import "syscall"
var ( var (
modadvapi32 = syscall.NewLazyDLL("advapi32.dll")
modkernel32 = syscall.NewLazyDLL("kernel32.dll") modkernel32 = syscall.NewLazyDLL("kernel32.dll")
procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW")
procGetCommState = modkernel32.NewProc("GetCommState") procGetCommState = modkernel32.NewProc("GetCommState")
procSetCommState = modkernel32.NewProc("SetCommState") procSetCommState = modkernel32.NewProc("SetCommState")
procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts") procSetCommTimeouts = modkernel32.NewProc("SetCommTimeouts")
) )
func RegEnumValue(key syscall.Handle, index uint32, name *uint16, nameLen *uint32, reserved *uint32, class *uint16, value *uint16, valueLen *uint32) (regerrno error) {
r0, _, _ := syscall.Syscall9(procRegEnumValueW.Addr(), 8, uintptr(key), uintptr(index), uintptr(unsafe.Pointer(name)), uintptr(unsafe.Pointer(nameLen)), uintptr(unsafe.Pointer(reserved)), uintptr(unsafe.Pointer(class)), uintptr(unsafe.Pointer(value)), uintptr(unsafe.Pointer(valueLen)), 0)
if r0 != 0 {
regerrno = syscall.Errno(r0)
}
return
}
func GetCommState(handle syscall.Handle, dcb *DCB) (err error) { func GetCommState(handle syscall.Handle, dcb *DCB) (err error) {
r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0) r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0)
if r1 == 0 { if r1 == 0 {