void EIO_Open(uv_work_t* req) {
  OpenBaton* data = static_cast<OpenBaton*>(req->data);
  UnixPlatformOptions* platformOptions = static_cast<UnixPlatformOptions*>(data->platformOptions);

  int baudRate = ToBaudConstant(data->baudRate);

// #if not ( defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) )
//   if(baudRate == -1) {
//     snprintf(data->errorString, sizeof(data->errorString), "Invalid baud rate setting %d", data->baudRate);
//     return;
//   }
// #endif

  int dataBits = ToDataBitsConstant(data->dataBits);
  if(dataBits == -1) {
    snprintf(data->errorString, sizeof(data->errorString), "Invalid data bits setting %d", data->dataBits);
    return;
  }


  int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_CLOEXEC | O_SYNC);
  int fd = open(data->path, flags);

  if (fd == -1) {
    snprintf(data->errorString, sizeof(data->errorString), "Cannot open %s", data->path);
    return;
  }


  // struct sigaction saio;
  // saio.sa_handler = sigio_handler;
  // sigemptyset(&saio.sa_mask);
  // saio.sa_flags = 0;
  // sigaction(SIGIO, &saio, NULL);

  // //all process to receive SIGIO
  // fcntl(fd, F_SETOWN, getpid());
  // int flflags = fcntl(fd, F_GETFL);
  // fcntl(fd, F_SETFL, flflags | FNONBLOCK);

  struct termios options;
  // Set baud and other configuration.
  tcgetattr(fd, &options);

// Removing check for valid BaudRates due to ticket: #140
// #if not ( defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) )
  // Specify the baud rate


  // On linux you can alter the meaning of B38400 to mean a custom baudrate...
#if defined(__linux__) && defined(ASYNC_SPD_CUST)
  if (baudRate == -1) {
    struct serial_struct serinfo;
    serinfo.reserved_char[0] = 0;
    if (ioctl(fd, TIOCGSERIAL, &serinfo) != -1) {
      serinfo.flags &= ~ASYNC_SPD_MASK;
      serinfo.flags |= ASYNC_SPD_CUST;
      serinfo.custom_divisor = (serinfo.baud_base + (data->baudRate / 2)) / data->baudRate;
      if (serinfo.custom_divisor < 1)
        serinfo.custom_divisor = 1;

      ioctl(fd, TIOCSSERIAL, &serinfo);
      ioctl(fd, TIOCGSERIAL, &serinfo);
      // if (serinfo.custom_divisor * rate != serinfo.baud_base) {
      //   warnx("actual baudrate is %d / %d = %f",
      //     serinfo.baud_base, serinfo.custom_divisor,
      //     (float)serinfo.baud_base / serinfo.custom_divisor);
      // }
    }

    // Now we use "B38400" to trigger the special baud rate.
    baudRate = B38400;
  }
#endif

  if (baudRate != -1) {
    cfsetispeed(&options, baudRate);
    cfsetospeed(&options, baudRate);
  }

// Removing check for valid BaudRates due to ticket: #140
// #endif

  /*
    IGNPAR  : ignore bytes with parity errors
  */
  options.c_iflag = IGNPAR;

  /*
    ICRNL   : map CR to NL (otherwise a CR input on the other computer
              will not terminate input)
  */
  // Pulling this for now. It should be an option, however. -Giseburt
  //options.c_iflag = ICRNL;

  //  otherwise make device raw (no other input processing)


  // Specify data bits
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= dataBits;

  options.c_cflag &= ~(CRTSCTS);

  if (data->rtscts) {
    options.c_cflag |= CRTSCTS;
    // evaluate specific flow control options
  }

  options.c_iflag &= ~(IXON | IXOFF | IXANY);

  if (data->xon) {
    options.c_iflag |= IXON;
  }

  if (data->xoff) {
    options.c_iflag |= IXOFF;
  }

  if (data->xany) {
    options.c_iflag |= IXANY;
  }


  switch (data->parity)
  {
  case SERIALPORT_PARITY_NONE:
    options.c_cflag &= ~PARENB;
    // options.c_cflag &= ~CSTOPB;
    // options.c_cflag &= ~CSIZE;
    // options.c_cflag |= CS8;
    break;
  case SERIALPORT_PARITY_ODD:
    options.c_cflag |= PARENB;
    options.c_cflag |= PARODD;
    // options.c_cflag &= ~CSTOPB;
    // options.c_cflag &= ~CSIZE;
    // options.c_cflag |= CS7;
    break;
  case SERIALPORT_PARITY_EVEN:
    options.c_cflag |= PARENB;
    options.c_cflag &= ~PARODD;
    // options.c_cflag &= ~CSTOPB;
    // options.c_cflag &= ~CSIZE;
    // options.c_cflag |= CS7;
    break;
  default:
    snprintf(data->errorString, sizeof(data->errorString), "Invalid parity setting %d", data->parity);
    close(fd);
    return;
  }

  switch(data->stopBits) {
  case SERIALPORT_STOPBITS_ONE:
    options.c_cflag &= ~CSTOPB;
    break;
  case SERIALPORT_STOPBITS_TWO:
    options.c_cflag |= CSTOPB;
    break;
  default:
    snprintf(data->errorString, sizeof(data->errorString), "Invalid stop bits setting %d", data->stopBits);
    close(fd);
    return;
  }

  options.c_cflag |= CLOCAL; //ignore status lines
  options.c_cflag |= CREAD;  //enable receiver
  options.c_cflag |= HUPCL;  //drop DTR (i.e. hangup) on close

  // Raw output
  options.c_oflag = 0;

  // ICANON makes partial lines not readable. It should be otional.
  // It works with ICRNL. -Giseburt
  options.c_lflag = 0; //ICANON;

  options.c_cc[VMIN]= platformOptions->vmin;
  options.c_cc[VTIME]= platformOptions->vtime;

  // removed this unneeded sleep.
  // sleep(1);
  tcflush(fd, TCIFLUSH);
  tcsetattr(fd, TCSANOW, &options);

  // On OS X, starting in Tiger, we can set a custom baud rate, as follows:
#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
  if (baudRate == -1) {
    speed_t speed = data->baudRate;
    if (ioctl(fd,  IOSSIOSPEED, &speed) == -1) {
      snprintf(data->errorString, sizeof(data->errorString), "Error %s calling ioctl( ..., IOSSIOSPEED, %ld )", strerror(errno), speed );
    }
  }
#endif

  data->result = fd;
}
void EIO_Open(uv_work_t* req) {
  OpenBaton* data = static_cast<OpenBaton*>(req->data);

#if not ( defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) )
  int baudRate = ToBaudConstant(data->baudRate);
  if(baudRate == -1) {
    sprintf(data->errorString, "Invalid baud rate setting %d", data->baudRate);
    return;
  }
#endif
  int dataBits = ToDataBitsConstant(data->dataBits);
  if(dataBits == -1) {
    sprintf(data->errorString, "Invalid data bits setting %d", data->dataBits);
    return;
  }

  int flowControl = ToFlowControlConstant(data->flowControl);
  if(flowControl == -1) {
    sprintf(data->errorString, "Invalid flow control setting %d", data->flowControl);
    return;
  }

  int flags = (O_RDWR | O_NOCTTY | O_NONBLOCK | O_NDELAY);
  int fd = open(data->path, flags);

  if (fd == -1) {
    sprintf(data->errorString, "Cannot open %s", data->path);
    return;
  }

  struct termios options;
  struct sigaction saio;
  saio.sa_handler = SIG_IGN;
  sigemptyset(&saio.sa_mask);
  saio.sa_flags = 0;
  sigaction(SIGIO, &saio, NULL);

  //all process to receive SIGIO
  fcntl(fd, F_SETOWN, getpid());
  fcntl(fd, F_SETFL, FASYNC);

  // Set baud and other configuration.
  tcgetattr(fd, &options);

#if not ( defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4) )
  // Specify the baud rate
  cfsetispeed(&options, baudRate);
  cfsetospeed(&options, baudRate);
#endif 

  // Specify data bits
  options.c_cflag &= ~CSIZE;
  options.c_cflag |= dataBits;

  // Specify flow control
  options.c_cflag &= ~flowControl;
  options.c_cflag |= flowControl;

  switch (data->parity)
  {
  case SERIALPORT_PARITY_NONE:
    options.c_cflag &= ~PARENB;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS8;
    break;
  case SERIALPORT_PARITY_ODD:
    options.c_cflag |= PARENB;
    options.c_cflag |= PARODD;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    break;
  case SERIALPORT_PARITY_EVEN:
    options.c_cflag |= PARENB;
    options.c_cflag &= ~PARODD;
    options.c_cflag &= ~CSTOPB;
    options.c_cflag &= ~CSIZE;
    options.c_cflag |= CS7;
    break;
  default:
    sprintf(data->errorString, "Invalid parity setting %d", data->parity);
    close(fd);
    return;
  }

  switch(data->stopBits) {
  case SERIALPORT_STOPBITS_ONE:
    options.c_cflag &= ~CSTOPB;
    break;
  case SERIALPORT_STOPBITS_TWO:
    options.c_cflag |= CSTOPB;
    break;
  default:
    sprintf(data->errorString, "Invalid stop bits setting %d", data->stopBits);
    close(fd);
    return;
  }

  options.c_cflag |= CLOCAL; //ignore status lines
  options.c_cflag |= CREAD;  //enable receiver
  options.c_cflag |= HUPCL;  //drop DTR (i.e. hangup) on close
  options.c_iflag = IGNPAR;
  options.c_oflag = 0;
  options.c_lflag = 0; //ICANON;
  options.c_cc[VMIN]=1;
  options.c_cc[VTIME]=0;

  sleep(1);
  tcflush(fd, TCIFLUSH);
  tcsetattr(fd, TCSANOW, &options);


#if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
    speed_t speed = data->baudRate;
    if ( ioctl( fd,  IOSSIOSPEED, &speed ) == -1 )
    {
      printf( "Error %d calling ioctl( ..., IOSSIOSPEED, ... )\n", errno );
    }
#endif 


  data->result = fd;
}
int setBaudRate(ConnectionOptionsBaton *data) {
  // lookup the standard baudrates from the table
  int baudRate = ToBaudConstant(data->baudRate);
  int fd = data->fd;

  // get port options
  struct termios options;
  if (-1 == tcgetattr(fd, &options)) {
    snprintf(data->errorString, sizeof(data->errorString),
             "Error: %s setting custom baud rate of %d", strerror(errno), data->baudRate);
    return -1;
  }

  // If there is a custom baud rate on linux you can do the following trick with B38400
  #if defined(__linux__) && defined(ASYNC_SPD_CUST)
    if (baudRate == -1) {
      int err = linuxSetCustomBaudRate(fd, data->baudRate);

      if (err == -1) {
        snprintf(data->errorString, sizeof(data->errorString),
                 "Error: %s || while retrieving termios2 info", strerror(errno));
        return -1;
      } else if (err == -2) {
        snprintf(data->errorString, sizeof(data->errorString),
                 "Error: %s || while setting custom baud rate of %d", strerror(errno), data->baudRate);
        return -1;
      }

      return 1;
    }
  #endif

  // On OS X, starting with Tiger, we can set a custom baud rate with ioctl
  #if defined(MAC_OS_X_VERSION_10_4) && (MAC_OS_X_VERSION_MIN_REQUIRED >= MAC_OS_X_VERSION_10_4)
    if (-1 == baudRate) {
      speed_t speed = data->baudRate;
      if (-1 == ioctl(fd, IOSSIOSPEED, &speed)) {
        snprintf(data->errorString, sizeof(data->errorString),
                 "Error: %s calling ioctl(.., IOSSIOSPEED, %ld )", strerror(errno), speed);
        return -1;
      } else {
        tcflush(fd, TCIOFLUSH);
        return 1;
      }
    }
  #endif

  if (-1 == baudRate) {
    snprintf(data->errorString, sizeof(data->errorString),
             "Error baud rate of %d is not supported on your platform", data->baudRate);
    return -1;
  }

  // If we have a good baud rate set it and lets go
  cfsetospeed(&options, baudRate);
  cfsetispeed(&options, baudRate);
  // throw away all the buffered data
  tcflush(fd, TCIOFLUSH);
  // make the changes now
  tcsetattr(fd, TCSANOW, &options);
  return 1;
}