text: const childProcess = require('child_process')
  const Readline = require('@serialport/parser-readline')
  
  // get only serial port names
  function checkPathOfDevice(path) {
    return /(tty(S|WCH|ACM|USB|AMA|MFD|O|XRUSB)|rfcomm)/.test(path) && path
  }
  
  function propName(name) {
    return {
      DEVNAME: 'path',
      ID_VENDOR_ENC: 'manufacturer',
      ID_SERIAL_SHORT: 'serialNumber',
      ID_VENDOR_ID: 'vendorId',
      ID_MODEL_ID: 'productId',
      DEVLINKS: 'pnpId',
    }[name.toUpperCase()]
  }
  
  function decodeHexEscape(str) {
    return str.replace(/\\x([a-fA-F0-9]{2})/g, (a, b) => {
      return String.fromCharCode(parseInt(b, 16))
    })
  }
  
  function propVal(name, val) {
    if (name === 'pnpId') {
      const match = val.match(/\/by-id\/([^\s]+)/)
      return (match && match[1]) || undefined
    }
    if (name === 'manufacturer') {
      return decodeHexEscape(val)
    }
    if (/^0x/.test(val)) {
      return val.substr(2)
    }
    return val
  }
  
  function listLinux() {
    return new Promise((resolve, reject) => {
      const ports = []
      const ude = childProcess.spawn('udevadm', ['info', '-e'])
      const lines = ude.stdout.pipe(new Readline())
      ude.on('close', code => code && reject(new Error(`Error listing ports udevadm exited with error code: ${code}`)))
      ude.on('error', reject)
      lines.on('error', reject)
  
      let port = {}
      let skipPort = false
      lines.on('data', line => {
        const lineType = line.slice(0, 1)
        const data = line.slice(3)
        // new port entry
        if (lineType === 'P') {
          port = {
            manufacturer: undefined,
            serialNumber: undefined,
            pnpId: undefined,
            locationId: undefined,
            vendorId: undefined,
            productId: undefined,
          }
          skipPort = false
          return
        }
  
        if (skipPort) {
          return
        }
  
        // Check dev name and save port if it matches flag to skip the rest of the data if not
        if (lineType === 'N') {
          if (checkPathOfDevice(data)) {
            ports.push(port)
          } else {
            skipPort = true
          }
          return
        }
  
        // parse data about each port
        if (lineType === 'E') {
          const keyValue = data.match(/^(.+)=(.*)/)
          if (!keyValue) {
            return
          }
          const key = propName(keyValue[1])
          if (!key) {
            return
          }
          port[key] = propVal(key, keyValue[2])
        }
      })
  
      lines.on('finish', () => resolve(ports))
    })
  }
  
  module.exports = listLinux
  