title: Android native open serial port
body: <p>I'm trying to open port in Android (rooted device) with .c file below. Unfortunately it gives me error <code>tcsetattr() failed</code> which is Log in my file (see code below). I seem not solve problem any help is appreciated.</p>
  
  <blockquote>
    <p>NOTE: <code>targetSdkVersion 17</code></p>
    
    <p>Also I have tested <code>canRead()</code> and <code>canWrite()</code> on dev/ttyS4 both
    returns <code>true</code></p>
  </blockquote>
  
  <pre><code>#include &lt;termios.h&gt;
  #include &lt;unistd.h&gt;
  #include &lt;sys/types.h&gt;
  #include &lt;sys/stat.h&gt;
  #include &lt;fcntl.h&gt;
  #include &lt;string.h&gt;
  #include &lt;jni.h&gt;
  
  #include "serial_port.h"
  
  #include "android/log.h"
  static const char *TAG="serial_port";
  #define LOGI(fmt, args...) __android_log_print(ANDROID_LOG_INFO,  TAG, fmt, ##args)
  #define LOGD(fmt, args...) __android_log_print(ANDROID_LOG_DEBUG, TAG, fmt, ##args)
  #define LOGE(fmt, args...) __android_log_print(ANDROID_LOG_ERROR, TAG, fmt, ##args)
  
  static speed_t getBaudrate(jint baudrate)
  {
      switch(baudrate) {
          case 0: return B0;
          case 50: return B50;
          case 75: return B75;
          case 110: return B110;
          case 134: return B134;
          case 150: return B150;
          case 200: return B200;
          case 300: return B300;
          case 600: return B600;
          case 1200: return B1200;
          case 1800: return B1800;
          case 2400: return B2400;
          case 4800: return B4800;
          case 9600: return B9600;
          case 19200: return B19200;
          case 38400: return B38400;
          case 57600: return B57600;
          case 115200: return B115200;
          case 230400: return B230400;
          case 460800: return B460800;
          case 500000: return B500000;
          case 576000: return B576000;
          case 921600: return B921600;
          case 1000000: return B1000000;
          case 1152000: return B1152000;
          case 1500000: return B1500000;
          case 2000000: return B2000000;
          case 2500000: return B2500000;
          case 3000000: return B3000000;
          case 3500000: return B3500000;
          case 4000000: return B4000000;
          default: return -1;
      }
  }
  
  /*
   * Class:     android_serialport_SerialPort
   * Method:    open
   * Signature: (Ljava/lang/String;II)Ljava/io/FileDescriptor;
   */
  JNIEXPORT jobject JNICALL Java_com_geotek_invent_rodinbell_port_SerialPort_open
          (JNIEnv *env, jclass thiz, jstring path, jint baudrate, jint flags)
  {
      int fd;
      speed_t speed;
      jobject mFileDescriptor;
  
      /* Check arguments */
      {
          speed = getBaudrate(baudrate);
          if (speed == -1) {
              /* TODO: throw an exception */
              LOGE("Invalid baudrate");
              return NULL;
          }
      }
  
      /* Opening device */
      {
          jboolean iscopy;
          const char *path_utf = (*env)-&gt;GetStringUTFChars(env, path, &amp;iscopy);
          LOGD("Opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags);
          fd = open(path_utf, O_RDWR | flags);
          LOGD("open() fd = %d", fd);
          (*env)-&gt;ReleaseStringUTFChars(env, path, path_utf);
          if (fd == -1)
          {
              /* Throw an exception */
              LOGE("Cannot open port");
              /* TODO: throw an exception */
              return NULL;
          }
      }
  
      /* Configure device */
      {
          struct termios cfg;
          LOGD("Configuring serial port");
          if (tcgetattr(fd, &amp;cfg))
          {
              LOGE("tcgetattr() failed");
              close(fd);
              /* TODO: throw an exception */
              return NULL;
          }
  
          cfmakeraw(&amp;cfg);
          cfsetispeed(&amp;cfg, speed);
          cfsetospeed(&amp;cfg, speed);
  
          if (tcsetattr(fd, TCSANOW, &amp;cfg))
          {
              LOGE("tcsetattr() failed");
              close(fd);
              /* TODO: throw an exception */
              return NULL;
          }
      }
  
      /* Create a corresponding file descriptor */
      {
          jclass cFileDescriptor = (*env)-&gt;FindClass(env, "java/io/FileDescriptor");
          jmethodID iFileDescriptor = (*env)-&gt;GetMethodID(env, cFileDescriptor, "&lt;init&gt;", "()V");
          jfieldID descriptorID = (*env)-&gt;GetFieldID(env, cFileDescriptor, "descriptor", "I");
          mFileDescriptor = (*env)-&gt;NewObject(env, cFileDescriptor, iFileDescriptor);
          (*env)-&gt;SetIntField(env, mFileDescriptor, descriptorID, (jint)fd);
      }
  
      return mFileDescriptor;
  }
  
  /*
   * Class:     cedric_serial_SerialPort
   * Method:    close
   * Signature: ()V
   */
  JNIEXPORT void JNICALL Java_com_geotek_invent_rodinbell_port_SerialPort_close
          (JNIEnv *env, jobject thiz)
  {
      jclass SerialPortClass = (*env)-&gt;GetObjectClass(env, thiz);
      jclass FileDescriptorClass = (*env)-&gt;FindClass(env, "java/io/FileDescriptor");
  
      jfieldID mFdID = (*env)-&gt;GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;");
      jfieldID descriptorID = (*env)-&gt;GetFieldID(env, FileDescriptorClass, "descriptor", "I");
  
      jobject mFd = (*env)-&gt;GetObjectField(env, thiz, mFdID);
      jint descriptor = (*env)-&gt;GetIntField(env, mFd, descriptorID);
  
      LOGD("close(fd = %d)", descriptor);
      close(descriptor);
  }
  </code></pre>