// // Created by pengx on 2024/11/7. // #include <termios.h> #include <unistd.h> #include <sys/types.h> #include <sys/stat.h> #include <fcntl.h> #include <cstring> #include <jni.h> #include "android/log.h" #include "serial_port.h" static const char *jni_tag = "JNI_SerialPort"; static speed_t get_baud_rate(jint j_baud_rate) { switch (j_baud_rate) { 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; } } static jobject j_fd_object = nullptr; extern "C" JNIEXPORT jobject JNICALL Java_com_casic_common_detector_gd_uart_SerialPort_open(JNIEnv *env, jobject thiz, jstring path, jint baud_rate, jint flags) { int fd; speed_t speed; /* Check arguments */ { speed = get_baud_rate(baud_rate); if (speed == -1) { __android_log_print(ANDROID_LOG_DEBUG, jni_tag, "invalid baud_rate"); return nullptr; } } /* Opening device */ { jboolean is_copy; const char *path_utf = env->GetStringUTFChars(path, &is_copy); __android_log_print( ANDROID_LOG_DEBUG, jni_tag, "opening serial port %s with flags 0x%x", path_utf, O_RDWR | flags ); fd = open(path_utf, O_RDWR | flags); __android_log_print(ANDROID_LOG_DEBUG, jni_tag, "open() fd = %d", fd); env->ReleaseStringUTFChars(path, path_utf); if (fd == -1) { __android_log_print(ANDROID_LOG_DEBUG, jni_tag, "open port failed"); return nullptr; } } /* Configure device */ { struct termios cfg{}; __android_log_print(ANDROID_LOG_DEBUG, jni_tag, "configuring serial port"); if (tcgetattr(fd, &cfg)) { __android_log_print(ANDROID_LOG_DEBUG, jni_tag, "tcgetattr() failed"); close(fd); return nullptr; } cfmakeraw(&cfg); cfsetispeed(&cfg, speed); cfsetospeed(&cfg, speed); if (tcsetattr(fd, TCSANOW, &cfg)) { __android_log_print(ANDROID_LOG_DEBUG, jni_tag, "tcsetattr() failed"); close(fd); return nullptr; } } /* Create a corresponding file descriptor */ { jclass j_fd_class = env->FindClass("java/io/FileDescriptor"); jmethodID j_fd_methodID = env->GetMethodID(j_fd_class, "<init>", "()V"); char descriptor_buffer[16] = {0}; strcat(descriptor_buffer, "descriptor"); jfieldID j_desc_fieldID = env->GetFieldID(j_fd_class, descriptor_buffer, "I"); j_fd_object = env->NewObject(j_fd_class, j_fd_methodID); env->SetIntField(j_fd_object, j_desc_fieldID, (jint) fd); } return j_fd_object; } extern "C" JNIEXPORT void JNICALL Java_com_casic_common_detector_gd_uart_SerialPort_close(JNIEnv *env, jobject thiz) { jclass serial_port_class = env->GetObjectClass(thiz); jclass file_descriptor_class = env->FindClass("java/io/FileDescriptor"); // fd 对应SerialPort里面的 fd char fd_buffer[4] = {0}; strcat(fd_buffer, "fd"); jfieldID fd_field_id = env->GetFieldID(serial_port_class, fd_buffer, "Ljava/io/FileDescriptor;"); char descriptor_buffer[16] = {0}; strcat(descriptor_buffer, "descriptor"); jfieldID descriptor_field_id = env->GetFieldID(file_descriptor_class, descriptor_buffer, "I"); jobject fd_obj = env->GetObjectField(thiz, fd_field_id); jint descriptor = env->GetIntField(fd_obj, descriptor_field_id); __android_log_print(ANDROID_LOG_DEBUG, jni_tag, "close()"); close(descriptor); }