2019-02-11 20:12:09 -06:00
|
|
|
#include <stdlib.h>
|
|
|
|
#include <string.h>
|
2019-02-12 00:00:13 -06:00
|
|
|
#include <inttypes.h>
|
2019-02-11 20:12:09 -06:00
|
|
|
#include <unistd.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <net/if.h>
|
|
|
|
|
|
|
|
#include <hexagram/capture.h>
|
|
|
|
|
|
|
|
struct _hexagram_capture {
|
|
|
|
int fd;
|
|
|
|
uint32_t endian;
|
|
|
|
};
|
|
|
|
|
|
|
|
hexagram_capture *hexagram_capture_open_fd(int fd, int flags) {
|
|
|
|
hexagram_capture *capture;
|
|
|
|
hexagram_capture_header header;
|
|
|
|
|
|
|
|
if ((capture = malloc(sizeof(*capture))) == NULL) {
|
|
|
|
goto error_malloc;
|
|
|
|
}
|
|
|
|
|
2019-02-12 00:00:13 -06:00
|
|
|
if ((flags & O_WRONLY) && !(flags & O_APPEND)) {
|
2019-02-11 20:12:09 -06:00
|
|
|
memcpy(header.magic, HEXAGRAM_CAPTURE_MAGIC, strlen(HEXAGRAM_CAPTURE_MAGIC));
|
|
|
|
|
|
|
|
header.endian = HEXAGRAM_CAPTURE_ENDIAN;
|
|
|
|
|
|
|
|
if (write(fd, &header, sizeof(header)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
2019-02-12 00:00:13 -06:00
|
|
|
} else if (flags == O_RDONLY) {
|
2019-02-11 20:12:09 -06:00
|
|
|
ssize_t readlen;
|
|
|
|
|
|
|
|
if ((readlen = read(fd, &header, sizeof(header))) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (memcmp(header.magic, HEXAGRAM_CAPTURE_MAGIC, sizeof(header.magic)) != 0) {
|
|
|
|
goto error_invalid_format;
|
|
|
|
}
|
|
|
|
|
|
|
|
switch (header.endian) {
|
|
|
|
case HEXAGRAM_CAPTURE_ENDIAN:
|
|
|
|
case HEXAGRAM_CAPTURE_ENDIAN_SWAPPED:
|
|
|
|
break;
|
|
|
|
|
|
|
|
default:
|
|
|
|
goto error_invalid_format;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
capture->fd = fd;
|
|
|
|
capture->endian = header.endian;
|
|
|
|
|
|
|
|
return capture;
|
|
|
|
|
|
|
|
error_invalid_format:
|
|
|
|
error_io:
|
|
|
|
free(capture);
|
|
|
|
|
|
|
|
error_malloc:
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
hexagram_capture *hexagram_capture_open_file(const char *file, int flags) {
|
|
|
|
int fd = (flags & O_CREAT)?
|
|
|
|
open(file, flags, 0644):
|
|
|
|
open(file, flags);
|
|
|
|
|
|
|
|
if (fd < 0) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
|
|
|
return hexagram_capture_open_fd(fd, flags);
|
|
|
|
}
|
|
|
|
|
|
|
|
void hexagram_capture_destroy(hexagram_capture *capture) {
|
|
|
|
memset(capture, '\0', sizeof(*capture));
|
|
|
|
|
|
|
|
free(capture);
|
|
|
|
}
|
|
|
|
|
2019-02-12 00:00:13 -06:00
|
|
|
void hexagram_capture_close(hexagram_capture *capture) {
|
|
|
|
close(capture->fd);
|
|
|
|
|
|
|
|
hexagram_capture_destroy(capture);
|
|
|
|
}
|
|
|
|
|
|
|
|
ssize_t hexagram_capture_read(hexagram_capture *capture,
|
|
|
|
uint32_t *timestamp_hi,
|
|
|
|
uint32_t *timestamp_lo,
|
|
|
|
struct can_frame *frame) {
|
2019-02-11 20:12:09 -06:00
|
|
|
ssize_t len;
|
|
|
|
hexagram_capture_frame data;
|
|
|
|
|
|
|
|
if ((len = read(capture->fd, &data, sizeof(data))) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
} else if (len < sizeof(data)) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
2019-02-12 00:00:13 -06:00
|
|
|
if (timestamp_hi) *timestamp_hi = data.timestamp_hi;
|
|
|
|
if (timestamp_lo) *timestamp_lo = data.timestamp_lo;
|
2019-02-11 20:12:09 -06:00
|
|
|
|
|
|
|
memcpy(frame, &data.frame, sizeof(data.frame));
|
|
|
|
|
2019-02-12 00:00:13 -06:00
|
|
|
return len;
|
2019-02-11 20:12:09 -06:00
|
|
|
|
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
2019-02-12 00:00:13 -06:00
|
|
|
ssize_t hexagram_capture_write(hexagram_capture *capture,
|
|
|
|
struct can_frame *frame,
|
|
|
|
struct timeval *timestamp) {
|
2019-02-11 20:12:09 -06:00
|
|
|
hexagram_capture_frame data;
|
2019-02-12 00:00:13 -06:00
|
|
|
uint64_t usec;
|
2019-02-11 20:12:09 -06:00
|
|
|
|
|
|
|
if (timestamp == NULL) {
|
|
|
|
struct timeval now;
|
|
|
|
|
|
|
|
if (gettimeofday(&now, NULL) < 0) {
|
|
|
|
goto error_gettimeofday;
|
|
|
|
}
|
|
|
|
|
2019-02-12 00:00:13 -06:00
|
|
|
usec = now.tv_usec + now.tv_sec * 1000000;
|
2019-02-11 20:12:09 -06:00
|
|
|
} else {
|
2019-02-12 00:00:13 -06:00
|
|
|
usec = timestamp->tv_usec + timestamp->tv_sec * 1000000;
|
2019-02-11 20:12:09 -06:00
|
|
|
}
|
|
|
|
|
2019-02-12 00:00:13 -06:00
|
|
|
data.timestamp_hi = usec & 0xffffffff00000000 >> 32;
|
|
|
|
data.timestamp_lo = usec & 0x00000000ffffffff;
|
|
|
|
|
2019-02-11 20:12:09 -06:00
|
|
|
memcpy(&data.frame, frame, sizeof(data.frame));
|
|
|
|
|
|
|
|
return write(capture->fd, &data, sizeof(data));
|
|
|
|
|
|
|
|
error_gettimeofday:
|
|
|
|
return -1;
|
|
|
|
}
|
2019-02-12 20:55:40 -06:00
|
|
|
|
|
|
|
int hexagram_capture_replay(hexagram_capture *capture,
|
|
|
|
hexagram_can_if *can_if,
|
|
|
|
float speed) {
|
|
|
|
ssize_t len;
|
|
|
|
|
|
|
|
uint32_t timestamp[2],
|
|
|
|
usec_last = 0;
|
|
|
|
|
|
|
|
struct can_frame frame;
|
|
|
|
|
|
|
|
while (1) {
|
|
|
|
if ((len = hexagram_capture_read(capture,
|
|
|
|
×tamp[0],
|
|
|
|
×tamp[1],
|
|
|
|
&frame)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
} else if (len == 0) {
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (usec_last) {
|
|
|
|
usleep(speed * (useconds_t)(timestamp[1] - usec_last));
|
|
|
|
}
|
|
|
|
|
|
|
|
if (write(can_if->sock, &frame, sizeof(struct can_frame)) < 0) {
|
|
|
|
goto error_io;
|
|
|
|
}
|
|
|
|
|
|
|
|
usec_last = timestamp[1];
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
|
|
|
error_io:
|
|
|
|
return -1;
|
|
|
|
}
|