Removed cgo dependency from windows implementation
This commit is contained in:
@@ -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
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -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 {
|
||||||
|
|||||||
Reference in New Issue
Block a user