git-svn-id: https://bucket.mit.edu/svn/nilm/zoom@7604 ddd99763-3ecb-0310-9145-efcb8ce7c51ftags/zoom-1.0
@@ -1 +1,13 @@ | |||||
CFLAGS=-Wall -Werror | |||||
all: read calibrate | all: read calibrate | ||||
serial-util.o: serial-util.h | |||||
read.o: serial-util.h | |||||
calibrate.o: serial-util.h | |||||
read: read.o serial-util.o | |||||
calibrate: calibrate.o serial-util.o |
@@ -1,18 +1,16 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <termio.h> | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/ioctl.h> | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <getopt.h> | #include <getopt.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <syslog.h> | #include <syslog.h> | ||||
#include <fcntl.h> | |||||
#include <err.h> | #include <err.h> | ||||
#include <linux/serial.h> | #include <linux/serial.h> | ||||
#include <sys/signal.h> | #include <sys/signal.h> | ||||
#include "serial-util.h" | |||||
int zoom, gpib; | int zoom, gpib; | ||||
@@ -26,62 +24,11 @@ void handle_sig(int sig) | |||||
quit = 1; | quit = 1; | ||||
} | } | ||||
int serial_open(const char *device, int rate) | |||||
{ | |||||
struct termios options; | |||||
struct serial_struct serinfo; | |||||
int fd; | |||||
int speed = 0; | |||||
/* Open and configure serial port */ | |||||
if ((fd = open(device,O_RDWR|O_NOCTTY)) == -1) | |||||
err(1, "%s", device); | |||||
switch (rate) { | |||||
case 9600: speed = B9600; break; | |||||
case 115200: speed = B115200; break; | |||||
} | |||||
if (speed == 0) { | |||||
serinfo.reserved_char[0] = 0; | |||||
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) | |||||
err(1, "%s: TIOCGSERIAL", device); | |||||
serinfo.flags &= ~ASYNC_SPD_MASK; | |||||
serinfo.flags |= ASYNC_SPD_CUST; | |||||
serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate; | |||||
if (serinfo.custom_divisor < 1) | |||||
serinfo.custom_divisor = 1; | |||||
if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) | |||||
err(1, "%s: TIOCSSERIAL", device); | |||||
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) | |||||
err(1, "%s: TIOCGSERIAL 2", device); | |||||
if (serinfo.custom_divisor * rate != serinfo.baud_base) { | |||||
warnx("actual baudrate is %d / %d = %f", | |||||
serinfo.baud_base, serinfo.custom_divisor, | |||||
(float)serinfo.baud_base / serinfo.custom_divisor); | |||||
} | |||||
} | |||||
fcntl(fd, F_SETFL, 0); | |||||
tcgetattr(fd, &options); | |||||
cfsetispeed(&options, speed ?: B38400); | |||||
cfsetospeed(&options, speed ?: B38400); | |||||
cfmakeraw(&options); | |||||
options.c_cflag |= (CLOCAL | CREAD); | |||||
options.c_cflag &= ~CRTSCTS; | |||||
if (tcsetattr(fd, TCSANOW, &options) != 0) | |||||
err(1, "TCSANOW"); | |||||
return fd; | |||||
} | |||||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||
{ | { | ||||
char *zoomdev=strdup("/dev/ttyUSB1"); | char *zoomdev=strdup("/dev/ttyUSB1"); | ||||
char *gpibdev=strdup("/dev/ttyUSB0"); | char *gpibdev=strdup("/dev/ttyUSB0"); | ||||
int getopt_index; | int getopt_index; | ||||
int i; | |||||
char buf[1024]; | |||||
static struct option long_opts[] = { | static struct option long_opts[] = { | ||||
{ "zoom-device", required_argument, NULL, 'z' }, | { "zoom-device", required_argument, NULL, 'z' }, | ||||
@@ -92,6 +39,16 @@ int main(int argc, char *argv[]) | |||||
int help=0; | int help=0; | ||||
char c; | char c; | ||||
{ | |||||
char buf[1024]; | |||||
drain(0); | |||||
fdprintf(1,"type a string in 5 sec: "); | |||||
fdgets(buf, 1024, 0, 5000); | |||||
chomp(buf); | |||||
fdprintf(1,"you typed: '%s' len %d\n", buf, strlen(buf)); | |||||
abort(); | |||||
} | |||||
while ((c = getopt_long(argc, argv, "z:g:h?", | while ((c = getopt_long(argc, argv, "z:g:h?", | ||||
long_opts, &getopt_index)) != -1) { | long_opts, &getopt_index)) != -1) { | ||||
switch(c) | switch(c) | ||||
@@ -1,17 +1,15 @@ | |||||
#include <stdio.h> | #include <stdio.h> | ||||
#include <stdlib.h> | #include <stdlib.h> | ||||
#include <termio.h> | |||||
#include <sys/types.h> | #include <sys/types.h> | ||||
#include <sys/ioctl.h> | |||||
#include <errno.h> | #include <errno.h> | ||||
#include <unistd.h> | #include <unistd.h> | ||||
#include <getopt.h> | #include <getopt.h> | ||||
#include <stdint.h> | #include <stdint.h> | ||||
#include <string.h> | #include <string.h> | ||||
#include <syslog.h> | #include <syslog.h> | ||||
#include <fcntl.h> | |||||
#include <err.h> | #include <err.h> | ||||
#include <linux/serial.h> | #include <linux/serial.h> | ||||
#include "serial-util.h" | |||||
int hex = 0; | int hex = 0; | ||||
int dec = 0; | int dec = 0; | ||||
@@ -21,54 +19,12 @@ int total = 0; | |||||
int process(const uint8_t *buf, int len); | int process(const uint8_t *buf, int len); | ||||
int serial_open(const char *device, int rate) | |||||
{ | |||||
struct termios options; | |||||
struct serial_struct serinfo; | |||||
int fd; | |||||
/* Open and configure serial port */ | |||||
if ((fd = open(device,O_RDWR|O_NOCTTY)) == -1) | |||||
err(1, "%s", device); | |||||
serinfo.reserved_char[0] = 0; | |||||
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) | |||||
err(1, "%s: TIOCGSERIAL", device); | |||||
serinfo.flags &= ~ASYNC_SPD_MASK; | |||||
serinfo.flags |= ASYNC_SPD_CUST; | |||||
serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate; | |||||
if (serinfo.custom_divisor < 1) | |||||
serinfo.custom_divisor = 1; | |||||
if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) | |||||
err(1, "%s: TIOCSSERIAL", device); | |||||
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) | |||||
err(1, "%s: TIOCGSERIAL 2", device); | |||||
if (serinfo.custom_divisor * rate != serinfo.baud_base) { | |||||
warnx("actual baudrate is %d / %d = %f", | |||||
serinfo.baud_base, serinfo.custom_divisor, | |||||
(float)serinfo.baud_base / serinfo.custom_divisor); | |||||
} | |||||
fcntl(fd, F_SETFL, 0); | |||||
tcgetattr(fd, &options); | |||||
cfsetispeed(&options, B38400); | |||||
cfsetospeed(&options, B38400); | |||||
cfmakeraw(&options); | |||||
options.c_cflag |= (CLOCAL | CREAD); | |||||
options.c_cflag &= ~CRTSCTS; | |||||
if (tcsetattr(fd, TCSANOW, &options) != 0) | |||||
err(1, "TCSANOW"); | |||||
return fd; | |||||
} | |||||
int main(int argc, char *argv[]) | int main(int argc, char *argv[]) | ||||
{ | { | ||||
char *device=strdup("/dev/ttyUSB0"); | char *device=strdup("/dev/ttyUSB0"); | ||||
int rate=500000; | int rate=500000; | ||||
int fd; | int fd; | ||||
int getopt_index; | int getopt_index; | ||||
int i; | |||||
char buf[1024]; | char buf[1024]; | ||||
int len; | int len; | ||||
@@ -146,7 +102,7 @@ int main(int argc, char *argv[]) | |||||
if (n <= 0) | if (n <= 0) | ||||
err(1, "read"); | err(1, "read"); | ||||
len += n; | len += n; | ||||
processed = process(buf, len); | |||||
processed = process((uint8_t *) buf, len); | |||||
memmove(buf, buf + processed, len - processed); | memmove(buf, buf + processed, len - processed); | ||||
len -= processed; | len -= processed; | ||||
} | } | ||||
@@ -0,0 +1,199 @@ | |||||
/* | |||||
* Serial I/O helper routines | |||||
* | |||||
* Jim Paris <jim@jtan.com> | |||||
* $Id$ | |||||
*/ | |||||
#include <stdio.h> | |||||
#include <stdlib.h> | |||||
#include <termio.h> | |||||
#include <sys/types.h> | |||||
#include <sys/ioctl.h> | |||||
#include <errno.h> | |||||
#include <unistd.h> | |||||
#include <string.h> | |||||
#include <fcntl.h> | |||||
#include <err.h> | |||||
#include <linux/serial.h> | |||||
#include <poll.h> | |||||
#include <stdarg.h> | |||||
#include "serial-util.h" | |||||
static int rate_to_constant(int baudrate) { | |||||
#define B(x) case x: return B##x | |||||
switch(baudrate) { | |||||
B(50); B(75); B(110); B(134); B(150); | |||||
B(200); B(300); B(600); B(1200); B(1800); | |||||
B(2400); B(4800); B(9600); B(19200); B(38400); | |||||
B(57600); B(115200); B(230400); B(460800); B(500000); | |||||
B(576000); B(921600); B(1000000);B(1152000);B(1500000); | |||||
default: return 0; | |||||
} | |||||
#undef B | |||||
} | |||||
/* Open serial port in raw mode, with custom baudrate if necessary */ | |||||
int serial_open(const char *device, int rate) | |||||
{ | |||||
struct termios options; | |||||
struct serial_struct serinfo; | |||||
int fd; | |||||
int speed = 0; | |||||
/* Open and configure serial port */ | |||||
if ((fd = open(device,O_RDWR|O_NOCTTY)) == -1) | |||||
return -1; | |||||
speed = rate_to_constant(rate); | |||||
if (speed == 0) { | |||||
serinfo.reserved_char[0] = 0; | |||||
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) | |||||
return -1; | |||||
serinfo.flags &= ~ASYNC_SPD_MASK; | |||||
serinfo.flags |= ASYNC_SPD_CUST; | |||||
serinfo.custom_divisor = (serinfo.baud_base + (rate / 2)) / rate; | |||||
if (serinfo.custom_divisor < 1) | |||||
serinfo.custom_divisor = 1; | |||||
if (ioctl(fd, TIOCSSERIAL, &serinfo) < 0) | |||||
return -1; | |||||
if (ioctl(fd, TIOCGSERIAL, &serinfo) < 0) | |||||
return -1; | |||||
if (serinfo.custom_divisor * rate != serinfo.baud_base) { | |||||
warnx("actual baudrate is %d / %d = %f", | |||||
serinfo.baud_base, serinfo.custom_divisor, | |||||
(float)serinfo.baud_base / serinfo.custom_divisor); | |||||
} | |||||
} | |||||
fcntl(fd, F_SETFL, 0); | |||||
tcgetattr(fd, &options); | |||||
cfsetispeed(&options, speed ?: B38400); | |||||
cfsetospeed(&options, speed ?: B38400); | |||||
cfmakeraw(&options); | |||||
options.c_cflag |= (CLOCAL | CREAD); | |||||
options.c_cflag &= ~CRTSCTS; | |||||
if (tcsetattr(fd, TCSANOW, &options) != 0) | |||||
return -1; | |||||
return fd; | |||||
} | |||||
/* Like read(), but restarts after EINTR, and reads until count bytes | |||||
are received or a timeout occurs. */ | |||||
int saferead_timeout(int fd, void *buf, size_t count, int timeout_ms) | |||||
{ | |||||
struct pollfd pfd; | |||||
int r; | |||||
size_t nread = 0; | |||||
while (count > 0) { | |||||
pfd.fd = fd; | |||||
pfd.events = POLLIN; | |||||
r = poll(&pfd, 1, timeout_ms); | |||||
if (r < 0 && errno == EINTR) /* retry */ | |||||
continue; | |||||
else if (r == 0) /* timeout */ | |||||
return nread; | |||||
else if (r == 1 && (pfd.revents & POLLIN)) { /* readable */ | |||||
r = read(fd, buf, count); | |||||
if (r < 0 && errno == EINTR) /* retry */ | |||||
continue; | |||||
if (r < 0) /* error */ | |||||
return r; | |||||
if (r == 0) /* EOF */ | |||||
return nread; | |||||
buf = (char *) buf + r; | |||||
count -= r; | |||||
nread += r; | |||||
} else { | |||||
/* error */ | |||||
return -1; | |||||
} | |||||
} | |||||
return nread; | |||||
} | |||||
/* Like write(), but restarts after EINTR */ | |||||
ssize_t safewrite(int fd, const void *buf, size_t count) | |||||
{ | |||||
size_t nwritten = 0; | |||||
while (count > 0) { | |||||
ssize_t r = write(fd, buf, count); | |||||
if (r < 0 && errno == EINTR) | |||||
continue; | |||||
if (r < 0) | |||||
return r; | |||||
if (r == 0) | |||||
return nwritten; | |||||
buf = (const char *)buf + r; | |||||
count -= r; | |||||
nwritten += r; | |||||
} | |||||
return nwritten; | |||||
} | |||||
/* Read bytes until no more are available for 0.1 sec */ | |||||
int drain(int fd) | |||||
{ | |||||
char buf[1024]; | |||||
int ret; | |||||
while (1) { | |||||
ret = saferead_timeout(fd, buf, sizeof(buf), 100); | |||||
if (ret <= 0) | |||||
return ret; | |||||
} | |||||
} | |||||
/* Like fprintf, but to a fd, using safewrite. */ | |||||
static int vfdprintf(int fd, const char *fmt, va_list args) | |||||
{ | |||||
static char buf[1024]; | |||||
vsnprintf(buf, sizeof(buf), fmt, args); | |||||
return safewrite(fd, buf, strlen(buf)); | |||||
} | |||||
int fdprintf(int fd, const char *fmt, ...) | |||||
{ | |||||
int ret; | |||||
va_list args; | |||||
va_start(args, fmt); | |||||
ret = vfdprintf(fd, fmt, args); | |||||
va_end(args); | |||||
return ret; | |||||
} | |||||
/* Like fgets, but from a fd, using saferead_timeout. */ | |||||
char *fdgets(char *s, int size, int fd, int timeout_ms) | |||||
{ | |||||
int ret; | |||||
int nread = 0; | |||||
/* Not very efficient, needs to read one char at a time to avoid buffering */ | |||||
while (nread < (size - 1)) { | |||||
ret = saferead_timeout(fd, &s[nread], 1, timeout_ms); | |||||
if (ret <= 0) { | |||||
s[nread] = '\0'; | |||||
return NULL; | |||||
} | |||||
if (ret == 1) { | |||||
nread++; | |||||
/* found terminator? */ | |||||
if (s[nread-1] == '\n') | |||||
break; | |||||
} | |||||
} | |||||
s[nread] = '\0'; | |||||
return s; | |||||
} | |||||
/* Like perl chomp. */ | |||||
void chomp(char *s) | |||||
{ | |||||
int len = strlen(s); | |||||
/* do it twice to remove \r\n as well */ | |||||
if (len > 1 && (s[len - 1] == '\r' || s[len - 1] == '\n')) s[--len] = '\0'; | |||||
if (len > 1 && (s[len - 1] == '\r' || s[len - 1] == '\n')) s[--len] = '\0'; | |||||
} |
@@ -0,0 +1,34 @@ | |||||
/* | |||||
* Serial I/O helper routines | |||||
* | |||||
* Jim Paris <jim@jtan.com> | |||||
* $Id$ | |||||
*/ | |||||
#ifndef UTIL_H | |||||
#define UTIL_H | |||||
#include <unistd.h> | |||||
/* Open serial port in raw mode, with custom baudrate if necessary */ | |||||
int serial_open(const char *device, int rate); | |||||
/* Like read(), but restarts after EINTR, and reads until count bytes | |||||
are received or a timeout occurs. */ | |||||
int saferead_timeout(int fd, void *buf, size_t count, int timeout_ms); | |||||
/* Like write(), but restarts after EINTR */ | |||||
ssize_t safewrite(int fd, const void *buf, size_t count); | |||||
/* Read bytes until no more are available for 0.1 sec */ | |||||
int drain(int fd); | |||||
/* Like fprintf, but to a fd, using safewrite */ | |||||
int fdprintf(int fd, const char *fmt, ...); | |||||
/* Like fgets, but from a fd, using saferead_timeout. */ | |||||
char *fdgets(char *s, int size, int fd, int timeout_ms); | |||||
/* Like perl chomp. */ | |||||
void chomp(char *s); | |||||
#endif |