DF-5422 / uftdi_live.c
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 | /* uftdi_live.c — live uftdi/cuaU0 exercise rig (DF-5422 pack) * modes: * t : baseline timings: open + tcsetattr(115200) + tcsetattr(9600) + close * w <n> : write n bytes, print md5-ish checksum of pattern written * r <n> <t>: read up to n bytes with timeout t ms, dump hex of first 64 * s : status ioctls: TIOCMGET, TIOCMSET toggle, break on/off * bad : invalid termios speeds (expect EINVAL), CS5..CS8 sweep * o : keep fd open and pause (for unplug/reset races) - sleeps 30s */ #include <sys/types.h> #include <sys/ioctl.h> #include <sys/time.h> #include <termios.h> #include <fcntl.h> #include <unistd.h> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <errno.h> #include <sys/endian.h> static double now(void) { struct timeval tv; gettimeofday(&tv, 0); return tv.tv_sec + tv.tv_usec / 1e6; } static int openport(void) { int fd = open("/dev/cuaU0", O_RDWR | O_NONBLOCK); if (fd < 0) perror("open /dev/cuaU0"); return fd; } int main(int argc, char **argv) { const char *mode = argc > 1 ? argv[1] : "t"; int fd, i, rc; if (!strcmp(mode, "t")) { for (i = 0; i < 3; i++) { double t0 = now(); fd = openport(); if (fd < 0) return 1; double t1 = now(); struct termios ti; rc = tcgetattr(fd, &ti); cfmakeraw(&ti); cfsetspeed(&ti, 115200); rc = tcsetattr(fd, TCSANOW, &ti); double t2 = now(); cfsetspeed(&ti, 9600); rc = tcsetattr(fd, TCSANOW, &ti); double t3 = now(); rc = close(fd); double t4 = now(); printf("run %d: open=%.1fms set115200=%.1fms set9600=%.1fms close=%.1fms rc=%d\n", i, (t1-t0)*1e3, (t2-t1)*1e3, (t3-t2)*1e3, (t4-t3)*1e3, rc); } return 0; } if (!strcmp(mode, "w")) { int n = argc > 2 ? atoi(argv[2]) : 4096; char *buf = malloc(n); for (i = 0; i < n; i++) buf[i] = (i * 7 + 3) & 0xff; fd = openport(); if (fd < 0) return 1; { struct termios t2; tcgetattr(fd, &t2); cfmakeraw(&t2); cfsetspeed(&t2, 115200); tcsetattr(fd, TCSANOW, &t2); } fcntl(fd, F_SETFL, fcntl(fd, F_GETFL) & ~O_NONBLOCK); int off = 0; while (off < n) { rc = write(fd, buf + off, n - off); if (rc < 0) { if (errno == EAGAIN) { usleep(1000); continue; } perror("write"); return 2; } off += rc; } unsigned long long h = 1469598103934665603ULL; for (i = 0; i < n; i++) { h ^= (unsigned char)buf[i]; h *= 1099511628211ULL; } printf("wrote %d bytes fnv64=%016llx\n", n, h); close(fd); return 0; } if (!strcmp(mode, "r")) { int n = argc > 2 ? atoi(argv[2]) : 65536; int ms = argc > 3 ? atoi(argv[3]) : 3000; char *buf = malloc(n); fd = openport(); if (fd < 0) return 1; { struct termios t2; tcgetattr(fd, &t2); cfmakeraw(&t2); cfsetspeed(&t2, 115200); tcsetattr(fd, TCSANOW, &t2); } int tot = 0; double t0 = now(); while (tot < n && (now() - t0) * 1000 < ms) { rc = read(fd, buf + tot, n - tot); if (rc > 0) tot += rc; else usleep(500); } printf("read %d bytes:\n", tot); for (i = 0; i < tot && i < 64; i++) printf("%02x", (unsigned char)buf[i]); printf("\n"); /* simple pattern check: expect 0..255 cycling if host sent that */ close(fd); return 0; } if (!strcmp(mode, "s")) { fd = openport(); if (fd < 0) return 1; int m = 0; rc = ioctl(fd, TIOCMGET, &m); printf("TIOCMGET rc=%d modem=0x%x\n", rc, m); m = TIOCM_DTR | TIOCM_RTS; rc = ioctl(fd, TIOCMSET, &m); printf("TIOCMSET(DTR|RTS) rc=%d\n", rc); rc = ioctl(fd, TIOCMGET, &m); printf("TIOCMGET modem=0x%x\n", m); struct termios ti; tcgetattr(fd, &ti); double t0 = now(); rc = ioctl(fd, TIOCSBRK); /* break on */ usleep(100000); rc |= ioctl(fd, TIOCCBRK); /* break off */ printf("break on/off rc=%d in %.1fms\n", rc, (now()-t0)*1e3); tcgetattr(fd, &ti); ioctl(fd, TIOCSDTR); ioctl(fd, TIOCCDTR); printf("dtr on/off done\n"); close(fd); return 0; } if (!strcmp(mode, "bad")) { fd = openport(); if (fd < 0) return 1; struct termios ti; tcgetattr(fd, &ti); int speeds[] = {0, 1, 50, 177, 178, 300, 9600, 57600, 115200, 309278, 309279, 4000000, 12000000}; for (i = 0; i < (int)(sizeof(speeds)/sizeof(speeds[0])); i++) { cfsetspeed(&ti, (speed_t)speeds[i]); int r = tcsetattr(fd, TCSANOW, &ti); printf("speed %7d -> rc=%d errno=%d (%s)\n", speeds[i], r, errno, r ? strerror(errno) : "ok"); } close(fd); return 0; } if (!strcmp(mode, "o")) { fd = openport(); if (fd < 0) return 1; printf("fd=%d open, sleeping 30s\n", fd); fflush(stdout); sleep(30); char c = 'X'; rc = write(fd, &c, 1); printf("post-sleep write rc=%d errno=%d (%s)\n", rc, errno, strerror(errno)); rc = read(fd, &c, 1); printf("post-sleep read rc=%d errno=%d\n", rc, errno); close(fd); printf("closed\n"); return 0; } fprintf(stderr, "unknown mode\n"); return 64; } |