Merge pull request #200 from cmaglie/CH340_hack
Hack to workaround misbehaving CH340 drivers on Windows
This commit is contained in:
@@ -30,6 +30,7 @@ import (
|
||||
type windowsPort struct {
|
||||
mu sync.Mutex
|
||||
handle windows.Handle
|
||||
hasTimeout bool
|
||||
}
|
||||
|
||||
func nativeGetPortsList() ([]string, error) {
|
||||
@@ -72,6 +73,7 @@ func (port *windowsPort) Read(p []byte) (int, error) {
|
||||
}
|
||||
defer windows.CloseHandle(ev.HEvent)
|
||||
|
||||
for {
|
||||
err = windows.ReadFile(port.handle, p, &readed, ev)
|
||||
if err == windows.ERROR_IO_PENDING {
|
||||
err = windows.GetOverlappedResult(port.handle, ev, &readed, true)
|
||||
@@ -91,8 +93,14 @@ func (port *windowsPort) Read(p []byte) (int, error) {
|
||||
}
|
||||
|
||||
// Timeout
|
||||
port.mu.Lock()
|
||||
hasTimeout := port.hasTimeout
|
||||
port.mu.Unlock()
|
||||
if hasTimeout {
|
||||
return 0, nil
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
func (port *windowsPort) Write(p []byte) (int, error) {
|
||||
var writed uint32
|
||||
@@ -275,10 +283,19 @@ func (port *windowsPort) GetModemStatusBits() (*ModemStatusBits, error) {
|
||||
}
|
||||
|
||||
func (port *windowsPort) SetReadTimeout(timeout time.Duration) error {
|
||||
// This is a brutal hack to make the CH340 chipset work properly.
|
||||
// Normally this value should be 0xFFFFFFFE but, after a lot of
|
||||
// tinkering, I discovered that any value with the highest
|
||||
// bit set will make the CH340 driver behave like the timeout is 0,
|
||||
// in the best cases leading to a spinning loop...
|
||||
// (could this be a wrong signed vs unsigned conversion in the driver?)
|
||||
// https://github.com/arduino/serial-monitor/issues/112
|
||||
const MaxReadTotalTimeoutConstant = 0x7FFFFFFE
|
||||
|
||||
commTimeouts := &windows.CommTimeouts{
|
||||
ReadIntervalTimeout: 0xFFFFFFFF,
|
||||
ReadTotalTimeoutMultiplier: 0xFFFFFFFF,
|
||||
ReadTotalTimeoutConstant: 0xFFFFFFFE,
|
||||
ReadTotalTimeoutConstant: MaxReadTotalTimeoutConstant,
|
||||
WriteTotalTimeoutConstant: 0,
|
||||
WriteTotalTimeoutMultiplier: 0,
|
||||
}
|
||||
@@ -287,12 +304,20 @@ func (port *windowsPort) SetReadTimeout(timeout time.Duration) error {
|
||||
if ms > 0xFFFFFFFE || ms < 0 {
|
||||
return &PortError{code: InvalidTimeoutValue}
|
||||
}
|
||||
|
||||
if ms > MaxReadTotalTimeoutConstant {
|
||||
ms = MaxReadTotalTimeoutConstant
|
||||
}
|
||||
|
||||
commTimeouts.ReadTotalTimeoutConstant = uint32(ms)
|
||||
}
|
||||
|
||||
port.mu.Lock()
|
||||
defer port.mu.Unlock()
|
||||
if err := windows.SetCommTimeouts(port.handle, commTimeouts); err != nil {
|
||||
return &PortError{code: InvalidTimeoutValue, causedBy: err}
|
||||
}
|
||||
port.hasTimeout = (timeout != NoTimeout)
|
||||
|
||||
return nil
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user