From 9e8541553244ee04b5b39e9c060b7fa9e5b44e07 Mon Sep 17 00:00:00 2001 From: Cristian Maglie Date: Wed, 31 Dec 2014 00:27:28 +0100 Subject: [PATCH] Removed cgo dependency from windows implementation --- serial_windows.go | 82 ++++++++++++++-------------------------------- syscall_windows.go | 12 ++++++- 2 files changed, 36 insertions(+), 58 deletions(-) diff --git a/serial_windows.go b/serial_windows.go index 2360792..11eebad 100644 --- a/serial_windows.go +++ b/serial_windows.go @@ -14,77 +14,45 @@ package serial // import "go.bug.st/serial" // Arduino Playground article on serial communication with Windows API: // http://playground.arduino.cc/Interfacing/CPPWindows -#include -#include - -//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 "unsafe" // opaque type that implements SerialPort interface for Windows type windowsSerialPort struct { 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) { - portList := C.openPortList() - if portList == C.INVALID_PORT_LIST { + subKey, err := syscall.UTF16PtrFromString("HARDWARE\\DEVICEMAP\\SERIALCOMM\\") + if err != nil { return nil, &SerialPortError{code: ERROR_ENUMERATING_PORTS} } - n := C.countPortList(portList) - list := make([]string, n) - for i := range list { - portName := C.getInPortList(portList, C.int(i)) - list[i] = C.GoString(portName) - C.free(unsafe.Pointer(portName)) + var h syscall.Handle + if syscall.RegOpenKeyEx(syscall.HKEY_LOCAL_MACHINE, subKey, 0, syscall.KEY_READ, &h) != nil { + return nil, &SerialPortError{code: ERROR_ENUMERATING_PORTS} + } + 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 } diff --git a/syscall_windows.go b/syscall_windows.go index c0065c2..f868cb8 100644 --- a/syscall_windows.go +++ b/syscall_windows.go @@ -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 package serial @@ -7,13 +7,23 @@ import "unsafe" import "syscall" var ( + modadvapi32 = syscall.NewLazyDLL("advapi32.dll") modkernel32 = syscall.NewLazyDLL("kernel32.dll") + procRegEnumValueW = modadvapi32.NewProc("RegEnumValueW") procGetCommState = modkernel32.NewProc("GetCommState") procSetCommState = modkernel32.NewProc("SetCommState") 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) { r1, _, e1 := syscall.Syscall(procGetCommState.Addr(), 2, uintptr(handle), uintptr(unsafe.Pointer(dcb)), 0) if r1 == 0 {