2017-06-28 3 views
0

J'essaie d'ouvrir le port dans Android (appareil rooté) avec le fichier .c ci-dessous. Malheureusement, il me donne l'erreur tcsetattr() failed qui se connecte mon fichier (voir le code ci-dessous). Je ne semble pas résoudre le problème toute aide est appréciée.Android port série ouvert natif

NOTE: targetSdkVersion 17

Aussi je l'ai testé canRead() et canWrite() sur dev/ttyS4 les deux retours true

#include <termios.h> 
#include <unistd.h> 
#include <sys/types.h> 
#include <sys/stat.h> 
#include <fcntl.h> 
#include <string.h> 
#include <jni.h> 

#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)->GetStringUTFChars(env, path, &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)->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, &cfg)) 
     { 
      LOGE("tcgetattr() failed"); 
      close(fd); 
      /* TODO: throw an exception */ 
      return NULL; 
     } 

     cfmakeraw(&cfg); 
     cfsetispeed(&cfg, speed); 
     cfsetospeed(&cfg, speed); 

     if (tcsetattr(fd, TCSANOW, &cfg)) 
     { 
      LOGE("tcsetattr() failed"); 
      close(fd); 
      /* TODO: throw an exception */ 
      return NULL; 
     } 
    } 

    /* Create a corresponding file descriptor */ 
    { 
     jclass cFileDescriptor = (*env)->FindClass(env, "java/io/FileDescriptor"); 
     jmethodID iFileDescriptor = (*env)->GetMethodID(env, cFileDescriptor, "<init>", "()V"); 
     jfieldID descriptorID = (*env)->GetFieldID(env, cFileDescriptor, "descriptor", "I"); 
     mFileDescriptor = (*env)->NewObject(env, cFileDescriptor, iFileDescriptor); 
     (*env)->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)->GetObjectClass(env, thiz); 
    jclass FileDescriptorClass = (*env)->FindClass(env, "java/io/FileDescriptor"); 

    jfieldID mFdID = (*env)->GetFieldID(env, SerialPortClass, "mFd", "Ljava/io/FileDescriptor;"); 
    jfieldID descriptorID = (*env)->GetFieldID(env, FileDescriptorClass, "descriptor", "I"); 

    jobject mFd = (*env)->GetObjectField(env, thiz, mFdID); 
    jint descriptor = (*env)->GetIntField(env, mFd, descriptorID); 

    LOGD("close(fd = %d)", descriptor); 
    close(descriptor); 
} 
+1

J'ai trouvé un moyen. Il semble fonctionner pour n'importe quel type d'appareil, car il suffit d'accéder aux périphériques en tant que fichier. Voir le lien android-serialport-api. Cela fonctionne pour n'importe quel type de/dev/... Dans chaque cas, j'ai dû installer le NDK et passer par toutes les hooplas pour le faire fonctionner. Il y a un morceau de code fait en C où il définit le débit en bauds. En fait, l'ouverture et la fermeture sont implémentées en C le reste est tout le standard Java androïde. – Dhiyaneshwaran

+1

Bien que ce ne soit pas votre problème, je pense que c'est une mauvaise forme de ne pas identifier votre attente de la valeur de retour et devrait être 'if (tcsetattr (fd, TCSANOW, & cfg)! = 0)'. –

Répondre

1

Et encore une fois grâce à Android versioning :(Je suis tout à fait perdu un certain temps pour trouver ce poste http://m.blog.csdn.net/caojengineer/article/details/51838394. Le problème était dans le fichier termios.h qui a changé après Android 19 ou Android 21. S o, ce que j'ai simplement fait était d'aller à la copie de lien termios.h qui est à partir de Android 19 ndk coller dans le répertoire où se trouvent mes fichiers .c et changer #include <termios.h> à #include termios.h. Voir l'extrait de code ci-dessus.