Created
November 27, 2025 07:32
-
-
Save max-verem/2c0b0812be321863796d1599c0f0dc59 to your computer and use it in GitHub Desktop.
CRSF [EE 18 16] => [C8 18 16]
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #include <stdio.h> | |
| #include <errno.h> | |
| #include <string.h> | |
| #include <stdlib.h> | |
| #include <unistd.h> | |
| #include <asm/termbits.h> | |
| #include <fcntl.h> | |
| #include <sys/ioctl.h> | |
| int serial_arbitrary_baudrate(int fd, int baudrate) | |
| { | |
| #if !defined BOTHER | |
| fprintf(stderr, "%s: not supported\n", __FUNCTION__); | |
| return -EINVAL; | |
| #else | |
| int r; | |
| struct termios2 tio; | |
| r = ioctl(fd, TCGETS2, &tio); | |
| if(r < 0) | |
| { | |
| r = errno; | |
| fprintf(stderr, "%s: ioctl(TCGETS2) failed: r=%d (%s)\n", __FUNCTION__, r, strerror(r)); | |
| return -r; | |
| }; | |
| /* Clear the current output baud rate and fill a new value */ | |
| tio.c_cflag &= ~CBAUD; | |
| tio.c_cflag |= BOTHER; | |
| tio.c_ospeed = baudrate; | |
| /* Clear the current input baud rate and fill a new value */ | |
| tio.c_cflag &= ~(CBAUD << IBSHIFT); | |
| tio.c_cflag |= BOTHER << IBSHIFT; | |
| tio.c_ispeed = baudrate; | |
| r = ioctl(fd, TCSETS2, &tio); | |
| if(r < 0) | |
| { | |
| r = errno; | |
| fprintf(stderr, "%s: ioctl(TCSETS2) failed: r=%d (%s)\n", __FUNCTION__, r, strerror(r)); | |
| return -r; | |
| }; | |
| r = ioctl(fd, TCGETS2, &tio); | |
| if(r < 0) | |
| { | |
| r = errno; | |
| fprintf(stderr, "%s: ioctl(TCGETS2) failed: r=%d (%s)\n", __FUNCTION__, r, strerror(r)); | |
| return -r; | |
| }; | |
| fprintf(stderr, "%s: c_ospeed=%u, c_ispeed=%u\n", __FUNCTION__, tio.c_ospeed, tio.c_ispeed); | |
| return 0; | |
| #endif | |
| }; |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #ifndef serial_arbitrary_baudrate_h | |
| #define serial_arbitrary_baudrate_h | |
| int serial_arbitrary_baudrate(int fd, int baudrate); | |
| #endif |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| /* | |
| gcc -Wall -g -ggdb -O0 serial_arbitrary_baudrate.c test2.c -o test2 | |
| */ | |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <stdint.h> | |
| #include <inttypes.h> | |
| #include <errno.h> | |
| #include <string.h> | |
| #include <unistd.h> | |
| #include <sys/stat.h> | |
| #include <time.h> | |
| #include <termios.h> | |
| #include <sys/ioctl.h> | |
| #include <sys/types.h> | |
| #include <linux/serial.h> | |
| #include <fcntl.h> | |
| #include <netdb.h> | |
| #include <sys/socket.h> | |
| #include <netinet/in.h> | |
| #include <arpa/inet.h> | |
| #include <pty.h> | |
| #include "serial_arbitrary_baudrate.h" | |
| #define CRSF_DEV "/home/demo/ttyCRSF" | |
| #define SERIAL_DEV "/dev/serial/by-id/usb-1a86_USB2.0-Ser_-if00-port0" | |
| #define SERIAL_SPEED 400000 | |
| int main(int argc, char** argv) | |
| { | |
| int r, fd_serial = -1, fd_pty = -1, q; | |
| uint64_t cnt_total = 0, cnt_crsf = 0, cnt_display = 0; | |
| struct termios newtio; | |
| char pty_name[1024]; | |
| /* remove existing link to pty */ | |
| unlink(CRSF_DEV); | |
| /* open pty */ | |
| r = openpty(&fd_pty, &q, pty_name, NULL, NULL); | |
| if(r < 0) | |
| { | |
| r = errno; | |
| fprintf(stderr, "%s: openpty() failed: r=%d (%s)\n", | |
| __FUNCTION__, r, strerror(r)); | |
| goto ex; | |
| }; | |
| { | |
| struct termios t; | |
| tcgetattr(q, &t); | |
| cfmakeraw(&t); | |
| tcsetattr(q, TCSANOW, &t); | |
| close(q); | |
| }; | |
| // r = fcntl(fd_pty, F_GETFL, 0); | |
| // if(!r) | |
| fcntl(fd_pty, F_SETFL, /* r | O_NONBLOCK | */ FNDELAY); | |
| fprintf(stderr, "%s:%d [%s]\n", __FUNCTION__, __LINE__, pty_name); | |
| /* create symlink */ | |
| r = symlink(pty_name, CRSF_DEV); | |
| if(r < 0) | |
| { | |
| r = errno; | |
| fprintf(stderr, "%s: symlink([%s], [%s]) failed: r=%d (%s)\n", | |
| __FUNCTION__, pty_name, CRSF_DEV, r, strerror(r)); | |
| goto ex; | |
| }; | |
| /* open serial port */ | |
| fd_serial = open(SERIAL_DEV, O_RDWR | O_NOCTTY); | |
| if(fd_serial < 0) | |
| { | |
| r = errno; | |
| fprintf(stderr, "%s: open(%s) failed: r=%d (%s)\n", | |
| __FUNCTION__, SERIAL_DEV, r, strerror(r)); | |
| return -r; | |
| }; | |
| /* configure serial device */ | |
| memset(&newtio, 0, sizeof(struct termios)); /* clear struct for new port settings */ | |
| newtio.c_iflag = IGNPAR; /* ignore bytes with parity errors */ | |
| newtio.c_oflag = 0; /* Raw output */ | |
| newtio.c_lflag = 0; /* enable canonical input */ | |
| newtio.c_cc[VTIME] = 1; /* inter-character timer unused */ | |
| newtio.c_cc[VMIN] = 1; /* blocking read until 5 chars received */ | |
| newtio.c_cflag = | |
| CS8 | | |
| CREAD | | |
| CLOCAL; | |
| r = cfsetspeed(&newtio, B115200); | |
| r = tcsetattr(fd_serial, TCSANOW, &newtio); | |
| if(r < 0) | |
| { | |
| r = errno; | |
| fprintf(stderr, "%s: tcsetattr failed: r=%d (%s)\n", | |
| __FUNCTION__, r, strerror(r)); | |
| close(fd_serial); | |
| return -r; | |
| }; | |
| serial_arbitrary_baudrate(fd_serial, SERIAL_SPEED); | |
| tcflush(fd_serial, TCIFLUSH); | |
| tcflush(fd_serial, TCIOFLUSH); | |
| while(1) | |
| { | |
| int l; | |
| static const char anim[4] = "|/-\\"; | |
| unsigned char msg[512]; | |
| r = read(fd_serial, msg, sizeof(msg)); | |
| cnt_total++; | |
| #if 0 | |
| fprintf(stdout, "%5d 0x%.02X 0x%.02X 0x%.02X 0x%.02X ... \r", | |
| r, msg[0], msg[1], msg[2], msg[3]); | |
| #endif | |
| /* | |
| [ 26] EE 18 16 EB 9B DE C4 B9 D7 0A F0 B5 A2 15 E0 03 1F F8 C0 07 3E F0 81 0F 7C 54 | |
| [ 26] EE 18 16 ED A3 DE C4 B9 D7 0A F0 B5 A2 15 E0 03 1F F8 C0 07 3E F0 81 0F 7C FF | |
| [ 26] EE 18 16 EC A3 DE C4 B9 D7 0A F0 B5 A2 15 E0 03 1F F8 C0 07 3E F0 81 0F 7C C4 | |
| */ | |
| #if 0 | |
| /* we accept only CRSF_FRAMETYPE_RC_CHANNELS_PACKED */ | |
| if(r != 26 || msg[0] != 0xEE || msg[1] != 0x18 || msg[2] != 0x16) | |
| { | |
| fprintf(stderr, "."); | |
| continue; | |
| }; | |
| msg[0] = 0xc8; // Flight Controller | |
| #else | |
| for(l = 0; l < (r - 3); l++) | |
| { | |
| if(msg[l + 0] == 0xEE && msg[l + 1] == 0x18 && msg[l + 2] == 0x16) | |
| msg[l + 0] = 0xC8; | |
| }; | |
| #endif | |
| cnt_crsf++; | |
| r = write(fd_pty, msg, l = r); | |
| if(r < 0) | |
| { | |
| r = errno; | |
| if(r != EAGAIN && r != EWOULDBLOCK) | |
| { | |
| fprintf(stderr, "%s:%d: write failed, r=%d (%s)\n", | |
| __FUNCTION__, __LINE__, r, strerror(r)); | |
| break; | |
| }; | |
| }; | |
| if(cnt_crsf % 20) | |
| continue; | |
| cnt_display++; | |
| fprintf(stderr, "[%c] ---\r", anim[cnt_display % sizeof(anim)]); | |
| }; | |
| ex: | |
| if(fd_serial > 0) | |
| close(fd_serial); | |
| if(fd_pty > 0) | |
| close(fd_pty); | |
| return r; | |
| }; | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment