clinux-device-driverembedded-linuxuartsocat

Virtual UART device in linux


I'm trying to implement a virtual UART using socat command for send and receive a string that is encrypted using XOR cipher on sending and decrypted while receiving using C program.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <fcntl.h>
#include <unistd.h>
#include <termios.h>

#define BUFFER_SIZE 256
#define UART_DEVICE_TX "./ttyV0"  // Transmit end
#define UART_DEVICE_RX "./ttyV1"  // Receive end

// XOR cipher for encryption and decryption
void xor_cipher(char *data, size_t length, char key) {
    for (size_t i = 0; i < length; ++i) {
        data[i] ^= key;
    }
}

// Configure the UART device
int configure_uart(const char *device) {
    int uart_fd = open(device, O_RDWR | O_NOCTTY);
    if (uart_fd < 0) {
        perror("Failed to open UART device");
        return -1;
    }

    struct termios options;
    tcgetattr(uart_fd, &options);

    // Set baud rate to 9600, 8 data bits, no parity, 1 stop bit
    cfsetispeed(&options, B9600);
    cfsetospeed(&options, B9600);
    options.c_cflag = (options.c_cflag & ~CSIZE) | CS8;  // 8 data bits
    options.c_cflag |= (CLOCAL | CREAD);                 // Enable receiver
    options.c_cflag &= ~(PARENB | CSTOPB);               // No parity, 1 stop bit
    options.c_iflag &= ~(IXON | IXOFF | IXANY);          // Disable flow control
    options.c_lflag = 0;                                 // Raw input mode
    options.c_oflag = 0;                                 // Raw output mode

    tcsetattr(uart_fd, TCSANOW, &options);
    return uart_fd;
}

int main() {
    const char key = 0x5A;          // XOR encryption key
    char original_message[] = "Hello, UART!";  // Original message
    char encrypted_message[BUFFER_SIZE];
    char received_message[BUFFER_SIZE];

    printf("Original message: %s\n", original_message);

    // Copy the original message and encrypt it
    strcpy(encrypted_message, original_message);
    xor_cipher(encrypted_message, strlen(encrypted_message), key);

    // Configure UART devices
    int uart_fd_tx = configure_uart(UART_DEVICE_TX);  // Transmit end
    int uart_fd_rx = configure_uart(UART_DEVICE_RX);  // Receive end
    if (uart_fd_tx < 0 || uart_fd_rx < 0) {
        return EXIT_FAILURE;
    }

    // Send the encrypted message to the TX port (master)
    write(uart_fd_tx, encrypted_message, strlen(encrypted_message));
    printf("Encrypted message sent: %s\n", encrypted_message);

    // Receive the encrypted message from the RX port (slave)
    memset(received_message, 0, BUFFER_SIZE);
    int bytes_read = read(uart_fd_rx, received_message, BUFFER_SIZE - 1);
    if (bytes_read < 0) {
        perror("Failed to read from UART device");
        close(uart_fd_tx);
        close(uart_fd_rx);
        return EXIT_FAILURE;
    }

    // Decrypt the received message
    xor_cipher(received_message, bytes_read, key);
    printf("Decrypted message: %s\n", received_message);

    // Check if the original and decrypted messages match
    if (strcmp(original_message, received_message) == 0) {
        printf("Decryption successful: Messages match.\n");
    } else {
        printf("Decryption failed: Messages do not match.\n");
    }

    // Clean up
    close(uart_fd_tx);
    close(uart_fd_rx);
    return EXIT_SUCCESS;
}

for creating virtual uart driver in the working directory i used this command: socat -d -d PTY,link=./ttyV0,raw,echo=0 PTY,link=./ttyV1,raw,echo=0

after compilation and running the c file the encryption parting running and iam getting the encrypted data on tty1(cat ./ttyV1)

but the decryption part is not working.. i need help to figure this out.

when i tried without looking on the devices its working fine

Original message: Hello, UART!

Encrypted message sent: ?665vz

Encrypted message received: ?665vz

Decrypted message: Hello, UART!

Decryption successful: Messages match.

when i start cat ./ttyV1 in one terminal and run the program it will display like this

Original message: Hello, UART!

Encrypted message sent: ?665vz

not doing the decryption part

but the key can be seen in the other terminal that runs cat ./ttyV1

why this happening?


Solution

  • When an open TTY receives data, it is held in a buffer until it has been read by one of the processes that has the TTY open. Once it has been read by a process (or thread), it is discarded and is no longer available for the other processes (or threads) to read. The same thing happens if multiple processes are trying to read from the receive end of a pipe, FIFO (named pipe), or socket, whether or not the file descriptors are freshly opened, duplicated, or inherited.