A process is running remotely on the Tessel and data is piped in over USB
function USBProcess(id, daemon) {
  // The numerical identifer for this process
  this.id = id;

  /*
  active && !closed = Process is running as usual
  !active && !closed = Process has been sent a signal but not completely closed (resources freed)
  !active && closed = Process has stopped running and has already been destroyed
  */
  // Status of whether this process is running
  this.active = true;
  // Status of whether this process was cleaned up
  this.closed = false;
  // Boolean of whether this process has been forcibly killed
  this.forceKill = false;
  // Code to be set upon process death
  this.exitedWithError = false;
  // Some processes, like `sysupgrade` will not be close-able
  // because OpenWRT does not have the spidaemon active.
  // In these cases, just close without trying to send kill signal
  this.waitForClose = true;

  // 4 remote process streams
  this.control = new RemoteWritableStream(this, daemon, protocol.controlWrite, protocol.controlClose);
  this.stdin = new RemoteWritableStream(this, daemon, protocol.stdinWrite, protocol.stdinClose);
  this.stdout = new RemoteReadableStream(this, daemon, protocol.stdoutAck);
  this.stderr = new RemoteReadableStream(this, daemon, protocol.stderrAck);

  // Once the process is killed
  this.once('death', (data) => {
    // This process is no longer running
    this.active = false;
    // Close the input streams because the remote proc can't handle data
    this.control.end();
    this.stdin.end();

    // Close the process
    this.closeProcessIfReady();

    // Check for a non-zero exit code
    var exitCode = parseInt(data.arg);
    debug(`Death for "${this.commandString}" with exit code: ${exitCode}`);
    if (exitCode !== 0 && !this.forceKill) {
      this.exitedWithError = true;
    }
  });

  // Tell the USBDaemon to close the remote process
  this.close = () => {
    // Write the close command
    daemon.write(protocol.closeProcess(this.id));

    // Mark this process as closed
    this.closed = true;
  };

  // Send a signal to the remote process
  this.kill = (signal) => {
    // Mark our boolean
    this.forceKill = true;

    // If we should wait for close (most processes should)
    if (this.waitForClose) {
      // Write the signal command
      daemon.write(protocol.killProcess(this.id, signal));
    } else {
      // Mark the process as inactive and closed
      this.active = false;
      this.closed = true;
      // Emit the close event
      setImmediate(() => this.emit('close'));
    }
  };

  // Checks if this process is ready to be closed
  // and closes it if it can
  this.closeProcessIfReady = () => {
    // If this process hasn't been closed before
    // and all of the streams are closed
    if (!this.active && !this.closed && this.stdout.closed && this.stderr.closed) {
      // Close this process
      this.close();
    }
  };

  // When any of the streams complete, check if the process is ready to close
  this.stdout.once('end', () => this.closeProcessIfReady());
  this.stderr.once('end', () => this.closeProcessIfReady());

  // This function is primarily intended for compatibility with the ssh2 stream API
  this.stdout.signal = (signalToSend) => {
    switch (signalToSend) {
      case 'KILL':
        this.kill(9);
        break;
      case 'SIGINT':
        this.kill(2);
        break;
    }
  };

  // Tell the remote daemon that this process was created
  daemon.write(protocol.newProcess(this.id));
  // Tell the remote daemon that we can start receiving outbound data
  this.stdout.ack(MAX_BUFFER_SIZE);
  this.stderr.ack(MAX_BUFFER_SIZE);
}