58 lines
1.9 KiB
JavaScript
58 lines
1.9 KiB
JavaScript
const fs = require('fs')
|
|
const debug = require('debug')
|
|
const logger = debug('serialport/bindings/unixWrite')
|
|
const { promisify } = require('util')
|
|
|
|
const writeAsync = promisify(fs.write)
|
|
|
|
const writable = binding => {
|
|
return new Promise((resolve, reject) => {
|
|
binding.poller.once('writable', err => (err ? reject(err) : resolve()))
|
|
})
|
|
}
|
|
|
|
const unixWrite = async ({ binding, buffer, offset = 0, fsWriteAsync = writeAsync }) => {
|
|
const bytesToWrite = buffer.length - offset
|
|
logger('Starting write', buffer.length, 'bytes offset', offset, 'bytesToWrite', bytesToWrite)
|
|
if (!binding.isOpen) {
|
|
throw new Error('Port is not open')
|
|
}
|
|
try {
|
|
const { bytesWritten } = await fsWriteAsync(binding.fd, buffer, offset, bytesToWrite)
|
|
logger('write returned: wrote', bytesWritten, 'bytes')
|
|
if (bytesWritten + offset < buffer.length) {
|
|
if (!binding.isOpen) {
|
|
throw new Error('Port is not open')
|
|
}
|
|
return unixWrite({ binding, buffer, offset: bytesWritten + offset, fsWriteAsync })
|
|
}
|
|
|
|
logger('Finished writing', bytesWritten + offset, 'bytes')
|
|
} catch (err) {
|
|
logger('write errored', err)
|
|
if (err.code === 'EAGAIN' || err.code === 'EWOULDBLOCK' || err.code === 'EINTR') {
|
|
if (!binding.isOpen) {
|
|
throw new Error('Port is not open')
|
|
}
|
|
logger('waiting for writable because of code:', err.code)
|
|
await writable(binding)
|
|
return unixWrite({ binding, buffer, offset, fsWriteAsync })
|
|
}
|
|
|
|
const disconnectError =
|
|
err.code === 'EBADF' || // Bad file number means we got closed
|
|
err.code === 'ENXIO' || // No such device or address probably usb disconnect
|
|
err.code === 'UNKNOWN' ||
|
|
err.errno === -1 // generic error
|
|
|
|
if (disconnectError) {
|
|
err.disconnect = true
|
|
logger('disconnecting', err)
|
|
}
|
|
|
|
logger('error', err)
|
|
throw err
|
|
}
|
|
}
|
|
module.exports = unixWrite
|