text: const fs = require('fs')
  const debug = require('debug')
  const logger = debug('serialport/bindings/unixRead')
  const { promisify } = require('util')
  
  const readAsync = promisify(fs.read)
  
  const readable = binding => {
    return new Promise((resolve, reject) => {
      binding.poller.once('readable', err => (err ? reject(err) : resolve()))
    })
  }
  
  const unixRead = async ({ binding, buffer, offset, length, fsReadAsync = readAsync }) => {
    logger('Starting read')
    if (!binding.isOpen) {
      const err = new Error('Port is not open')
      err.canceled = true
      throw err
    }
  
    try {
      const { bytesRead } = await fsReadAsync(binding.fd, buffer, offset, length, null)
      if (bytesRead === 0) {
        return unixRead({ binding, buffer, offset, length, fsReadAsync })
      }
      logger('Finished read', bytesRead, 'bytes')
      return { bytesRead, buffer }
    } catch (err) {
      logger('read error', err)
      if (err.code === 'EAGAIN' || err.code === 'EWOULDBLOCK' || err.code === 'EINTR') {
        if (!binding.isOpen) {
          const err = new Error('Port is not open')
          err.canceled = true
          throw err
        }
        logger('waiting for readable because of code:', err.code)
        await readable(binding)
        return unixRead({ binding, buffer, offset, length, fsReadAsync })
      }
  
      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.canceled = true
        logger('disconnecting', err)
      }
  
      throw err
    }
  }
  
  module.exports = unixRead
  