node-serialport icon indicating copy to clipboard operation
node-serialport copied to clipboard

Set RTS and Clear DTR does not work on Linux

Open iKK001 opened this issue 1 year ago • 1 comments

SerialPort Version

10.5.0

Node Version

18

Electron Version

No response

Platform

Linux or Mac

Architecture

x64

Hardware or chipset of serialport

FTDI

What steps will reproduce the bug?

These are the Serialport Config:

const config: Config = {
    BAUD_RATE: 115200,
    DATA_BITS: 8,
    STOP_BITS: 1,
    PARITY: "none",
    RTSCTS: false, // default false
    XON: false, // default false
    XOFF: false, // default false
    XANY: false, // default false
    HUPCL: true, // default true
}

And these are my SerialPort SetOptions:

port.set(
    {
        brk: false,
        cts: false,
        dsr: false,
        dtr: false,
        rts: true,      // <--- note: this one is set to true
    },
    function (err) {
        if (err) {
            console.log("Set Error: ", err.message)
        }
        console.log("Set Done")
    },
)

We have a working 3rd-party Controller that works on Windows and Mac.

Now we would like to make it run using node-18 and node-serialport running it on Linux.

We know that the 3rd-party Controller will only work if RTS is set and DTR is cleared (but both modem-lignes are needed !!).

What happens?

I get no answer from the 3rd-party Controller whatsoever.

The following readData() is null (but should deliver a response other than null):

port.flush()
port.write(`info\n`)    // <-- this is a test command for the 3rd-party Controller that normally delivers an answer
port.drain((error) => {
    if (error) {
        console.log(`error = ${error}`)
    } else {
        console.log(
            `no drain error - readData = ${port.read()}`,  // <-- unfortunately, this is always NULL (but should be an answer)
        )
    }
})

What should have happened?

The following Delphi code works on Mac (see below)

How do I have to set Serialport settings in order to achieve the very same goal ?

As you can see below, our 3rd-party Controller needs

LE = false DTR = false RTS = true CTS = false CAR = false RNG = false DSR = false

How do I achieve the same with the node-serialport ????

fXComPort.SetModemCtrl(false, false, true, false, false, false, false,StatusIn, StatusOut);

And here the Delphi-Procedure that works under Mac:

Can you tell me how to achieve the same on node-serial ?

procedure TXComPort.SetModemCtrl(LE, DTR, RTS, CTS, CAR, RNG, DSR: boolean;
  var StatusIn, StatusOut: integer);
{$IFDEF MACOS}
const
  TIOCMGET = integer(IOC_OUT or ((SizeOf(integer) and IOCPARM_MASK) shl 16)
    or (Ord('t') shl 8) or 106);  { _IOR('t', 106, int) }
  TIOCMSET = integer(IOC_IN or ((SizeOf(integer) and IOCPARM_MASK) shl 16)
    or (Ord('t') shl 8) or 109);   { _IOW('t', 109, int) }
  TIOCEXCL = IOC_VOID or ((0 and IOCPARM_MASK) shl 16)
    or (Ord('t') shl 8) or 13;  { _IO('t', 13) }
  TIOCM_LE  = $0001; // line enable
  TIOCM_DTR = $0002; // data terminal ready
  TIOCM_RTS = $0004; // request to send
  TIOCM_CTS = $0040; // clear to send
  TIOCM_CAR = $0100; // carrier detected
  TIOCM_RNG = $0200; // ring
  TIOCM_DSR = $0400; // data set ready
{$ENDIF}
begin
{$IFDEF MACOS}
  CheckActive;
  StatusIn := $FFFF;
  Check(ioctl(FHandle, TIOCMGET, @StatusIn) = 0);
  StatusOut := StatusIn;
  if LE then
    StatusOut := StatusOut or TIOCM_LE
  else
    StatusOut := StatusOut and not TIOCM_LE;
  if DTR then
    StatusOut := StatusOut or TIOCM_DTR
  else
    StatusOut := StatusOut and not TIOCM_DTR;
  if RTS then
    StatusOut := StatusOut or TIOCM_RTS
  else
    StatusOut := StatusOut and not TIOCM_RTS;
  if CTS then
    StatusOut := StatusOut or TIOCM_CTS
  else
    StatusOut := StatusOut and not TIOCM_CTS;
  if CAR then
    StatusOut := StatusOut or TIOCM_CAR
  else
    StatusOut := StatusOut and not TIOCM_CAR;
  if RNG then
    StatusOut := StatusOut or TIOCM_RNG
  else
    StatusOut := StatusOut and not TIOCM_RNG;
  if DSR then
    StatusOut := StatusOut or TIOCM_DSR
  else
    StatusOut := StatusOut and not TIOCM_DSR;
  Check(ioctl(FHandle, TIOCMSET, @StatusOut) = 0);
{$ENDIF}
end;

Additional information

No response

iKK001 avatar Jun 01 '23 16:06 iKK001

You should be able to achieve this with node-serialport across Win, Linux and Mac with the same javascript code for all 3 platforms.

I'm using a device that uses DTR to trigger a firmware update mode. In my case, while normal operations with the device operate at a high board rate, in order for the DTR to have an effect I need to drop the baud rate.

I've tweaked a version of electron-serialport @ https://github.com/GazHank/electron-serialport/tree/test2299 which exposes some of this functionality as a means to debug or play with the module. You can see the logic in the renderer.js... from listing, opening, settingDTS etc, and it also includes my "resetDevice()" function per above. Hopefully this might help you get started and see how the module works for you on both Linux and other platforms

GazHank avatar Jun 06 '23 17:06 GazHank