const { promisify } = require('util') const binding = require('bindings')('bindings.node') const AbstractBinding = require('@serialport/binding-abstract') const linuxList = require('./linux-list') const Poller = require('./poller') const unixRead = require('./unix-read') const unixWrite = require('./unix-write') const { wrapWithHiddenComName } = require('./legacy') const defaultBindingOptions = Object.freeze({ vmin: 1, vtime: 0, }) const asyncOpen = promisify(binding.open) const asyncClose = promisify(binding.close) const asyncUpdate = promisify(binding.update) const asyncSet = promisify(binding.set) const asyncGet = promisify(binding.get) const asyncGetBaudRate = promisify(binding.getBaudRate) const asyncDrain = promisify(binding.drain) const asyncFlush = promisify(binding.flush) /** * The linux binding layer */ class LinuxBinding extends AbstractBinding { static list() { return wrapWithHiddenComName(linuxList()) } constructor(opt = {}) { super(opt) this.bindingOptions = { ...defaultBindingOptions, ...opt.bindingOptions } this.fd = null this.writeOperation = null } get isOpen() { return this.fd !== null } async open(path, options) { await super.open(path, options) this.openOptions = { ...this.bindingOptions, ...options } const fd = await asyncOpen(path, this.openOptions) this.fd = fd this.poller = new Poller(fd) } async close() { await super.close() const fd = this.fd this.poller.stop() this.poller.destroy() this.poller = null this.openOptions = null this.fd = null return asyncClose(fd) } async read(buffer, offset, length) { await super.read(buffer, offset, length) return unixRead({ binding: this, buffer, offset, length }) } async write(buffer) { this.writeOperation = super.write(buffer).then(async () => { if (buffer.length === 0) { return } await unixWrite({ binding: this, buffer }) this.writeOperation = null }) return this.writeOperation } async update(options) { await super.update(options) return asyncUpdate(this.fd, options) } async set(options) { await super.set(options) return asyncSet(this.fd, options) } async get() { await super.get() return asyncGet(this.fd) } async getBaudRate() { await super.get() return asyncGetBaudRate(this.fd) } async drain() { await super.drain() await this.writeOperation return asyncDrain(this.fd) } async flush() { await super.flush() return asyncFlush(this.fd) } } module.exports = LinuxBinding