Skip to content

Commit

Permalink
settings
Browse files Browse the repository at this point in the history
  • Loading branch information
Jan Klaban committed Feb 2, 2025
1 parent 689b91c commit dd60540
Show file tree
Hide file tree
Showing 2 changed files with 103 additions and 49 deletions.
51 changes: 32 additions & 19 deletions base/serial.go
Original file line number Diff line number Diff line change
@@ -1,29 +1,42 @@
package base

type SerialDataBits int
type SerialParity int
type SerialStopBits int
type SerialFlowControl int

const (
Serial5DataBits = 5
Serial6DataBits = 6
Serial7DataBits = 7
Serial8DataBits = 8
SerialNoParity = 1
SerialOddParity = 2
SerialEvenParity = 3
SerialMarkParity = 4
SerialSpaceParity = 5
SerialOneStopBit = 1
SerialTwoStopBits = 2
SerialOneAndHalfStopBits = 3
SerialNoFlowControl = 1
SerialSWFlowControl = 2
SerialHWFlowControl = 3
SerialDCDFlowControl = 17
SerialDSRFlowControl = 19
Serial5DataBits SerialDataBits = 5
Serial6DataBits SerialDataBits = 6
Serial7DataBits SerialDataBits = 7
Serial8DataBits SerialDataBits = 8
SerialNoParity SerialParity = 1
SerialOddParity SerialParity = 2
SerialEvenParity SerialParity = 3
SerialMarkParity SerialParity = 4
SerialSpaceParity SerialParity = 5
SerialOneStopBit SerialStopBits = 1
SerialTwoStopBits SerialStopBits = 2
SerialOneAndHalfStopBits SerialStopBits = 3
SerialNoFlowControl SerialFlowControl = 1
SerialSWFlowControl SerialFlowControl = 2
SerialHWFlowControl SerialFlowControl = 3
SerialDCDFlowControl SerialFlowControl = 17
SerialDSRFlowControl SerialFlowControl = 19
)

type SerialStreamSettings struct {
BaudRate int
DataBits SerialDataBits
Parity SerialParity
StopBits SerialStopBits
FlowControl SerialFlowControl
}

type SerialStream interface {
Stream

SetSpeed(baudRate int, dataBits int, parity int, stopBits int) error
SetFlowControl(flowControl int) error
SetSpeed(baudRate int, dataBits SerialDataBits, parity SerialParity, stopBits SerialStopBits) error
SetFlowControl(flowControl SerialFlowControl) error
SetDTR(dtr bool) error
}
101 changes: 71 additions & 30 deletions rfc2217/rfc2217.go
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,14 @@ type rfc2217Serial struct {
isopen bool
writebuffer []byte

settings base.SerialStreamSettings

// status variables
baudrate int
databits int
parity int
stopbits int
control int
databits base.SerialDataBits
parity base.SerialParity
stopbits base.SerialStopBits
control base.SerialFlowControl
linestate byte
modemstate byte

Expand Down Expand Up @@ -75,6 +77,13 @@ func (r *rfc2217Serial) Open() error {
return nil
}

if err := sanityControl(r.settings.FlowControl); err != nil {
return err
}
if err := sanitySpeed(r.settings.BaudRate, r.settings.DataBits, r.settings.Parity, r.settings.StopBits); err != nil {
return err
}

if err := r.transport.Open(); err != nil {
return err
}
Expand All @@ -91,14 +100,23 @@ func (r *rfc2217Serial) Open() error {
// also send some artifical signature
r.writebuffer = r.writeSignature(r.writebuffer)

// request current settings (baud rate, control, parity, data bits, stop bits)
cmd := []byte{0, 0, 0, 0}
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 1, cmd[:]) // request baud rate
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 2, cmd[:1]) // data size
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 3, cmd[:1]) // parity
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 4, cmd[:1]) // stop bits
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 5, cmd[:1]) // control
// set desired settings
var cmd [4]byte
binary.BigEndian.PutUint32(cmd[:], uint32(r.settings.BaudRate))
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 1, cmd[:])
cmd[0] = byte(r.settings.DataBits)
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 2, cmd[:1])
cmd[0] = byte(r.settings.Parity)
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 3, cmd[:1])
cmd[0] = byte(r.settings.StopBits)
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 4, cmd[:1])

cmd[0] = byte(r.settings.FlowControl)
r.writebuffer = r.writeSubnegotiation(r.writebuffer[:0], 5, cmd[:1])
if r.settings.FlowControl == base.SerialNoFlowControl { // set RTS to true by force
cmd[0] = 11
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 5, cmd[:1])
}
r.isopen = true
return r.transport.Write(r.writebuffer)
}
Expand Down Expand Up @@ -252,42 +270,42 @@ func (r *rfc2217Serial) processSubnegotiation(sub []byte) error {
if len(sub) != 2 {
return fmt.Errorf("invalid subnegotiation length")
}
switch sub[1] {
switch base.SerialDataBits(sub[1]) {
case base.Serial5DataBits, base.Serial6DataBits, base.Serial7DataBits, base.Serial8DataBits:
default:
return fmt.Errorf("unsupported data bits %02x", sub[1])
}
r.databits = int(sub[1])
r.databits = base.SerialDataBits(sub[1])
r.logf("reported data bits: %d", r.databits)
case 103: // set parity
if len(sub) != 2 {
return fmt.Errorf("invalid subnegotiation length")
}
switch sub[1] {
switch base.SerialParity(sub[1]) {
case base.SerialNoParity, base.SerialOddParity, base.SerialEvenParity, base.SerialMarkParity, base.SerialSpaceParity:
default:
return fmt.Errorf("unsupported parity %02x", sub[1])
}
r.parity = int(sub[1])
r.parity = base.SerialParity(sub[1])
r.logf("reported parity: %d", r.parity)
case 104: // set stop bits
if len(sub) != 2 {
return fmt.Errorf("invalid subnegotiation length")
}
switch sub[1] {
switch base.SerialStopBits(sub[1]) {
case base.SerialOneStopBit, base.SerialTwoStopBits, base.SerialOneAndHalfStopBits:
default:
return fmt.Errorf("unsupported stop bits %02x", sub[1])
}
r.stopbits = int(sub[1])
r.stopbits = base.SerialStopBits(sub[1])
r.logf("reported stop bits: %d", r.stopbits)
case 105: // set control
if len(sub) != 2 {
return fmt.Errorf("invalid subnegotiation length")
}
switch sub[1] {
switch base.SerialFlowControl(sub[1]) {
case base.SerialNoFlowControl, base.SerialSWFlowControl, base.SerialHWFlowControl, base.SerialDCDFlowControl, base.SerialDSRFlowControl:
r.control = int(sub[1])
r.control = base.SerialFlowControl(sub[1])
r.logf("reported control: %d", r.control)
default:
r.logf("unsupported control %02x", sub[1])
Expand Down Expand Up @@ -395,31 +413,34 @@ func (r *rfc2217Serial) SetDTR(dtr bool) error {
}

// SetFlowControl implements SerialStream.
func (r *rfc2217Serial) SetFlowControl(flowControl int) error {
func (r *rfc2217Serial) SetFlowControl(flowControl base.SerialFlowControl) error {
if !r.isopen {
return base.ErrNotOpened
}

switch flowControl {
case base.SerialNoFlowControl, base.SerialSWFlowControl, base.SerialHWFlowControl, base.SerialDCDFlowControl, base.SerialDSRFlowControl:
default:
return fmt.Errorf("unsupported flow control %d", flowControl)
if err := sanityControl(flowControl); err != nil {
return err
}

r.settings.FlowControl = flowControl

r.writebuffer = r.writeSubnegotiation(r.writebuffer[:0], 5, []byte{byte(flowControl)})
if flowControl == base.SerialNoFlowControl { // set RTS to true by force
r.writebuffer = r.writeSubnegotiation(r.writebuffer, 5, []byte{11})
}
return r.transport.Write(r.writebuffer)
}

// SetSpeed implements SerialStream.
func (r *rfc2217Serial) SetSpeed(baudRate int, dataBits int, parity int, stopBits int) error {
var cmd [4]byte
if !r.isopen {
return base.ErrNotOpened
func sanityControl(flowControl base.SerialFlowControl) error {
switch flowControl {
case base.SerialNoFlowControl, base.SerialSWFlowControl, base.SerialHWFlowControl, base.SerialDCDFlowControl, base.SerialDSRFlowControl:
default:
return fmt.Errorf("unsupported flow control %d", flowControl)
}
return nil
}

func sanitySpeed(baudRate int, dataBits base.SerialDataBits, parity base.SerialParity, stopBits base.SerialStopBits) error {
switch baudRate {
case 300, 600, 1200, 2400, 4800, 9600, 19200, 38400, 57600, 115200, 128000, 256000:
default:
Expand All @@ -441,6 +462,25 @@ func (r *rfc2217Serial) SetSpeed(baudRate int, dataBits int, parity int, stopBit
return fmt.Errorf("unsupported stop bits %d", stopBits)
}

return nil
}

// SetSpeed implements SerialStream.
func (r *rfc2217Serial) SetSpeed(baudRate int, dataBits base.SerialDataBits, parity base.SerialParity, stopBits base.SerialStopBits) error {
var cmd [4]byte
if !r.isopen {
return base.ErrNotOpened
}

if err := sanitySpeed(baudRate, dataBits, parity, stopBits); err != nil {
return err
}

r.settings.BaudRate = baudRate
r.settings.DataBits = dataBits
r.settings.Parity = parity
r.settings.StopBits = stopBits

binary.BigEndian.PutUint32(cmd[:], uint32(baudRate))
r.writebuffer = r.writeSubnegotiation(r.writebuffer[:0], 1, cmd[:])
cmd[0] = byte(dataBits)
Expand Down Expand Up @@ -477,8 +517,9 @@ func (r *rfc2217Serial) Write(src []byte) error {
return r.transport.Write(r.writebuffer)
}

func NewRfc2217Serial(t base.Stream) base.SerialStream {
func NewRfc2217Serial(settings base.SerialStreamSettings, t base.Stream) base.SerialStream {
ret := &rfc2217Serial{
settings: settings,
transport: t,
isopen: false,
writebuffer: make([]byte, 0, 1024),
Expand Down

0 comments on commit dd60540

Please sign in to comment.