Node-serialport: Track NodeJS native serial port suport

Created on 17 Jul 2015  路  17Comments  路  Source: serialport/node-serialport

During the hardware working group meetup at Cascadia we were asked to document ioclt or other calls used on all platforms to make sure we're able to target all the features we need for exiting functionality.

never-stale

Most helpful comment

One thing that would be nice to see is a libuv level API proposal. If this is going to "inherit" from uv_stream_t we might need to make internal adjustments. It's important we catch those as early as possible.

All 17 comments

Linux/OSX
normal ioctl setup, and custom baud on linux

  serinfo.flags &= ~ASYNC_SPD_MASK;
  serinfo.flags |= ASYNC_SPD_CUST;
  ioctl(fd, TIOCSSERIAL, &serinfo);
  ioctl(fd, TIOCGSERIAL, &serinfo);

osx we use a different ioctl call to do custom baud
if (ioctl(fd, IOSSIOSPEED, &speed) == -1) {

Then we set control and break codes with
TIOCMSET TIOCM_RTS | TIOCM_CTS | TIOCM_DTR | TIOCM_DSR
TIOCSBRK
TIOCCBRK

Tagging @nebrius and linking to https://github.com/libuv/libuv/pull/379

@jacobrosenthal @dtex @nebrius This seems like the issue where we're tracking built in serialport support to libuv. I was about to close this but it seems.. pertinent. Anyone know how that's going?

I had a long discussion with @jessicaquynh and @TheAlphaNerd about moving this forward.

As of today this is what the bindings interface looks like. Full Documentation

  • list returns a list of objects describing available serialports
  • open takes a path and options, opens a file handle, and configures the port's baudRate, parity, stopbits, locking, and flow control.
  • close closes the file handle
  • read mimics fs.read but is guaranteed to read at least one byte (abstracting away uv_poll/epoll/I/O Completion Ports)
  • write mimics fs.writeFile
  • set/get sets and gets flow control flags and break status (probably conflated)
  • flush/drain flushes and drains the port at the os level.
  • update updates the buadrate of an open port (maybe more options in the future, not well defined yet)

This are the nodejs interfaces I wish I had that would allow me to not use any c/c++

  • fs.poll a callback interface to let me know the port is readable, writable, or disconnected
  • fs.read that worked for serialports on windows. I have a file handle but I get access denied
  • fs.writeFile that worked for serialports on all platforms. I haven't yet debugged what's going on but it doesn't work so we implemented something similar.
  • fs.flush to call tcflush or PurgeComm
  • fs.drain to call tcdrain or FlushFileBuffers
  • fs.setBaudRate Setting baudrates cross platform for custom and preset baud rates. 250k baud is currently not supported in node serialport because it's hard. There are a finite set of tricks for linux, osx and windows to make this work right and serialport hasn't yet figured them all out yet.
  • fs.setFlowControl / fs.getFlowControl to set and get flow control flags
  • fs.getBreak / fs.clearBreak to set and clear break status.

Here are the c functions I use that could have JS equivalents. We could build some of the above with these functions.

  • ioctl / SetCommState
  • tcsetattr / tcgetattr
  • EscapeCommFunction / GetCommModemStatus
  • flock

@saghul what are your thoughts on the above? Would you have time in the next week to break ground on libuv extras?

what are your thoughts on the above?

Looks good! One comment I have to make is that IMHO nothing serialport related belongs in the fs module. Yes, everything is a file descriptor in Unix, but conceptually a serial port is not a file :-)

Would you have time in the next week to break ground on libuv extras?

I'll try to get the basic building blocks + build system ready.

In case it helps, this can also serve as API inspiration: http://doc.qt.io/qt-5/qserialport.html Alas we can't borrow any code from Qt because it's GPL.

One thing that would be nice to see is a libuv level API proposal. If this is going to "inherit" from uv_stream_t we might need to make internal adjustments. It's important we catch those as early as possible.

I'll have to study qt serialport. Python's serialport is another good reference, I've used it for ioctl tricks on different platforms more than a few times.

We're not currently using uv_stream_t directly. We do have a write queue that was implemented early on but I'm hoping to move away from it. For reads uv_stream_t does select on osx, overlapped reads on windows and .. I'm not sure on linux. For writes I'm less sure what's going on. But it looks like windows leverages iocp (or.. emulates it?) which is a lot more than we do.

I don't understand what a serialport is cross platform to libuv. On unix it's not a file or a domain socket, but under the hood fs.read is probably using uv_stream_t and that works great. On windows is it a named pipe? I know fs.read doesn't work there.

I imagine a uv_serial_t would handle the reading and writing to an open serial connection. Would it include opening the file handles and the configuration primitives too?

For reads uv_stream_t does select on osx

Incorrect. That's only the case if the fd doesn't work with kqueue.

I don't understand what a serialport is cross platform to libuv.

I consider it an abstract entity. On Unix it's file descriptor, yeah, but that's it's an implementation detail. AFAIS it behaves like a stream so it should probably be one, and inherit the heavy lifting already inplace.

On unix it's not a file or a domain socket, but under the hood fs.read is probably using uv_stream_t and that works great.

No, it's not. Streams queue writes, while the fs operations run in parallel and use offsets.

I imagine a uv_serial_t would handle the reading and writing to an open serial connection. Would it include opening the file handles and the configuration primitives too?

I'd say yes. The whole idea behind putting this in the libuv layer is that the Node native module would just be a wrapper of the C part, plus handling of data types.

I love it. What should a proposal look like?

Since the plan is to put this in libuv-extras, I'd say something like http://docs.libuv.org/en/v1.x/tty.html would be a good start. That is: public API and datatypes.

The implementation can start as a C file (plus the header) while I figure out the best way to deal with libuv-extras as a companion library depending on libuv.

ping @reconbot you have a chance to look at this yet?

also @saghul can you build more on how serialport is not a file. Are you speaking in comparison to what you use the fs module for or unix files?

What would you define it as?

A device?

I have but it's a lot of work =p

Here's my start https://github.com/reconbot/libuv/blob/uv_serial_t/docs/src/serial.rst we can crib most of the QSerialPort class, but it's got a few legacy things I'll probably drop unless there's a compelling reason. I also need to square terminology with what we currently provide.

/sub, I'm building a project that I'd like to be able to package cross-platform (in particular, on raspberry pi) and node-serialport's native module is a big impediment to packaging with pkg. I'd love to see this be possible with pure JS. anything I can do to help?

There isn't anything possible at this time. We're eventually going to support N-API but will probably always be a binary module.

Was this page helpful?
0 / 5 - 0 ratings

Related issues

belargo picture belargo  路  4Comments

Fuzzzzel picture Fuzzzzel  路  6Comments

jdshin123 picture jdshin123  路  3Comments

vkuehn picture vkuehn  路  6Comments

pghalliday picture pghalliday  路  4Comments