From e893621a6b6052469dc84af149931843d9de9390 Mon Sep 17 00:00:00 2001 From: perrypetiet <61829617+perrypetiet@users.noreply.github.com> Date: Wed, 26 Oct 2022 12:35:02 +0200 Subject: [PATCH 1/3] mark/space parity + custom baudrate Added mark and space parity using the CMSPAR flag in combination with the PARODD flag. Added custom baudrate using the termios2 structure instead of the termios header. Added function to change the parity of a port given the device File and the parity. Added constants to set parity easier (example.. Parity_Even instead of 2). --- serialport/src/main/cpp/SerialPort.c | 217 +++++++++++++++------------ serialport/src/main/cpp/SerialPort.h | 8 + 2 files changed, 126 insertions(+), 99 deletions(-) diff --git a/serialport/src/main/cpp/SerialPort.c b/serialport/src/main/cpp/SerialPort.c index 07049cb..0d66dab 100644 --- a/serialport/src/main/cpp/SerialPort.c +++ b/serialport/src/main/cpp/SerialPort.c @@ -14,7 +14,8 @@ * limitations under the License. */ -#include +//#include +#include #include #include #include @@ -31,74 +32,6 @@ static const char *TAG = "serial_port"; #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 @@ -114,15 +47,6 @@ JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open speed_t speed; jobject mFileDescriptor; - /* Check arguments */ - { - speed = getBaudrate(baudrate); - if (speed == -1) { - /* TODO: throw an exception */ - LOGE("Invalid baudrate"); - return NULL; - } - } /* Opening device */ { @@ -142,33 +66,31 @@ JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open /* Configure device */ { - struct termios cfg; - LOGD("Configuring serial port"); - if (tcgetattr(fd, &cfg)) { - LOGE("tcgetattr() failed"); - close(fd); - /* TODO: throw an exception */ - return NULL; - } + struct termios2 cfg; + - cfmakeraw(&cfg); - cfsetispeed(&cfg, speed); - cfsetospeed(&cfg, speed); + ioctl (fd, TCGETS2, &cfg); + // SET BAUDRATE + cfg.c_cflag &= ~CBAUD; + cfg.c_cflag |= BOTHER; + + cfg.c_ispeed = baudrate; + cfg.c_ospeed = baudrate; cfg.c_cflag &= ~CSIZE; switch (dataBits) { case 5: - cfg.c_cflag |= CS5; //使用5位数据位 + cfg.c_cflag |= CS5; break; case 6: - cfg.c_cflag |= CS6; //使用6位数据位 + cfg.c_cflag |= CS6; break; case 7: - cfg.c_cflag |= CS7; //使用7位数据位 + cfg.c_cflag |= CS7; break; case 8: - cfg.c_cflag |= CS8; //使用8位数据位 + cfg.c_cflag |= CS8; break; default: cfg.c_cflag |= CS8; @@ -177,17 +99,40 @@ JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open switch (parity) { case 0: - cfg.c_cflag &= ~PARENB; //无奇偶校验 + // PARITY OFF + cfg.c_cflag &= ~PARENB; break; case 1: - cfg.c_cflag |= (PARODD | PARENB); //奇校验 + // PARITY ODD + cfg.c_cflag |= (PARODD | PARENB); + cfg.c_iflag &= ~IGNPAR; + cfg.c_iflag |= PARMRK; + cfg.c_iflag |= INPCK; break; case 2: - cfg.c_iflag &= ~(IGNPAR | PARMRK); // 偶校验 + // PARITY EVEN + cfg.c_iflag &= ~(IGNPAR | PARMRK); cfg.c_iflag |= INPCK; cfg.c_cflag |= PARENB; cfg.c_cflag &= ~PARODD; break; + case 3: + // PARITY SPACE + cfg.c_iflag &= ~IGNPAR; // Make sure wrong parity is not ignored + cfg.c_iflag |= PARMRK; // Marks parity error, parity error + // is given as three char sequence + cfg.c_iflag |= INPCK; // Enable input parity checking + cfg.c_cflag |= PARENB | CMSPAR; // Enable parity and set space parity + cfg.c_cflag &= ~PARODD; // + break; + case 4: + // PARITY MARK + cfg.c_iflag &= ~IGNPAR; // Make sure wrong parity is not ignored + cfg.c_iflag |= PARMRK; // Marks parity error, parity error + // is given as three char sequence + cfg.c_iflag |= INPCK; // Enable input parity checking + cfg.c_cflag |= PARENB | CMSPAR | PARODD; + break; default: cfg.c_cflag &= ~PARENB; break; @@ -205,11 +150,11 @@ JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open break; } - if (tcsetattr(fd, TCSANOW, &cfg)) { - LOGE("tcsetattr() failed"); + if(ioctl (fd, TCSETS2, &cfg)){ + LOGE("tcsets2 failed"); close(fd); - /* TODO: throw an exception */ return NULL; + /* TODO: throw an exception */ } } @@ -245,3 +190,77 @@ JNIEXPORT void JNICALL Java_android_serialport_SerialPort_close close(descriptor); } + +JNIEXPORT void JNICALL +Java_android_serialport_SerialPort_setParity(JNIEnv *env, jobject thiz, jstring absolute_path, + jint parity) { + int flags = 0; + int fd; + + /* Opening device */ + { + jboolean iscopy; + const char *path_utf = (*env)->GetStringUTFChars(env, absolute_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, absolute_path, path_utf); + if (fd == -1) { + /* Throw an exception */ + LOGE("Cannot get serial port!"); + return; + /* TODO: throw an exception */ + } + } + + /* Configure device */ + { + struct termios2 cfg; + ioctl(fd, TCGETS2, &cfg); + switch (parity) { + case 0: + // PARITY OFF + cfg.c_cflag &= ~PARENB; + break; + case 1: + // PARITY ODD + cfg.c_cflag |= (PARODD | PARENB); + cfg.c_iflag &= ~IGNPAR; + cfg.c_iflag |= PARMRK; + cfg.c_iflag |= INPCK; + break; + case 2: + // PARITY EVEN + cfg.c_iflag &= ~(IGNPAR | PARMRK); + cfg.c_iflag |= INPCK; + cfg.c_cflag |= PARENB; + cfg.c_cflag &= ~PARODD; + break; + case 3: + // PARITY SPACE + cfg.c_iflag &= ~IGNPAR; // Make sure wrong parity is not ignored + cfg.c_iflag |= PARMRK; // Marks parity error, parity error + // is given as three char sequence + cfg.c_iflag |= INPCK; // Enable input parity checking + cfg.c_cflag |= PARENB | CMSPAR; // Enable parity and set space parity + cfg.c_cflag &= ~PARODD; // + break; + case 4: + // PARITY MARK + cfg.c_iflag &= ~IGNPAR; // Make sure wrong parity is not ignored + cfg.c_iflag |= PARMRK; // Marks parity error, parity error + // is given as three char sequence + cfg.c_iflag |= INPCK; // Enable input parity checking + cfg.c_cflag |= PARENB | CMSPAR | PARODD; + break; + default: + cfg.c_cflag &= ~PARENB; + break; + } + if(ioctl (fd, TCSETS2, &cfg)){ + LOGE("tcsets2 failed, parity not updated!"); + return; + /* TODO: throw an exception */ + } + } +} \ No newline at end of file diff --git a/serialport/src/main/cpp/SerialPort.h b/serialport/src/main/cpp/SerialPort.h index bed2cc7..0be3397 100644 --- a/serialport/src/main/cpp/SerialPort.h +++ b/serialport/src/main/cpp/SerialPort.h @@ -15,6 +15,14 @@ extern "C" { JNIEXPORT jobject JNICALL Java_android_serialport_SerialPort_open (JNIEnv *, jobject, jstring, jint, jint, jint, jint, jint); +/* + * Class: android_serialport_SerialPort + * Method: setParity + * Signature: (Ljava/lang/String;I)Ljava/io/FileDescriptor; + */ +JNIEXPORT void JNICALL +Java_android_serialport_SerialPort_setParity(JNIEnv *, jobject, jstring, jint); + /* * Class: android_serialport_SerialPort * Method: close From e9779c8602d1016383e6f68caaf3ac05e2b02323 Mon Sep 17 00:00:00 2001 From: perrypetiet <61829617+perrypetiet@users.noreply.github.com> Date: Wed, 26 Oct 2022 12:36:44 +0200 Subject: [PATCH 2/3] mark/space parity + custom baudrate Added mark and space parity using the CMSPAR flag in combination with the PARODD flag. Added custom baudrate using the termios2 structure instead of the termios header. Added function to change the parity of a port given the device File and the parity. Added constants to set parity easier (example.. Parity_Even instead of 2). --- .../java/android/serialport/SerialPort.java | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/serialport/src/main/java/android/serialport/SerialPort.java b/serialport/src/main/java/android/serialport/SerialPort.java index 8d4b53d..f911ee2 100644 --- a/serialport/src/main/java/android/serialport/SerialPort.java +++ b/serialport/src/main/java/android/serialport/SerialPort.java @@ -27,19 +27,27 @@ import java.io.InputStream; import java.io.OutputStream; + + public final class SerialPort { + public static final int Parity_None = 0; + public static final int Parity_Odd = 1; + public static final int Parity_Even = 2; + public static final int Parity_Space= 3; + public static final int Parity_Mark = 4; + private static final String TAG = "SerialPort"; public static final String DEFAULT_SU_PATH = "/system/bin/su"; private static String sSuPath = DEFAULT_SU_PATH; - private File device; - private int baudrate; - private int dataBits; - private int parity; - private int stopBits; - private int flags; + private final File device; + private final int baudrate; + private final int dataBits; + private final int parity; + private final int stopBits; + private final int flags; /** * Set the su binary path, the default su binary path is {@link #DEFAULT_SU_PATH} @@ -66,9 +74,9 @@ public static String getSuPath() { /* * Do not remove or rename the field mFd: it is used by native method close(); */ - private FileDescriptor mFd; - private FileInputStream mFileInputStream; - private FileOutputStream mFileOutputStream; + private final FileDescriptor mFd; + private final FileInputStream mFileInputStream; + private final FileOutputStream mFileOutputStream; /** * 串口 @@ -187,10 +195,18 @@ public int getFlags() { return flags; } + /** Change parity */ + public void changeParity(File device, int parity){ + setParity(device.getAbsolutePath(), parity); + } + // JNI private native FileDescriptor open(String absolutePath, int baudrate, int dataBits, int parity, int stopBits, int flags); + // JNI + private native void setParity(String absolutePath, int parity); + public native void close(); /** 关闭流和串口,已经try-catch */ @@ -228,8 +244,8 @@ public static Builder newBuilder(String devicePath, int baudrate) { public final static class Builder { - private File device; - private int baudrate; + private final File device; + private final int baudrate; private int dataBits = 8; private int parity = 0; private int stopBits = 1; From 58d514994cc634ddb8cee037fc435de724abb148 Mon Sep 17 00:00:00 2001 From: perrypetiet <61829617+perrypetiet@users.noreply.github.com> Date: Wed, 26 Oct 2022 13:05:08 +0200 Subject: [PATCH 3/3] parity updated fix parity is now also updated in the serialport class after calling the changeparity function --- .../main/java/android/serialport/SerialPort.java | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) diff --git a/serialport/src/main/java/android/serialport/SerialPort.java b/serialport/src/main/java/android/serialport/SerialPort.java index f911ee2..c35702e 100644 --- a/serialport/src/main/java/android/serialport/SerialPort.java +++ b/serialport/src/main/java/android/serialport/SerialPort.java @@ -42,12 +42,12 @@ public final class SerialPort { public static final String DEFAULT_SU_PATH = "/system/bin/su"; private static String sSuPath = DEFAULT_SU_PATH; - private final File device; - private final int baudrate; - private final int dataBits; - private final int parity; - private final int stopBits; - private final int flags; + private File device; + private int baudrate; + private int dataBits; + private int parity; + private int stopBits; + private int flags; /** * Set the su binary path, the default su binary path is {@link #DEFAULT_SU_PATH} @@ -198,6 +198,7 @@ public int getFlags() { /** Change parity */ public void changeParity(File device, int parity){ setParity(device.getAbsolutePath(), parity); + this.parity = parity; } // JNI