mirror of
https://github.com/linux-can/can-utils.git
synced 2026-09-21 15:29:56 +02:00
Compare commits
37
Commits
fc53b4e8d2
...
master
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
cbbad5eede | ||
|
|
95aae6bf83 | ||
|
|
bf5fe736c3 | ||
|
|
14245b7c79 | ||
|
|
90383a0cca | ||
|
|
d5cb91c8ea | ||
|
|
9743a2ffcf | ||
|
|
d5ed23583c | ||
|
|
60301896d1 | ||
|
|
99ab67143a | ||
|
|
a0aeaed234 | ||
|
|
3cae8a449b | ||
|
|
44e6eb45e3 | ||
|
|
9e444073b1 | ||
|
|
9d4f3c82a2 | ||
|
|
7e8e247b2f | ||
|
|
3fe1c42bbf | ||
|
|
1520ab5b98 | ||
|
|
aa902ae2af | ||
|
|
a0b592178e | ||
|
|
4f2fdecfba | ||
|
|
cbbe4b41ea | ||
|
|
2da0c7e95e | ||
|
|
1f038b3cd8 | ||
|
|
392ccc970b | ||
|
|
7939678070 | ||
|
|
88a0417a6b | ||
|
|
65e715d56d | ||
|
|
374fecde09 | ||
|
|
bfbf0c851f | ||
|
|
ed7822c9a2 | ||
|
|
e9ea9d1168 | ||
|
|
2d793d38d2 | ||
|
|
340a3b8c92 | ||
|
|
8838ce80fc | ||
|
|
d6c57240ed | ||
|
|
3e0e6ae3a4 |
@@ -75,7 +75,6 @@ jobs:
|
|||||||
gcc \
|
gcc \
|
||||||
gcc-aarch64-linux-gnu \
|
gcc-aarch64-linux-gnu \
|
||||||
gcc-arm-linux-gnueabihf \
|
gcc-arm-linux-gnueabihf \
|
||||||
gcc-mips-linux-gnu \
|
|
||||||
libgps-dev \
|
libgps-dev \
|
||||||
make
|
make
|
||||||
|
|
||||||
@@ -139,13 +138,6 @@ jobs:
|
|||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=${gps} -B build-${toolchain}
|
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -DENABLE_GPS=${gps} -B build-${toolchain}
|
||||||
podman exec -i stable cmake --build build-${toolchain}
|
podman exec -i stable cmake --build build-${toolchain}
|
||||||
|
|
||||||
- name: Configure & Build with mips-linux-gnu-gcc
|
|
||||||
env:
|
|
||||||
toolchain: mips-linux-gnu-gcc
|
|
||||||
run: |
|
|
||||||
podman exec -i stable cmake -DCMAKE_BUILD_TYPE=Debug -DCMAKE_TOOLCHAIN_FILE=cmake/${toolchain}.cmake -DENABLE_WERROR=ON -B build-${toolchain}
|
|
||||||
podman exec -i stable cmake --build build-${toolchain}
|
|
||||||
|
|
||||||
- name: Configure & Build with gcc (Makefile)
|
- name: Configure & Build with gcc (Makefile)
|
||||||
env:
|
env:
|
||||||
cc: gcc
|
cc: gcc
|
||||||
|
|||||||
+1
-1
@@ -1,4 +1,4 @@
|
|||||||
cmake_minimum_required(VERSION 3.5)
|
cmake_minimum_required(VERSION 3.5...3.10)
|
||||||
|
|
||||||
project(can-utils LANGUAGES C)
|
project(can-utils LANGUAGES C)
|
||||||
|
|
||||||
|
|||||||
@@ -84,7 +84,7 @@ static void print_usage(char *prg)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void prframe(FILE *file, struct timeval *tv, int dev,
|
static void prframe(FILE *file, struct timeval *tv, int dev,
|
||||||
cu_t *cf, char dir)
|
union cfu *cf, char dir)
|
||||||
{
|
{
|
||||||
static char abuf[BUFLEN];
|
static char abuf[BUFLEN];
|
||||||
|
|
||||||
@@ -177,7 +177,7 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
cf.len = CAN_ERR_DLC;
|
cf.len = CAN_ERR_DLC;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, (cu_t *)&cf, NO_DIR);
|
prframe(outfile, &tv, interface, (union cfu *)&cf, NO_DIR);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -249,7 +249,7 @@ static void eval_can(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
cf.data[i] = data[i] & 0xFFU;
|
cf.data[i] = data[i] & 0xFFU;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -374,7 +374,7 @@ static void eval_canfd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
}
|
}
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
|
|
||||||
/* No support for really strange CANFD ErrorFrames format m( */
|
/* No support for really strange CANFD ErrorFrames format m( */
|
||||||
@@ -487,7 +487,7 @@ static void eval_canxl_cc(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
cf.len8_dlc = dlc;
|
cf.len8_dlc = dlc;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -584,7 +584,7 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
if (!(flags & ASC_F_FDF))
|
if (!(flags & ASC_F_FDF))
|
||||||
return;
|
return;
|
||||||
|
|
||||||
cf.flags = CANFD_FDF;
|
cf.flags = CANFD_FDF;
|
||||||
|
|
||||||
@@ -594,7 +594,7 @@ static void eval_canxl_fd(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
cf.flags |= CANFD_ESI;
|
cf.flags |= CANFD_ESI;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -723,7 +723,7 @@ static void eval_canxl_xl(char* buf, struct timeval *date_tvp, char timestamps,
|
|||||||
cf.flags |= CANXL_RRS;
|
cf.flags |= CANXL_RRS;
|
||||||
|
|
||||||
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
calc_tv(&tv, &read_tv, date_tvp, timestamps, dplace);
|
||||||
prframe(outfile, &tv, interface, (cu_t *)&cf, dir[0]);
|
prframe(outfile, &tv, interface, (union cfu *)&cf, dir[0]);
|
||||||
fflush(outfile);
|
fflush(outfile);
|
||||||
|
|
||||||
/* No support for CAN XL ErrorFrames */
|
/* No support for CAN XL ErrorFrames */
|
||||||
|
|||||||
+29
-9
@@ -153,7 +153,7 @@ int main(void)
|
|||||||
|
|
||||||
char buf[MAXLEN];
|
char buf[MAXLEN];
|
||||||
char format[FORMATSZ];
|
char format[FORMATSZ];
|
||||||
char rxmsg[50];
|
char rxmsg[64];
|
||||||
|
|
||||||
#pragma GCC diagnostic push
|
#pragma GCC diagnostic push
|
||||||
#pragma GCC diagnostic ignored "-Wpragmas"
|
#pragma GCC diagnostic ignored "-Wpragmas"
|
||||||
@@ -234,7 +234,7 @@ int main(void)
|
|||||||
}
|
}
|
||||||
|
|
||||||
while (1) {
|
while (1) {
|
||||||
|
again:
|
||||||
FD_ZERO(&readfds);
|
FD_ZERO(&readfds);
|
||||||
FD_SET(sc, &readfds);
|
FD_SET(sc, &readfds);
|
||||||
FD_SET(sa, &readfds);
|
FD_SET(sa, &readfds);
|
||||||
@@ -242,6 +242,8 @@ int main(void)
|
|||||||
select((sc > sa)?sc+1:sa+1, &readfds, NULL, NULL, NULL);
|
select((sc > sa)?sc+1:sa+1, &readfds, NULL, NULL, NULL);
|
||||||
|
|
||||||
if (FD_ISSET(sc, &readfds)) {
|
if (FD_ISSET(sc, &readfds)) {
|
||||||
|
size_t size = sizeof(rxmsg);
|
||||||
|
int len = 0, res;
|
||||||
|
|
||||||
recvfrom(sc, &msg, sizeof(msg), 0,
|
recvfrom(sc, &msg, sizeof(msg), 0,
|
||||||
(struct sockaddr*)&caddr, &caddrlen);
|
(struct sockaddr*)&caddr, &caddrlen);
|
||||||
@@ -249,17 +251,35 @@ int main(void)
|
|||||||
ifr.ifr_ifindex = caddr.can_ifindex;
|
ifr.ifr_ifindex = caddr.can_ifindex;
|
||||||
ioctl(sc, SIOCGIFNAME, &ifr);
|
ioctl(sc, SIOCGIFNAME, &ifr);
|
||||||
|
|
||||||
sprintf(rxmsg, "< %s %03X %d ", ifr.ifr_name,
|
res = snprintf(rxmsg, size, "< %s %03X %d ", ifr.ifr_name,
|
||||||
msg.msg_head.can_id, msg.frame.can_dlc);
|
msg.msg_head.can_id, msg.frame.can_dlc);
|
||||||
|
if (res < 0 || (size_t)res >= size) {
|
||||||
|
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
for ( i = 0; i < msg.frame.can_dlc; i++)
|
len += res;
|
||||||
sprintf(rxmsg + strlen(rxmsg), "%02X ",
|
|
||||||
msg.frame.data[i]);
|
for (i = 0; i < msg.frame.can_dlc; i++) {
|
||||||
|
res = snprintf(rxmsg + len, size - len, "%02X ", msg.frame.data[i]);
|
||||||
|
if (res < 0 || (size_t)res >= (size - len)) {
|
||||||
|
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
|
||||||
|
goto again;
|
||||||
|
}
|
||||||
|
|
||||||
|
len += res;
|
||||||
|
}
|
||||||
|
|
||||||
/* delimiter '\0' for Adobe(TM) Flash(TM) XML sockets */
|
/* delimiter '\0' for Adobe(TM) Flash(TM) XML sockets */
|
||||||
strcat(rxmsg, ">\0");
|
res = snprintf(rxmsg + len, size - len, ">");
|
||||||
|
if (res < 0 || (size_t)res >= (size - len)) {
|
||||||
|
printf("Error: rxmsg buffer (size %zu) too small for data.\n", size);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
send(sa, rxmsg, strlen(rxmsg) + 1, 0);
|
len += res;
|
||||||
|
|
||||||
|
send(sa, rxmsg, len + 1, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -72,6 +72,9 @@
|
|||||||
#ifndef SO_TIMESTAMPING
|
#ifndef SO_TIMESTAMPING
|
||||||
#define SO_TIMESTAMPING 37
|
#define SO_TIMESTAMPING 37
|
||||||
#endif
|
#endif
|
||||||
|
#ifndef SCM_TIMESTAMPING
|
||||||
|
#define SCM_TIMESTAMPING SO_TIMESTAMPING
|
||||||
|
#endif
|
||||||
|
|
||||||
#define TIMESTAMPSZ 50 /* string 'absolute with date' requires max 49 bytes */
|
#define TIMESTAMPSZ 50 /* string 'absolute with date' requires max 49 bytes */
|
||||||
|
|
||||||
@@ -113,7 +116,8 @@ static const int canfx_on = 1;
|
|||||||
|
|
||||||
#define MAXANI 4
|
#define MAXANI 4
|
||||||
static const char anichar[MAXANI] = { '|', '/', '-', '\\' };
|
static const char anichar[MAXANI] = { '|', '/', '-', '\\' };
|
||||||
static const char extra_m_info[4][4] = { "- -", "B -", "- E", "B E" };
|
static const char extra_fd_info[4][4] = { "- -", "B -", "- E", "B E" };
|
||||||
|
static const char extra_xl_info[4][4] = { "- -", "S -", "- R", "S R" };
|
||||||
|
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
|
|
||||||
@@ -143,7 +147,7 @@ static void print_usage(void)
|
|||||||
fprintf(stderr, " -d (monitor dropped CAN frames)\n");
|
fprintf(stderr, " -d (monitor dropped CAN frames)\n");
|
||||||
fprintf(stderr, " -e (dump CAN error frames in human-readable format)\n");
|
fprintf(stderr, " -e (dump CAN error frames in human-readable format)\n");
|
||||||
fprintf(stderr, " -8 (display raw DLC values in {} for Classical CAN)\n");
|
fprintf(stderr, " -8 (display raw DLC values in {} for Classical CAN)\n");
|
||||||
fprintf(stderr, " -x (print extra message infos, rx/tx brs esi)\n");
|
fprintf(stderr, " -x (print extra message infos, rx/tx [brs esi|sec rrs])\n");
|
||||||
fprintf(stderr, " -T <msecs> (terminate after <msecs> if no frames were received)\n");
|
fprintf(stderr, " -T <msecs> (terminate after <msecs> if no frames were received)\n");
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
fprintf(stderr, "Up to %d CAN interfaces with optional filter sets can be specified\n", MAXSOCK);
|
||||||
@@ -338,7 +342,7 @@ int main(int argc, char **argv)
|
|||||||
struct cmsghdr *cmsg;
|
struct cmsghdr *cmsg;
|
||||||
struct can_filter *rfilter;
|
struct can_filter *rfilter;
|
||||||
can_err_mask_t err_mask;
|
can_err_mask_t err_mask;
|
||||||
static cu_t cu; /* union for CAN CC/FD/XL frames */
|
static union cfu cu; /* union for CAN CC/FD/XL frames */
|
||||||
int nbytes, i;
|
int nbytes, i;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct timespec ts, last_ts;
|
struct timespec ts, last_ts;
|
||||||
@@ -711,12 +715,12 @@ int main(int argc, char **argv)
|
|||||||
localtime_r(&currtime, &now);
|
localtime_r(&currtime, &now);
|
||||||
|
|
||||||
snprintf(fname, sizeof(fname), "candump-%04d-%02d-%02d_%02d%02d%02d.log",
|
snprintf(fname, sizeof(fname), "candump-%04d-%02d-%02d_%02d%02d%02d.log",
|
||||||
now.tm_year + 1900,
|
now.tm_year + 1900,
|
||||||
now.tm_mon + 1,
|
now.tm_mon + 1,
|
||||||
now.tm_mday,
|
now.tm_mday,
|
||||||
now.tm_hour,
|
now.tm_hour,
|
||||||
now.tm_min,
|
now.tm_min,
|
||||||
now.tm_sec);
|
now.tm_sec);
|
||||||
|
|
||||||
logname = fname;
|
logname = fname;
|
||||||
}
|
}
|
||||||
@@ -806,13 +810,13 @@ int main(int argc, char **argv)
|
|||||||
for (cmsg = CMSG_FIRSTHDR(&msg);
|
for (cmsg = CMSG_FIRSTHDR(&msg);
|
||||||
cmsg && (cmsg->cmsg_level == SOL_SOCKET);
|
cmsg && (cmsg->cmsg_level == SOL_SOCKET);
|
||||||
cmsg = CMSG_NXTHDR(&msg,cmsg)) {
|
cmsg = CMSG_NXTHDR(&msg,cmsg)) {
|
||||||
if (cmsg->cmsg_type == SO_TIMESTAMP) {
|
if (cmsg->cmsg_type == SCM_TIMESTAMP) {
|
||||||
struct timeval tv;
|
struct timeval tv;
|
||||||
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
|
memcpy(&tv, CMSG_DATA(cmsg), sizeof(tv));
|
||||||
ts.tv_sec = tv.tv_sec;
|
ts.tv_sec = tv.tv_sec;
|
||||||
ts.tv_nsec = tv.tv_usec;
|
ts.tv_nsec = tv.tv_usec;
|
||||||
ts.tv_nsec *= 1000;
|
ts.tv_nsec *= 1000;
|
||||||
} else if (cmsg->cmsg_type == SO_TIMESTAMPING) {
|
} else if (cmsg->cmsg_type == SCM_TIMESTAMPING) {
|
||||||
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
|
struct timespec *stamp = (struct timespec *)CMSG_DATA(cmsg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@@ -887,16 +891,21 @@ int main(int argc, char **argv)
|
|||||||
alen = sprintf(afrbuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : "");
|
alen = sprintf(afrbuf, " %s", (color > 2) ? col_on[idx % MAXCOL] : "");
|
||||||
alen += sprint_timestamp(afrbuf + alen, timestamp, use_ns, &ts, &last_ts);
|
alen += sprint_timestamp(afrbuf + alen, timestamp, use_ns, &ts, &last_ts);
|
||||||
alen += sprintf(afrbuf + alen, " %s%*s",
|
alen += sprintf(afrbuf + alen, " %s%*s",
|
||||||
(color && (color < 3)) ? col_on[idx % MAXCOL] : "",
|
(color && (color < 3)) ? col_on[idx % MAXCOL] : "",
|
||||||
max_devname_len, devname[idx]);
|
max_devname_len, devname[idx]);
|
||||||
|
|
||||||
if (extra_msg_info) {
|
if (extra_msg_info) {
|
||||||
if (msg.msg_flags & MSG_DONTROUTE)
|
if (msg.msg_flags & MSG_DONTROUTE)
|
||||||
alen += sprintf(afrbuf + alen, " TX %s",
|
alen += sprintf(afrbuf + alen, " TX");
|
||||||
extra_m_info[cu.fd.flags & 3]);
|
|
||||||
else
|
else
|
||||||
alen += sprintf(afrbuf + alen, " RX %s",
|
alen += sprintf(afrbuf + alen, " RX");
|
||||||
extra_m_info[cu.fd.flags & 3]);
|
|
||||||
|
if (cu.xl.flags & CANXL_XLF)
|
||||||
|
alen += sprintf(afrbuf + alen, " %s",
|
||||||
|
extra_xl_info[cu.xl.flags & 3]);
|
||||||
|
else
|
||||||
|
alen += sprintf(afrbuf + alen, " %s",
|
||||||
|
extra_fd_info[cu.fd.flags & 3]);
|
||||||
}
|
}
|
||||||
|
|
||||||
alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : "");
|
alen += sprintf(afrbuf + alen, "%s ", (color == 1) ? col_off : "");
|
||||||
|
|||||||
+18
-19
@@ -25,6 +25,7 @@
|
|||||||
#include <linux/can/error.h>
|
#include <linux/can/error.h>
|
||||||
#include <linux/can/raw.h>
|
#include <linux/can/raw.h>
|
||||||
#include <net/if.h>
|
#include <net/if.h>
|
||||||
|
#include <stdarg.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
#include <stdint.h>
|
#include <stdint.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
@@ -122,27 +123,25 @@ void show_help_and_exit()
|
|||||||
exit(EXIT_SUCCESS);
|
exit(EXIT_SUCCESS);
|
||||||
}
|
}
|
||||||
|
|
||||||
void err_exit(const char *msg)
|
void __attribute__((format (printf, 1, 2))) err_exit(const char *format, ...)
|
||||||
{
|
{
|
||||||
printf("%s", msg);
|
va_list ap;
|
||||||
exit(EXIT_FAILURE);
|
|
||||||
}
|
|
||||||
|
|
||||||
void show_custom_format_and_exit(const char *param, const char *format)
|
va_start(ap, format);
|
||||||
{
|
vfprintf(stdout, format, ap);
|
||||||
char str_buf[80];
|
va_end(ap);
|
||||||
sprintf(str_buf, format, param);
|
|
||||||
err_exit(str_buf);
|
exit(EXIT_FAILURE);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_invalid_option(const char *option)
|
void show_invalid_option(const char *option)
|
||||||
{
|
{
|
||||||
show_custom_format_and_exit(option, "Error: Invalid option %s\n");
|
err_exit("Error: Invalid option %s\n", option);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_err_and_exit(const char *err_type)
|
void show_err_and_exit(const char *err_type)
|
||||||
{
|
{
|
||||||
show_custom_format_and_exit(err_type, "Error: You can only have one %s parameter!\n");
|
err_exit("Error: You can only have one %s parameter!\n", err_type);
|
||||||
}
|
}
|
||||||
|
|
||||||
void show_loc_err_and_exit()
|
void show_loc_err_and_exit()
|
||||||
@@ -176,7 +175,6 @@ int main(int argc, char *argv[])
|
|||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
struct can_frame frame;
|
struct can_frame frame;
|
||||||
bool show_bits = false, location_processed = false, transceiver_processed = false, arbitration_processed = false;
|
bool show_bits = false, location_processed = false, transceiver_processed = false, arbitration_processed = false;
|
||||||
char tmp_str[256];
|
|
||||||
|
|
||||||
printf("CAN Sockets Error Messages Simulator\n");
|
printf("CAN Sockets Error Messages Simulator\n");
|
||||||
if (argc < 3)
|
if (argc < 3)
|
||||||
@@ -537,24 +535,25 @@ int main(int argc, char *argv[])
|
|||||||
|
|
||||||
// create socket
|
// create socket
|
||||||
if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
|
if ((sock = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0)
|
||||||
err_exit("Error while opening socket");
|
err_exit("Error while opening socket\n");
|
||||||
|
|
||||||
// set interface name
|
// set interface name
|
||||||
|
if (strlen(argv[1]) >= IFNAMSIZ)
|
||||||
|
err_exit("Name of CAN device '%s' is too long!\n\n", argv[1]);
|
||||||
|
|
||||||
strcpy(ifr.ifr_name, argv[1]); // can0, vcan0...
|
strcpy(ifr.ifr_name, argv[1]); // can0, vcan0...
|
||||||
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0) {
|
if (ioctl(sock, SIOCGIFINDEX, &ifr) < 0)
|
||||||
sprintf(tmp_str, "Error setting CAN interface name %s", argv[1]);
|
err_exit("Error setting CAN interface name %s\n", argv[1]);
|
||||||
err_exit(tmp_str);
|
|
||||||
}
|
|
||||||
|
|
||||||
// bind socket to the CAN interface
|
// bind socket to the CAN interface
|
||||||
addr.can_family = AF_CAN;
|
addr.can_family = AF_CAN;
|
||||||
addr.can_ifindex = ifr.ifr_ifindex;
|
addr.can_ifindex = ifr.ifr_ifindex;
|
||||||
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0)
|
||||||
err_exit("Error in socket bind");
|
err_exit("Error in socket bind\n");
|
||||||
|
|
||||||
// Send CAN error frame
|
// Send CAN error frame
|
||||||
if (write(sock, &frame, sizeof(frame)) < 0)
|
if (write(sock, &frame, sizeof(frame)) < 0)
|
||||||
err_exit("Error writing to socket");
|
err_exit("Error writing to socket\n");
|
||||||
else
|
else
|
||||||
printf("CAN error frame sent\n");
|
printf("CAN error frame sent\n");
|
||||||
|
|
||||||
|
|||||||
@@ -180,7 +180,7 @@ static void print_usage(char *prg)
|
|||||||
fprintf(stderr, " -X (generate CAN XL CAN frames)\n");
|
fprintf(stderr, " -X (generate CAN XL CAN frames)\n");
|
||||||
fprintf(stderr, " -R (generate RTR frames)\n");
|
fprintf(stderr, " -R (generate RTR frames)\n");
|
||||||
fprintf(stderr, " -8 (allow DLC values greater then 8 for Classic CAN frames)\n");
|
fprintf(stderr, " -8 (allow DLC values greater then 8 for Classic CAN frames)\n");
|
||||||
fprintf(stderr, " -m (mix -e -f -b -E -R -X frames)\n");
|
fprintf(stderr, " -m (mix CC [-e -R] FD [-f -b -E] XL [-X] on capable devices)\n");
|
||||||
fprintf(stderr, " -I <mode> (CAN ID generation mode - see below)\n");
|
fprintf(stderr, " -I <mode> (CAN ID generation mode - see below)\n");
|
||||||
fprintf(stderr, " -L <mode> (CAN data length code (dlc) generation mode - see below)\n");
|
fprintf(stderr, " -L <mode> (CAN data length code (dlc) generation mode - see below)\n");
|
||||||
fprintf(stderr, " -D <mode> (CAN data (payload) generation mode - see below)\n");
|
fprintf(stderr, " -D <mode> (CAN data (payload) generation mode - see below)\n");
|
||||||
@@ -299,7 +299,7 @@ static int setsockopt_txtime(int fd)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_send_one(int fd, cu_t *cu, size_t len, int timeout)
|
static int do_send_one(int fd, union cfu *cu, size_t len, int timeout)
|
||||||
{
|
{
|
||||||
uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 };
|
uint8_t control[CMSG_SPACE(sizeof(uint64_t))] = { 0 };
|
||||||
struct iovec iov = {
|
struct iovec iov = {
|
||||||
@@ -339,10 +339,9 @@ resend:
|
|||||||
nbytes = sendmsg(fd, &msg, 0);
|
nbytes = sendmsg(fd, &msg, 0);
|
||||||
if (nbytes < 0) {
|
if (nbytes < 0) {
|
||||||
ret = -errno;
|
ret = -errno;
|
||||||
if (ret != -ENOBUFS) {
|
if (ret != -ENOBUFS)
|
||||||
perror("write");
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
|
||||||
if (!ignore_enobufs && !timeout) {
|
if (!ignore_enobufs && !timeout) {
|
||||||
perror("write");
|
perror("write");
|
||||||
return ret;
|
return ret;
|
||||||
@@ -455,6 +454,9 @@ int main(int argc, char **argv)
|
|||||||
unsigned char extended = 0;
|
unsigned char extended = 0;
|
||||||
unsigned char canfd = 0;
|
unsigned char canfd = 0;
|
||||||
unsigned char canxl = 0;
|
unsigned char canxl = 0;
|
||||||
|
unsigned char mixcc = 1; /* mix default */
|
||||||
|
unsigned char mixfd = 1; /* mix default */
|
||||||
|
unsigned char mixxl = 1; /* mix default */
|
||||||
unsigned char brs = 0;
|
unsigned char brs = 0;
|
||||||
unsigned char esi = 0;
|
unsigned char esi = 0;
|
||||||
unsigned char mix = 0;
|
unsigned char mix = 0;
|
||||||
@@ -492,7 +494,7 @@ int main(int argc, char **argv)
|
|||||||
struct can_raw_vcid_options vcid_opts = {
|
struct can_raw_vcid_options vcid_opts = {
|
||||||
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
||||||
};
|
};
|
||||||
static cu_t cu;
|
static union cfu cu;
|
||||||
int i;
|
int i;
|
||||||
struct ifreq ifr = { 0 };
|
struct ifreq ifr = { 0 };
|
||||||
const int enable_canfx = 1;
|
const int enable_canfx = 1;
|
||||||
@@ -574,7 +576,6 @@ int main(int argc, char **argv)
|
|||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
mix = 1;
|
mix = 1;
|
||||||
canfd = 1; /* to switch the socket into CAN FD mode */
|
|
||||||
view |= CANLIB_VIEW_INDENT_SFF;
|
view |= CANLIB_VIEW_INDENT_SFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -777,14 +778,58 @@ int main(int argc, char **argv)
|
|||||||
&loopback, sizeof(loopback));
|
&loopback, sizeof(loopback));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canfd || canxl) {
|
/* get CAN netdevice MTU for frame type capabilities */
|
||||||
|
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
|
||||||
|
perror("SIOCGIFMTU");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
/* check if the frame fits into the CAN netdevice */
|
/* check CAN XL support */
|
||||||
if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
|
if (ifr.ifr_mtu < (int)CANXL_MIN_MTU) {
|
||||||
perror("SIOCGIFMTU");
|
mixxl = 0;
|
||||||
|
if (canxl) {
|
||||||
|
printf("CAN interface not CAN XL capable - sorry.\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* check CAN FD support */
|
||||||
|
if (ifr.ifr_mtu < (int)CANFD_MTU) {
|
||||||
|
mixfd = 0;
|
||||||
|
if (canfd) {
|
||||||
|
printf("CAN interface not CAN FD capable - sorry.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable CAN FD on the socket */
|
||||||
|
if (mixfd) {
|
||||||
|
/* interface is ok - try to switch the socket into CAN FD mode */
|
||||||
|
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
|
||||||
|
&enable_canfx, sizeof(enable_canfx))){
|
||||||
|
printf("error when enabling CAN FD support\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* enable CAN XL on the socket */
|
||||||
|
if (mixxl) {
|
||||||
|
/* interface is ok - try to switch the socket into CAN XL mode */
|
||||||
|
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES,
|
||||||
|
&enable_canfx, sizeof(enable_canfx))){
|
||||||
|
printf("error when enabling CAN XL support\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
/* try to enable the CAN XL VCID pass through mode */
|
||||||
|
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS,
|
||||||
|
&vcid_opts, sizeof(vcid_opts))) {
|
||||||
|
printf("error when enabling CAN XL VCID pass through\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* sanitize given values */
|
||||||
|
if (canfd || canxl) {
|
||||||
if (canfd) {
|
if (canfd) {
|
||||||
/* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */
|
/* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64 */
|
||||||
cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len));
|
cu.fd.len = can_fd_dlc2len(can_fd_len2dlc(cu.fd.len));
|
||||||
@@ -793,41 +838,6 @@ int main(int argc, char **argv)
|
|||||||
if (cu.fd.len > CANFD_MAX_DLEN)
|
if (cu.fd.len > CANFD_MAX_DLEN)
|
||||||
cu.fd.len = CANFD_MAX_DLEN;
|
cu.fd.len = CANFD_MAX_DLEN;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (canxl && (ifr.ifr_mtu < (int)CANXL_MIN_MTU)) {
|
|
||||||
printf("CAN interface not CAN XL capable - sorry.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (canfd && (ifr.ifr_mtu < (int)CANFD_MTU)) {
|
|
||||||
printf("CAN interface not CAN FD capable - sorry.\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifr.ifr_mtu == (int)CANFD_MTU) {
|
|
||||||
/* interface is ok - try to switch the socket into CAN FD mode */
|
|
||||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
|
|
||||||
&enable_canfx, sizeof(enable_canfx))){
|
|
||||||
printf("error when enabling CAN FD support\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if (ifr.ifr_mtu >= (int)CANXL_MIN_MTU) {
|
|
||||||
/* interface is ok - try to switch the socket into CAN XL mode */
|
|
||||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_FRAMES,
|
|
||||||
&enable_canfx, sizeof(enable_canfx))){
|
|
||||||
printf("error when enabling CAN XL support\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
/* try to enable the CAN XL VCID pass through mode */
|
|
||||||
if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_XL_VCID_OPTS,
|
|
||||||
&vcid_opts, sizeof(vcid_opts))) {
|
|
||||||
printf("error when enabling CAN XL VCID pass through\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
/* sanitize Classical CAN 2.0 frame length */
|
/* sanitize Classical CAN 2.0 frame length */
|
||||||
if (len8_dlc) {
|
if (len8_dlc) {
|
||||||
@@ -1040,8 +1050,31 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
ret = do_send_one(s, &cu, mtu, polltimeout);
|
ret = do_send_one(s, &cu, mtu, polltimeout);
|
||||||
if (ret)
|
if ((ret == -EINVAL) && mix) {
|
||||||
|
/* mix mode: disable unsupported CAN frame type */
|
||||||
|
switch (mtu) {
|
||||||
|
case CAN_MTU:
|
||||||
|
mixcc = 0;
|
||||||
|
break;
|
||||||
|
case CANFD_MTU:
|
||||||
|
mixfd = 0;
|
||||||
|
break;
|
||||||
|
case CANXL_MTU:
|
||||||
|
mixxl = 0;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
printf ("mix mode: unknown MTU");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (!mixcc && !mixfd && !mixxl) {
|
||||||
|
printf ("mix mode: no valid CAN frame types\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
} else if (ret) {
|
||||||
|
/* other error than -ENOBUFS and -EINVAL */
|
||||||
|
perror("write");
|
||||||
return 1;
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
if (burst_sent_count >= burst_count)
|
if (burst_sent_count >= burst_count)
|
||||||
burst_sent_count = 0;
|
burst_sent_count = 0;
|
||||||
@@ -1082,18 +1115,41 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (mix) {
|
if (mix) {
|
||||||
|
canfd = 0;
|
||||||
|
canxl = 0;
|
||||||
i = random();
|
i = random();
|
||||||
extended = i & 1;
|
extended = i & 1;
|
||||||
canfd = i & 2;
|
if (mixfd) {
|
||||||
if (canfd) {
|
canfd = i & 2;
|
||||||
brs = i & 4;
|
if (canfd) {
|
||||||
esi = i & 8;
|
brs = i & 4;
|
||||||
|
esi = i & 8;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (mixxl) {
|
||||||
|
if (mixfd)
|
||||||
|
canxl = ((i & 96) == 96); /* 1/4 */
|
||||||
|
else
|
||||||
|
canxl = ((i & 32) == 32); /* 1/2 */
|
||||||
|
}
|
||||||
|
if (mixcc) {
|
||||||
|
rtr_frame = ((i & 24) == 24); /* reduce RTR to 1/4 */
|
||||||
|
} else {
|
||||||
|
/* no CC frames allowed - CAN XL-only mode? */
|
||||||
|
if (!canxl && !canfd) {
|
||||||
|
/* force XL or FD frames */
|
||||||
|
if (mixxl)
|
||||||
|
canxl = 1;
|
||||||
|
else if (mixfd) {
|
||||||
|
canfd = 1;
|
||||||
|
brs = i & 4;
|
||||||
|
esi = i & 8;
|
||||||
|
} else {
|
||||||
|
printf ("mix mode: no valid CAN frame types\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
/* generate CAN XL traffic if the interface is capable */
|
|
||||||
if (ifr.ifr_mtu >= (int)CANXL_MIN_MTU)
|
|
||||||
canxl = ((i & 96) == 96);
|
|
||||||
|
|
||||||
rtr_frame = ((i & 24) == 24); /* reduce RTR frames to 1/4 */
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+28
-6
@@ -177,7 +177,8 @@ int main(int argc, char **argv)
|
|||||||
sigset_t sigset;
|
sigset_t sigset;
|
||||||
fd_set rdfs;
|
fd_set rdfs;
|
||||||
int s[MAXDEV];
|
int s[MAXDEV];
|
||||||
int socki, accsocket;
|
int socki;
|
||||||
|
int accsocket = -1;
|
||||||
canid_t mask[MAXDEV] = {0};
|
canid_t mask[MAXDEV] = {0};
|
||||||
canid_t value[MAXDEV] = {0};
|
canid_t value[MAXDEV] = {0};
|
||||||
int inv_filter[MAXDEV] = {0};
|
int inv_filter[MAXDEV] = {0};
|
||||||
@@ -191,7 +192,7 @@ int main(int argc, char **argv)
|
|||||||
.rx_vcid_mask = 0,
|
.rx_vcid_mask = 0,
|
||||||
};
|
};
|
||||||
struct can_filter rfilter;
|
struct can_filter rfilter;
|
||||||
static cu_t cu; /* union for CAN CC/FD/XL frames */
|
static union cfu cu; /* union for CAN CC/FD/XL frames */
|
||||||
const int canfx_on = 1;
|
const int canfx_on = 1;
|
||||||
int nbytes, i, j;
|
int nbytes, i, j;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
@@ -286,7 +287,7 @@ int main(int argc, char **argv)
|
|||||||
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
inaddr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
inaddr.sin_port = htons(port);
|
inaddr.sin_port = htons(port);
|
||||||
|
|
||||||
while(bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
while(running && bind(socki, (struct sockaddr*)&inaddr, sizeof(inaddr)) < 0) {
|
||||||
struct timespec f = {
|
struct timespec f = {
|
||||||
.tv_nsec = 100 * 1000 * 1000,
|
.tv_nsec = 100 * 1000 * 1000,
|
||||||
};
|
};
|
||||||
@@ -295,18 +296,28 @@ int main(int argc, char **argv)
|
|||||||
nanosleep(&f, NULL);
|
nanosleep(&f, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if loop exited due to signal (during nanosleep) rather than
|
||||||
|
* successful bind.
|
||||||
|
*/
|
||||||
|
if (!running) {
|
||||||
|
close(socki);
|
||||||
|
return 128 + signal_num;
|
||||||
|
}
|
||||||
|
|
||||||
if (listen(socki, 3) != 0) {
|
if (listen(socki, 3) != 0) {
|
||||||
perror("listen");
|
perror("listen");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
while(1) {
|
while(running) {
|
||||||
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
|
accsocket = accept(socki, (struct sockaddr*)&clientaddr, &sin_size);
|
||||||
if (accsocket > 0) {
|
if (accsocket > 0) {
|
||||||
//printf("accepted\n");
|
//printf("accepted\n");
|
||||||
if (!fork())
|
if (!fork())
|
||||||
break;
|
break;
|
||||||
close(accsocket);
|
close(accsocket);
|
||||||
|
accsocket = -1;
|
||||||
}
|
}
|
||||||
else if (errno != EINTR) {
|
else if (errno != EINTR) {
|
||||||
perror("accept");
|
perror("accept");
|
||||||
@@ -314,11 +325,22 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Check if loop exited due to signal (accept returned EINTR) rather
|
||||||
|
* than successful fork
|
||||||
|
*/
|
||||||
|
if (!running) {
|
||||||
|
if (accsocket > 0)
|
||||||
|
close(accsocket);
|
||||||
|
close(socki);
|
||||||
|
return 128 + signal_num;
|
||||||
|
}
|
||||||
|
|
||||||
for (i=0; i<currmax; i++) {
|
for (i=0; i<currmax; i++) {
|
||||||
|
|
||||||
pr_debug("open %d '%s' m%08X v%08X i%d e%d.\n",
|
pr_debug("open %d '%s' m%08X v%08X i%d e%d.\n",
|
||||||
i, argv[optind+i], mask[i], value[i],
|
i, argv[optind+i], mask[i], value[i],
|
||||||
inv_filter[i], err_mask[i]);
|
inv_filter[i], err_mask[i]);
|
||||||
|
|
||||||
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
if ((s[i] = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
|
||||||
perror("socket");
|
perror("socket");
|
||||||
|
|||||||
+1
-1
@@ -261,7 +261,7 @@ int main(int argc, char **argv)
|
|||||||
struct can_raw_vcid_options vcid_opts = {
|
struct can_raw_vcid_options vcid_opts = {
|
||||||
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
||||||
};
|
};
|
||||||
static cu_t cu;
|
static union cfu cu;
|
||||||
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
|
static struct timeval today_tv, log_tv, last_log_tv, diff_tv;
|
||||||
struct timespec sleep_ts;
|
struct timespec sleep_ts;
|
||||||
int s; /* CAN_RAW socket */
|
int s; /* CAN_RAW socket */
|
||||||
|
|||||||
@@ -80,7 +80,10 @@ static void print_usage(char *prg)
|
|||||||
"_{dlc}:\n"
|
"_{dlc}:\n"
|
||||||
" an optional 9..F data length code value when payload length is 8\n"
|
" an optional 9..F data length code value when payload length is 8\n"
|
||||||
"<flags>:\n"
|
"<flags>:\n"
|
||||||
" a single ASCII Hex value (0 .. F) which defines canfd_frame.flags\n"
|
" a single ASCII Hex value (0 .. F) which defines canfd_frame.flags:\n"
|
||||||
|
" %x CANFD_BRS\n"
|
||||||
|
" %x CANFD_ESI\n"
|
||||||
|
" %x CANFD_FDF\n"
|
||||||
"\n"
|
"\n"
|
||||||
"<vcid>:\n"
|
"<vcid>:\n"
|
||||||
" 2 hex chars - virtual CAN network identifier (00 .. FF)\n"
|
" 2 hex chars - virtual CAN network identifier (00 .. FF)\n"
|
||||||
@@ -100,7 +103,8 @@ static void print_usage(char *prg)
|
|||||||
" 1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E /\n"
|
" 1F334455#1122334455667788_B / 123#R / 00000123#R3 / 333#R8_E /\n"
|
||||||
" 45123#81:00:12345678#11223344.556677 / 00242#81:07:40000123#112233\n"
|
" 45123#81:00:12345678#11223344.556677 / 00242#81:07:40000123#112233\n"
|
||||||
"\n",
|
"\n",
|
||||||
prg, prg);
|
prg, prg,
|
||||||
|
CANFD_BRS, CANFD_ESI, CANFD_FDF);
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
@@ -113,7 +117,7 @@ int main(int argc, char **argv)
|
|||||||
struct can_raw_vcid_options vcid_opts = {
|
struct can_raw_vcid_options vcid_opts = {
|
||||||
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
.flags = CAN_RAW_XL_VCID_TX_PASS,
|
||||||
};
|
};
|
||||||
static cu_t cu;
|
static union cfu cu;
|
||||||
struct ifreq ifr;
|
struct ifreq ifr;
|
||||||
|
|
||||||
/* check command line options */
|
/* check command line options */
|
||||||
|
|||||||
+11
-11
@@ -161,15 +161,15 @@ void switchvdl(char *delim)
|
|||||||
|
|
||||||
int comp(const void *elem1, const void *elem2)
|
int comp(const void *elem1, const void *elem2)
|
||||||
{
|
{
|
||||||
unsigned long f = ((struct snif*)elem1)->current.can_id;
|
unsigned long f = ((struct snif*)elem1)->current.can_id;
|
||||||
unsigned long s = ((struct snif*)elem2)->current.can_id;
|
unsigned long s = ((struct snif*)elem2)->current.can_id;
|
||||||
|
|
||||||
if (f > s)
|
if (f > s)
|
||||||
return 1;
|
return 1;
|
||||||
if (f < s)
|
if (f < s)
|
||||||
return -1;
|
return -1;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
void print_usage(char *prg)
|
void print_usage(char *prg)
|
||||||
@@ -741,10 +741,10 @@ int handle_timeo(long currcms)
|
|||||||
do_clr(i, UPDATE);
|
do_clr(i, UPDATE);
|
||||||
}
|
}
|
||||||
else if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
|
else if ((sniftab[i].hold) && (sniftab[i].hold < currcms)) {
|
||||||
memset(&sniftab[i].marker.data, 0, max_dlen);
|
memset(&sniftab[i].marker.data, 0, max_dlen);
|
||||||
print_snifline(i);
|
print_snifline(i);
|
||||||
sniftab[i].hold = 0; /* disable update by hold */
|
sniftab[i].hold = 0; /* disable update by hold */
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
printf("%s", CSR_DOWN); /* skip my line */
|
printf("%s", CSR_DOWN); /* skip my line */
|
||||||
|
|
||||||
|
|||||||
+88
-88
@@ -426,112 +426,112 @@ int main(int argc, char **argv)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (frame.can_id & CAN_EFF_FLAG)
|
if (frame.can_id & CAN_EFF_FLAG)
|
||||||
printf(" %s %8X", argv[optind], frame.can_id & CAN_EFF_MASK);
|
printf(" %s %8X", argv[optind], frame.can_id & CAN_EFF_MASK);
|
||||||
else
|
else
|
||||||
printf(" %s %3X", argv[optind], frame.can_id & CAN_SFF_MASK);
|
printf(" %s %3X", argv[optind], frame.can_id & CAN_SFF_MASK);
|
||||||
|
|
||||||
if (ext)
|
if (ext)
|
||||||
printf("{%02X}", frame.data[0]);
|
printf("{%02X}", frame.data[0]);
|
||||||
|
|
||||||
if (nbytes == CAN_MTU)
|
if (nbytes == CAN_MTU)
|
||||||
printf(" [%d] ", frame.len);
|
printf(" [%d] ", frame.len);
|
||||||
else
|
else
|
||||||
printf(" [%02d] ", frame.len);
|
printf(" [%02d] ", frame.len);
|
||||||
|
|
||||||
datidx = 0;
|
datidx = 0;
|
||||||
n_pci = frame.data[ext];
|
n_pci = frame.data[ext];
|
||||||
|
|
||||||
switch (n_pci & 0xF0) {
|
switch (n_pci & 0xF0) {
|
||||||
case 0x00:
|
case 0x00:
|
||||||
is_ff = 1;
|
is_ff = 1;
|
||||||
if (n_pci & 0xF) {
|
if (n_pci & 0xF) {
|
||||||
printf("[SF] ln: %-4d data:", n_pci & 0xF);
|
printf("[SF] ln: %-4d data:", n_pci & 0xF);
|
||||||
datidx = ext+1;
|
|
||||||
} else {
|
|
||||||
printf("[SF] ln: %-4d data:", frame.data[ext + 1]);
|
|
||||||
datidx = ext+2;
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x10:
|
|
||||||
is_ff = 1;
|
|
||||||
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
|
||||||
if (fflen)
|
|
||||||
datidx = ext+2;
|
|
||||||
else {
|
|
||||||
fflen = (frame.data[ext+2]<<24) +
|
|
||||||
(frame.data[ext+3]<<16) +
|
|
||||||
(frame.data[ext+4]<<8) +
|
|
||||||
frame.data[ext+5];
|
|
||||||
datidx = ext+6;
|
|
||||||
}
|
|
||||||
printf("[FF] ln: %-4lu data:", fflen);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x20:
|
|
||||||
printf("[CF] sn: %X data:", n_pci & 0x0F);
|
|
||||||
datidx = ext+1;
|
datidx = ext+1;
|
||||||
break;
|
} else {
|
||||||
|
printf("[SF] ln: %-4d data:", frame.data[ext + 1]);
|
||||||
|
datidx = ext+2;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
case 0x30:
|
case 0x10:
|
||||||
n_pci &= 0x0F;
|
is_ff = 1;
|
||||||
printf("[FC] FC: %d ", n_pci);
|
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
||||||
|
if (fflen)
|
||||||
|
datidx = ext+2;
|
||||||
|
else {
|
||||||
|
fflen = (frame.data[ext+2]<<24) +
|
||||||
|
(frame.data[ext+3]<<16) +
|
||||||
|
(frame.data[ext+4]<<8) +
|
||||||
|
frame.data[ext+5];
|
||||||
|
datidx = ext+6;
|
||||||
|
}
|
||||||
|
printf("[FF] ln: %-4lu data:", fflen);
|
||||||
|
break;
|
||||||
|
|
||||||
if (n_pci > 3)
|
case 0x20:
|
||||||
n_pci = 3;
|
printf("[CF] sn: %X data:", n_pci & 0x0F);
|
||||||
|
datidx = ext+1;
|
||||||
|
break;
|
||||||
|
|
||||||
printf("= %s # ", fc_info[n_pci]);
|
case 0x30:
|
||||||
|
n_pci &= 0x0F;
|
||||||
|
printf("[FC] FC: %d ", n_pci);
|
||||||
|
|
||||||
printf("BS: %d %s# ", frame.data[ext+1],
|
if (n_pci > 3)
|
||||||
(frame.data[ext+1])? "":"= off ");
|
n_pci = 3;
|
||||||
|
|
||||||
i = frame.data[ext+2];
|
printf("= %s # ", fc_info[n_pci]);
|
||||||
printf("STmin: 0x%02X = ", i);
|
|
||||||
|
|
||||||
if (i < 0x80)
|
printf("BS: %d %s# ", frame.data[ext+1],
|
||||||
printf("%d ms", i);
|
(frame.data[ext+1])? "":"= off ");
|
||||||
else if (i > 0xF0 && i < 0xFA)
|
|
||||||
printf("%d us", (i & 0x0F) * 100);
|
|
||||||
else
|
|
||||||
printf("reserved");
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
i = frame.data[ext+2];
|
||||||
printf("[??]");
|
printf("STmin: 0x%02X = ", i);
|
||||||
|
|
||||||
|
if (i < 0x80)
|
||||||
|
printf("%d ms", i);
|
||||||
|
else if (i > 0xF0 && i < 0xFA)
|
||||||
|
printf("%d us", (i & 0x0F) * 100);
|
||||||
|
else
|
||||||
|
printf("reserved");
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
printf("[??]");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (datidx && frame.len > datidx) {
|
||||||
|
printf(" ");
|
||||||
|
for (i = datidx; i < frame.len; i++) {
|
||||||
|
printf("%02X ", frame.data[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (datidx && frame.len > datidx) {
|
if (asc) {
|
||||||
printf(" ");
|
printf("%*s", ((7-ext) - (frame.len-datidx))*3 + 5 ,
|
||||||
|
"- '");
|
||||||
for (i = datidx; i < frame.len; i++) {
|
for (i = datidx; i < frame.len; i++) {
|
||||||
printf("%02X ", frame.data[i]);
|
printf("%c",((frame.data[i] > 0x1F) &&
|
||||||
}
|
(frame.data[i] < 0x7F))?
|
||||||
|
frame.data[i] : '.');
|
||||||
if (asc) {
|
|
||||||
printf("%*s", ((7-ext) - (frame.len-datidx))*3 + 5 ,
|
|
||||||
"- '");
|
|
||||||
for (i = datidx; i < frame.len; i++) {
|
|
||||||
printf("%c",((frame.data[i] > 0x1F) &&
|
|
||||||
(frame.data[i] < 0x7F))?
|
|
||||||
frame.data[i] : '.');
|
|
||||||
}
|
|
||||||
printf("'");
|
|
||||||
}
|
|
||||||
if (uds_output && is_ff) {
|
|
||||||
int offset = 3;
|
|
||||||
if (asc)
|
|
||||||
offset = 1;
|
|
||||||
printf("%*s", ((7-ext) - (frame.len-datidx))*offset + 3,
|
|
||||||
" - ");
|
|
||||||
print_uds_message(frame.data[datidx], frame.data[datidx+2]);
|
|
||||||
is_ff = 0;
|
|
||||||
}
|
}
|
||||||
|
printf("'");
|
||||||
}
|
}
|
||||||
|
if (uds_output && is_ff) {
|
||||||
|
int offset = 3;
|
||||||
|
if (asc)
|
||||||
|
offset = 1;
|
||||||
|
printf("%*s", ((7-ext) - (frame.len-datidx))*offset + 3,
|
||||||
|
" - ");
|
||||||
|
print_uds_message(frame.data[datidx], frame.data[datidx+2]);
|
||||||
|
is_ff = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (color)
|
if (color)
|
||||||
printf("%s", ATTRESET);
|
printf("%s", ATTRESET);
|
||||||
printf("\n");
|
printf("\n");
|
||||||
fflush(stdout);
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
|
|||||||
+162
-162
@@ -243,177 +243,177 @@ int main(int argc, char **argv)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* check extended address if provided */
|
||||||
|
if (ext && extaddr != frame.data[0])
|
||||||
|
continue;
|
||||||
|
|
||||||
|
/* only get flow control information from dst CAN ID */
|
||||||
|
if (frame.can_id == dst) {
|
||||||
/* check extended address if provided */
|
/* check extended address if provided */
|
||||||
if (ext && extaddr != frame.data[0])
|
if (rx_ext && frame.data[0] != rx_extaddr)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* only get flow control information from dst CAN ID */
|
n_pci = frame.data[rx_ext];
|
||||||
if (frame.can_id == dst) {
|
/* check flow control PCI only */
|
||||||
/* check extended address if provided */
|
if ((n_pci & 0xF0) != 0x30)
|
||||||
if (rx_ext && frame.data[0] != rx_extaddr)
|
continue;
|
||||||
continue;
|
|
||||||
|
|
||||||
n_pci = frame.data[rx_ext];
|
bs = frame.data[rx_ext + 1];
|
||||||
/* check flow control PCI only */
|
stmin = frame.data[rx_ext + 2];
|
||||||
if ((n_pci & 0xF0) != 0x30)
|
}
|
||||||
continue;
|
|
||||||
|
|
||||||
bs = frame.data[rx_ext + 1];
|
/* data content starts and index datidx */
|
||||||
stmin = frame.data[rx_ext + 2];
|
datidx = 0;
|
||||||
|
|
||||||
|
n_pci = frame.data[ext];
|
||||||
|
switch (n_pci & 0xF0) {
|
||||||
|
|
||||||
|
case 0x00:
|
||||||
|
/* SF */
|
||||||
|
if (n_pci & 0xF) {
|
||||||
|
fflen = rcvlen = n_pci & 0xF;
|
||||||
|
datidx = ext+1;
|
||||||
|
} else {
|
||||||
|
fflen = rcvlen = frame.data[ext + 1];
|
||||||
|
datidx = ext+2;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* data content starts and index datidx */
|
/* ignore incorrect SF PDUs */
|
||||||
datidx = 0;
|
if (frame.len < rcvlen + datidx)
|
||||||
|
|
||||||
n_pci = frame.data[ext];
|
|
||||||
switch (n_pci & 0xF0) {
|
|
||||||
|
|
||||||
case 0x00:
|
|
||||||
/* SF */
|
|
||||||
if (n_pci & 0xF) {
|
|
||||||
fflen = rcvlen = n_pci & 0xF;
|
|
||||||
datidx = ext+1;
|
|
||||||
} else {
|
|
||||||
fflen = rcvlen = frame.data[ext + 1];
|
|
||||||
datidx = ext+2;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* ignore incorrect SF PDUs */
|
|
||||||
if (frame.len < rcvlen + datidx)
|
|
||||||
fflen = rcvlen = 0;
|
|
||||||
|
|
||||||
/* get number of digits for printing */
|
|
||||||
fflen_digits = getdigits(fflen);
|
|
||||||
|
|
||||||
/* get CAN FD bitrate & LL_DL setting information */
|
|
||||||
brs = frame.flags & CANFD_BRS;
|
|
||||||
ll_dl = frame.len;
|
|
||||||
if (ll_dl < 8)
|
|
||||||
ll_dl = 8;
|
|
||||||
|
|
||||||
ioctl(s, SIOCGSTAMP, &start_tv);
|
|
||||||
|
|
||||||
/* determine CAN frame mode for this PDU */
|
|
||||||
if (nbytes == CAN_MTU)
|
|
||||||
canfd_on = 0;
|
|
||||||
else
|
|
||||||
canfd_on = 1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x10:
|
|
||||||
/* FF */
|
|
||||||
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
|
||||||
if (fflen)
|
|
||||||
datidx = ext+2;
|
|
||||||
else {
|
|
||||||
fflen = (frame.data[ext+2]<<24) +
|
|
||||||
(frame.data[ext+3]<<16) +
|
|
||||||
(frame.data[ext+4]<<8) +
|
|
||||||
frame.data[ext+5];
|
|
||||||
datidx = ext+6;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* to increase the time resolution we multiply fflen with 1000 later */
|
|
||||||
if (fflen >= (UINT32_MAX / 1000)) {
|
|
||||||
printf("fflen %lu is more than ~4.2 MB - ignoring PDU\n", fflen);
|
|
||||||
fflush(stdout);
|
|
||||||
fflen = rcvlen = 0;
|
|
||||||
continue;
|
|
||||||
}
|
|
||||||
rcvlen = frame.len - datidx;
|
|
||||||
last_sn = 0;
|
|
||||||
|
|
||||||
/* get number of digits for printing */
|
|
||||||
fflen_digits = getdigits(fflen);
|
|
||||||
|
|
||||||
/* get CAN FD bitrate & LL_DL setting information */
|
|
||||||
brs = frame.flags & CANFD_BRS;
|
|
||||||
ll_dl = frame.len;
|
|
||||||
|
|
||||||
ioctl(s, SIOCGSTAMP, &start_tv);
|
|
||||||
|
|
||||||
/* determine CAN frame mode for this PDU */
|
|
||||||
if (nbytes == CAN_MTU)
|
|
||||||
canfd_on = 0;
|
|
||||||
else
|
|
||||||
canfd_on = 1;
|
|
||||||
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x20:
|
|
||||||
/* CF */
|
|
||||||
if (rcvlen) {
|
|
||||||
sn = n_pci & 0x0F;
|
|
||||||
if (sn == ((last_sn + 1) & 0xF)) {
|
|
||||||
last_sn = sn;
|
|
||||||
datidx = ext+1;
|
|
||||||
rcvlen += frame.len - datidx;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PDU reception in process */
|
|
||||||
if (rcvlen) {
|
|
||||||
if (rcvlen > fflen)
|
|
||||||
rcvlen = fflen;
|
|
||||||
|
|
||||||
percent = (rcvlen * 100 / fflen);
|
|
||||||
printf("\r %3lu%% ", percent);
|
|
||||||
|
|
||||||
printf("|");
|
|
||||||
|
|
||||||
if (percent > 100)
|
|
||||||
percent = 100;
|
|
||||||
|
|
||||||
for (i=0; i < NUMBAR; i++){
|
|
||||||
if (i < (int)(percent/PERCENTRES))
|
|
||||||
printf("X");
|
|
||||||
else
|
|
||||||
printf(".");
|
|
||||||
}
|
|
||||||
printf("| %*lu/%lu ", fflen_digits, rcvlen, fflen);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* PDU complete */
|
|
||||||
if (rcvlen && rcvlen >= fflen) {
|
|
||||||
|
|
||||||
printf("\r%s %02d%c (BS:%2hhu # ", canfd_on?"CAN-FD":"CAN2.0", ll_dl, brs?'*':' ', bs);
|
|
||||||
if (stmin < 0x80)
|
|
||||||
printf("STmin:%3hhu msec)", stmin);
|
|
||||||
else if (stmin > 0xF0 && stmin < 0xFA)
|
|
||||||
printf("STmin:%3u usec)", (stmin & 0xF) * 100);
|
|
||||||
else
|
|
||||||
printf("STmin: invalid )");
|
|
||||||
|
|
||||||
printf(" : %lu byte in ", fflen);
|
|
||||||
|
|
||||||
/* calculate time */
|
|
||||||
ioctl(s, SIOCGSTAMP, &end_tv);
|
|
||||||
diff_tv.tv_sec = end_tv.tv_sec - start_tv.tv_sec;
|
|
||||||
diff_tv.tv_usec = end_tv.tv_usec - start_tv.tv_usec;
|
|
||||||
if (diff_tv.tv_usec < 0)
|
|
||||||
diff_tv.tv_sec--, diff_tv.tv_usec += 1000000;
|
|
||||||
if (diff_tv.tv_sec < 0)
|
|
||||||
diff_tv.tv_sec = diff_tv.tv_usec = 0;
|
|
||||||
|
|
||||||
/* check devisor to be not zero */
|
|
||||||
if (diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000){
|
|
||||||
printf("%llu.%06llus ", (unsigned long long)diff_tv.tv_sec, (unsigned long long)diff_tv.tv_usec);
|
|
||||||
printf("=> %lu byte/s", (fflen * 1000) /
|
|
||||||
(unsigned long)(diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000));
|
|
||||||
} else
|
|
||||||
printf("(no time available) ");
|
|
||||||
|
|
||||||
printf("\n");
|
|
||||||
/* wait for next PDU */
|
|
||||||
fflen = rcvlen = 0;
|
fflen = rcvlen = 0;
|
||||||
|
|
||||||
|
/* get number of digits for printing */
|
||||||
|
fflen_digits = getdigits(fflen);
|
||||||
|
|
||||||
|
/* get CAN FD bitrate & LL_DL setting information */
|
||||||
|
brs = frame.flags & CANFD_BRS;
|
||||||
|
ll_dl = frame.len;
|
||||||
|
if (ll_dl < 8)
|
||||||
|
ll_dl = 8;
|
||||||
|
|
||||||
|
ioctl(s, SIOCGSTAMP, &start_tv);
|
||||||
|
|
||||||
|
/* determine CAN frame mode for this PDU */
|
||||||
|
if (nbytes == CAN_MTU)
|
||||||
|
canfd_on = 0;
|
||||||
|
else
|
||||||
|
canfd_on = 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x10:
|
||||||
|
/* FF */
|
||||||
|
fflen = ((n_pci & 0x0F)<<8) + frame.data[ext+1];
|
||||||
|
if (fflen)
|
||||||
|
datidx = ext+2;
|
||||||
|
else {
|
||||||
|
fflen = (frame.data[ext+2]<<24) +
|
||||||
|
(frame.data[ext+3]<<16) +
|
||||||
|
(frame.data[ext+4]<<8) +
|
||||||
|
frame.data[ext+5];
|
||||||
|
datidx = ext+6;
|
||||||
}
|
}
|
||||||
fflush(stdout);
|
|
||||||
|
/* to increase the time resolution we multiply fflen with 1000 later */
|
||||||
|
if (fflen >= (UINT32_MAX / 1000)) {
|
||||||
|
printf("fflen %lu is more than ~4.2 MB - ignoring PDU\n", fflen);
|
||||||
|
fflush(stdout);
|
||||||
|
fflen = rcvlen = 0;
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
rcvlen = frame.len - datidx;
|
||||||
|
last_sn = 0;
|
||||||
|
|
||||||
|
/* get number of digits for printing */
|
||||||
|
fflen_digits = getdigits(fflen);
|
||||||
|
|
||||||
|
/* get CAN FD bitrate & LL_DL setting information */
|
||||||
|
brs = frame.flags & CANFD_BRS;
|
||||||
|
ll_dl = frame.len;
|
||||||
|
|
||||||
|
ioctl(s, SIOCGSTAMP, &start_tv);
|
||||||
|
|
||||||
|
/* determine CAN frame mode for this PDU */
|
||||||
|
if (nbytes == CAN_MTU)
|
||||||
|
canfd_on = 0;
|
||||||
|
else
|
||||||
|
canfd_on = 1;
|
||||||
|
|
||||||
|
break;
|
||||||
|
|
||||||
|
case 0x20:
|
||||||
|
/* CF */
|
||||||
|
if (rcvlen) {
|
||||||
|
sn = n_pci & 0x0F;
|
||||||
|
if (sn == ((last_sn + 1) & 0xF)) {
|
||||||
|
last_sn = sn;
|
||||||
|
datidx = ext+1;
|
||||||
|
rcvlen += frame.len - datidx;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PDU reception in process */
|
||||||
|
if (rcvlen) {
|
||||||
|
if (rcvlen > fflen)
|
||||||
|
rcvlen = fflen;
|
||||||
|
|
||||||
|
percent = (rcvlen * 100 / fflen);
|
||||||
|
printf("\r %3lu%% ", percent);
|
||||||
|
|
||||||
|
printf("|");
|
||||||
|
|
||||||
|
if (percent > 100)
|
||||||
|
percent = 100;
|
||||||
|
|
||||||
|
for (i=0; i < NUMBAR; i++){
|
||||||
|
if (i < (int)(percent/PERCENTRES))
|
||||||
|
printf("X");
|
||||||
|
else
|
||||||
|
printf(".");
|
||||||
|
}
|
||||||
|
printf("| %*lu/%lu ", fflen_digits, rcvlen, fflen);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* PDU complete */
|
||||||
|
if (rcvlen && rcvlen >= fflen) {
|
||||||
|
|
||||||
|
printf("\r%s %02d%c (BS:%2hhu # ", canfd_on?"CAN-FD":"CAN2.0", ll_dl, brs?'*':' ', bs);
|
||||||
|
if (stmin < 0x80)
|
||||||
|
printf("STmin:%3hhu msec)", stmin);
|
||||||
|
else if (stmin > 0xF0 && stmin < 0xFA)
|
||||||
|
printf("STmin:%3u usec)", (stmin & 0xF) * 100);
|
||||||
|
else
|
||||||
|
printf("STmin: invalid )");
|
||||||
|
|
||||||
|
printf(" : %lu byte in ", fflen);
|
||||||
|
|
||||||
|
/* calculate time */
|
||||||
|
ioctl(s, SIOCGSTAMP, &end_tv);
|
||||||
|
diff_tv.tv_sec = end_tv.tv_sec - start_tv.tv_sec;
|
||||||
|
diff_tv.tv_usec = end_tv.tv_usec - start_tv.tv_usec;
|
||||||
|
if (diff_tv.tv_usec < 0)
|
||||||
|
diff_tv.tv_sec--, diff_tv.tv_usec += 1000000;
|
||||||
|
if (diff_tv.tv_sec < 0)
|
||||||
|
diff_tv.tv_sec = diff_tv.tv_usec = 0;
|
||||||
|
|
||||||
|
/* check devisor to be not zero */
|
||||||
|
if (diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000){
|
||||||
|
printf("%llu.%06llus ", (unsigned long long)diff_tv.tv_sec, (unsigned long long)diff_tv.tv_usec);
|
||||||
|
printf("=> %lu byte/s", (fflen * 1000) /
|
||||||
|
(unsigned long)(diff_tv.tv_sec * 1000 + diff_tv.tv_usec / 1000));
|
||||||
|
} else
|
||||||
|
printf("(no time available) ");
|
||||||
|
|
||||||
|
printf("\n");
|
||||||
|
/* wait for next PDU */
|
||||||
|
fflen = rcvlen = 0;
|
||||||
|
}
|
||||||
|
fflush(stdout);
|
||||||
}
|
}
|
||||||
|
|
||||||
close(s);
|
close(s);
|
||||||
|
|||||||
+155
-155
@@ -82,183 +82,183 @@ void print_usage(char *prg)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
static struct can_isotp_options opts;
|
static struct can_isotp_options opts;
|
||||||
static struct can_isotp_fc_options fcopts;
|
static struct can_isotp_fc_options fcopts;
|
||||||
static struct can_isotp_ll_options llopts;
|
static struct can_isotp_ll_options llopts;
|
||||||
int opt, i;
|
int opt, i;
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
__u32 force_rx_stmin = 0;
|
__u32 force_rx_stmin = 0;
|
||||||
int loop = 0;
|
int loop = 0;
|
||||||
|
|
||||||
unsigned char msg[BUFSIZE];
|
unsigned char msg[BUFSIZE];
|
||||||
int nbytes;
|
int nbytes;
|
||||||
|
|
||||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:b:m:w:f:lFL:?")) != -1) {
|
while ((opt = getopt(argc, argv, "s:d:x:p:P:b:m:w:f:lFL:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 's':
|
case 's':
|
||||||
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
||||||
if (strlen(optarg) > 7)
|
if (strlen(optarg) > 7)
|
||||||
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
||||||
if (strlen(optarg) > 7)
|
if (strlen(optarg) > 7)
|
||||||
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
{
|
{
|
||||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||||
&opts.ext_address,
|
&opts.ext_address,
|
||||||
&opts.rx_ext_address);
|
&opts.rx_ext_address);
|
||||||
|
|
||||||
if (elements == 1)
|
if (elements == 1)
|
||||||
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
||||||
else if (elements == 2)
|
else if (elements == 2)
|
||||||
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
||||||
else {
|
else {
|
||||||
printf("incorrect extended addr values '%s'.\n", optarg);
|
printf("incorrect extended addr values '%s'.\n", optarg);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
{
|
{
|
||||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||||
&opts.txpad_content,
|
&opts.txpad_content,
|
||||||
&opts.rxpad_content);
|
&opts.rxpad_content);
|
||||||
|
|
||||||
if (elements == 1)
|
if (elements == 1)
|
||||||
opts.flags |= CAN_ISOTP_TX_PADDING;
|
opts.flags |= CAN_ISOTP_TX_PADDING;
|
||||||
else if (elements == 2)
|
else if (elements == 2)
|
||||||
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
||||||
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
||||||
opts.flags |= CAN_ISOTP_RX_PADDING;
|
opts.flags |= CAN_ISOTP_RX_PADDING;
|
||||||
else {
|
else {
|
||||||
printf("incorrect padding values '%s'.\n", optarg);
|
printf("incorrect padding values '%s'.\n", optarg);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
if (optarg[0] == 'l')
|
if (optarg[0] == 'l')
|
||||||
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
||||||
else if (optarg[0] == 'c')
|
else if (optarg[0] == 'c')
|
||||||
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
||||||
else if (optarg[0] == 'a')
|
else if (optarg[0] == 'a')
|
||||||
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
||||||
else {
|
else {
|
||||||
printf("unknown padding check option '%c'.\n", optarg[0]);
|
printf("unknown padding check option '%c'.\n", optarg[0]);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
fcopts.bs = strtoul(optarg, NULL, 16) & 0xFF;
|
fcopts.bs = strtoul(optarg, NULL, 16) & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'm':
|
case 'm':
|
||||||
fcopts.stmin = strtoul(optarg, NULL, 16) & 0xFF;
|
fcopts.stmin = strtoul(optarg, NULL, 16) & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'w':
|
case 'w':
|
||||||
fcopts.wftmax = strtoul(optarg, NULL, 16) & 0xFF;
|
fcopts.wftmax = strtoul(optarg, NULL, 16) & 0xFF;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
opts.flags |= CAN_ISOTP_FORCE_RXSTMIN;
|
opts.flags |= CAN_ISOTP_FORCE_RXSTMIN;
|
||||||
force_rx_stmin = strtoul(optarg, NULL, 10);
|
force_rx_stmin = strtoul(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
loop = 1;
|
loop = 1;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'F':
|
case 'F':
|
||||||
opts.flags |= CAN_ISOTP_DYN_FC_PARMS;
|
opts.flags |= CAN_ISOTP_DYN_FC_PARMS;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
||||||
&llopts.mtu,
|
&llopts.mtu,
|
||||||
&llopts.tx_dl,
|
&llopts.tx_dl,
|
||||||
&llopts.tx_flags) != 3) {
|
&llopts.tx_flags) != 3) {
|
||||||
printf("unknown link layer options '%s'.\n", optarg);
|
printf("unknown link layer options '%s'.\n", optarg);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown option %c\n", opt);
|
fprintf(stderr, "Unknown option %c\n", opt);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if ((argc - optind != 1) ||
|
|
||||||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
|
||||||
(addr.can_addr.tp.rx_id == NO_CAN_ID)) {
|
|
||||||
print_usage(basename(argv[0]));
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
|
||||||
perror("socket");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
|
||||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts, sizeof(fcopts));
|
|
||||||
|
|
||||||
if (llopts.tx_dl) {
|
|
||||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
|
||||||
perror("link layer sockopt");
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.flags & CAN_ISOTP_FORCE_RXSTMIN)
|
if ((argc - optind != 1) ||
|
||||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RX_STMIN, &force_rx_stmin, sizeof(force_rx_stmin));
|
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
||||||
|
(addr.can_addr.tp.rx_id == NO_CAN_ID)) {
|
||||||
|
print_usage(basename(argv[0]));
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||||
|
perror("socket");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts));
|
||||||
addr.can_ifindex = if_nametoindex(argv[optind]);
|
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RECV_FC, &fcopts, sizeof(fcopts));
|
||||||
if (!addr.can_ifindex) {
|
|
||||||
perror("if_nametoindex");
|
if (llopts.tx_dl) {
|
||||||
exit(1);
|
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
||||||
}
|
perror("link layer sockopt");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (opts.flags & CAN_ISOTP_FORCE_RXSTMIN)
|
||||||
|
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_RX_STMIN, &force_rx_stmin, sizeof(force_rx_stmin));
|
||||||
|
|
||||||
|
addr.can_family = AF_CAN;
|
||||||
|
addr.can_ifindex = if_nametoindex(argv[optind]);
|
||||||
|
if (!addr.can_ifindex) {
|
||||||
|
perror("if_nametoindex");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
close(s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
do {
|
||||||
|
nbytes = read(s, msg, BUFSIZE);
|
||||||
|
if (nbytes > 0 && nbytes < BUFSIZE)
|
||||||
|
for (i=0; i < nbytes; i++)
|
||||||
|
printf("%02X ", msg[i]);
|
||||||
|
printf("\n");
|
||||||
|
} while (loop);
|
||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
perror("bind");
|
|
||||||
close(s);
|
close(s);
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
do {
|
return 0;
|
||||||
nbytes = read(s, msg, BUFSIZE);
|
|
||||||
if (nbytes > 0 && nbytes < BUFSIZE)
|
|
||||||
for (i=0; i < nbytes; i++)
|
|
||||||
printf("%02X ", msg[i]);
|
|
||||||
printf("\n");
|
|
||||||
} while (loop);
|
|
||||||
|
|
||||||
close(s);
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
}
|
||||||
|
|||||||
+200
-200
@@ -86,238 +86,238 @@ void print_usage(char *prg)
|
|||||||
|
|
||||||
int main(int argc, char **argv)
|
int main(int argc, char **argv)
|
||||||
{
|
{
|
||||||
int s;
|
int s;
|
||||||
struct sockaddr_can addr;
|
struct sockaddr_can addr;
|
||||||
static struct can_isotp_options opts;
|
static struct can_isotp_options opts;
|
||||||
static struct can_isotp_ll_options llopts;
|
static struct can_isotp_ll_options llopts;
|
||||||
int opt;
|
int opt;
|
||||||
extern int optind, opterr, optopt;
|
extern int optind, opterr, optopt;
|
||||||
unsigned int loops = 1; /* one (== no) loop by default */
|
unsigned int loops = 1; /* one (== no) loop by default */
|
||||||
useconds_t usecs = 0; /* wait before sending the PDU */
|
useconds_t usecs = 0; /* wait before sending the PDU */
|
||||||
__u32 force_tx_stmin = 0;
|
__u32 force_tx_stmin = 0;
|
||||||
unsigned char buf[BUFSIZE];
|
unsigned char buf[BUFSIZE];
|
||||||
int buflen = 0;
|
int buflen = 0;
|
||||||
int datalen = 0;
|
int datalen = 0;
|
||||||
int retval = 0;
|
int retval = 0;
|
||||||
|
|
||||||
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
addr.can_addr.tp.tx_id = addr.can_addr.tp.rx_id = NO_CAN_ID;
|
||||||
|
|
||||||
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSCL:?")) != -1) {
|
while ((opt = getopt(argc, argv, "s:d:x:p:P:t:f:D:l:g:bSCL:?")) != -1) {
|
||||||
switch (opt) {
|
switch (opt) {
|
||||||
case 's':
|
case 's':
|
||||||
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
addr.can_addr.tp.tx_id = strtoul(optarg, NULL, 16);
|
||||||
if (strlen(optarg) > 7)
|
if (strlen(optarg) > 7)
|
||||||
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
addr.can_addr.tp.tx_id |= CAN_EFF_FLAG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'd':
|
case 'd':
|
||||||
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
addr.can_addr.tp.rx_id = strtoul(optarg, NULL, 16);
|
||||||
if (strlen(optarg) > 7)
|
if (strlen(optarg) > 7)
|
||||||
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
addr.can_addr.tp.rx_id |= CAN_EFF_FLAG;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'x':
|
case 'x':
|
||||||
{
|
{
|
||||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||||
&opts.ext_address,
|
&opts.ext_address,
|
||||||
&opts.rx_ext_address);
|
&opts.rx_ext_address);
|
||||||
|
|
||||||
if (elements == 1)
|
if (elements == 1)
|
||||||
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
opts.flags |= CAN_ISOTP_EXTEND_ADDR;
|
||||||
else if (elements == 2)
|
else if (elements == 2)
|
||||||
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
opts.flags |= (CAN_ISOTP_EXTEND_ADDR | CAN_ISOTP_RX_EXT_ADDR);
|
||||||
else {
|
else {
|
||||||
printf("incorrect extended addr values '%s'.\n", optarg);
|
printf("incorrect extended addr values '%s'.\n", optarg);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'p':
|
case 'p':
|
||||||
{
|
{
|
||||||
int elements = sscanf(optarg, "%hhx:%hhx",
|
int elements = sscanf(optarg, "%hhx:%hhx",
|
||||||
&opts.txpad_content,
|
&opts.txpad_content,
|
||||||
&opts.rxpad_content);
|
&opts.rxpad_content);
|
||||||
|
|
||||||
if (elements == 1)
|
if (elements == 1)
|
||||||
opts.flags |= CAN_ISOTP_TX_PADDING;
|
opts.flags |= CAN_ISOTP_TX_PADDING;
|
||||||
else if (elements == 2)
|
else if (elements == 2)
|
||||||
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
opts.flags |= (CAN_ISOTP_TX_PADDING | CAN_ISOTP_RX_PADDING);
|
||||||
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
else if (sscanf(optarg, ":%hhx", &opts.rxpad_content) == 1)
|
||||||
opts.flags |= CAN_ISOTP_RX_PADDING;
|
opts.flags |= CAN_ISOTP_RX_PADDING;
|
||||||
else {
|
else {
|
||||||
printf("incorrect padding values '%s'.\n", optarg);
|
printf("incorrect padding values '%s'.\n", optarg);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
case 'P':
|
case 'P':
|
||||||
if (optarg[0] == 'l')
|
if (optarg[0] == 'l')
|
||||||
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
opts.flags |= CAN_ISOTP_CHK_PAD_LEN;
|
||||||
else if (optarg[0] == 'c')
|
else if (optarg[0] == 'c')
|
||||||
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
opts.flags |= CAN_ISOTP_CHK_PAD_DATA;
|
||||||
else if (optarg[0] == 'a')
|
else if (optarg[0] == 'a')
|
||||||
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
opts.flags |= (CAN_ISOTP_CHK_PAD_LEN | CAN_ISOTP_CHK_PAD_DATA);
|
||||||
else {
|
else {
|
||||||
printf("unknown padding check option '%c'.\n", optarg[0]);
|
printf("unknown padding check option '%c'.\n", optarg[0]);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 't':
|
case 't':
|
||||||
if (!strncmp(optarg, ZERO_STRING, strlen(ZERO_STRING)))
|
if (!strncmp(optarg, ZERO_STRING, strlen(ZERO_STRING)))
|
||||||
opts.frame_txtime = CAN_ISOTP_FRAME_TXTIME_ZERO;
|
opts.frame_txtime = CAN_ISOTP_FRAME_TXTIME_ZERO;
|
||||||
else
|
else
|
||||||
opts.frame_txtime = strtoul(optarg, NULL, 10);
|
opts.frame_txtime = strtoul(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'f':
|
case 'f':
|
||||||
opts.flags |= CAN_ISOTP_FORCE_TXSTMIN;
|
opts.flags |= CAN_ISOTP_FORCE_TXSTMIN;
|
||||||
force_tx_stmin = strtoul(optarg, NULL, 10);
|
force_tx_stmin = strtoul(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'D':
|
case 'D':
|
||||||
datalen = strtoul(optarg, NULL, 10);
|
datalen = strtoul(optarg, NULL, 10);
|
||||||
if (!datalen || datalen >= BUFSIZE) {
|
if (!datalen || datalen >= BUFSIZE) {
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'l':
|
case 'l':
|
||||||
if (optarg[0] == 'i') {
|
if (optarg[0] == 'i') {
|
||||||
loops = 0; /* infinite loop */
|
loops = 0; /* infinite loop */
|
||||||
} else {
|
} else {
|
||||||
loops = strtoul(optarg, NULL, 10);
|
loops = strtoul(optarg, NULL, 10);
|
||||||
if (!loops) {
|
if (!loops) {
|
||||||
fprintf(stderr, "Invalid argument for option -l!\n");
|
fprintf(stderr, "Invalid argument for option -l!\n");
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'g':
|
case 'g':
|
||||||
usecs = strtoul(optarg, NULL, 10);
|
usecs = strtoul(optarg, NULL, 10);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'b':
|
case 'b':
|
||||||
opts.flags |= CAN_ISOTP_WAIT_TX_DONE;
|
opts.flags |= CAN_ISOTP_WAIT_TX_DONE;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'S':
|
case 'S':
|
||||||
opts.flags |= CAN_ISOTP_SF_BROADCAST;
|
opts.flags |= CAN_ISOTP_SF_BROADCAST;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'C':
|
case 'C':
|
||||||
opts.flags |= CAN_ISOTP_CF_BROADCAST;
|
opts.flags |= CAN_ISOTP_CF_BROADCAST;
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 'L':
|
case 'L':
|
||||||
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
if (sscanf(optarg, "%hhu:%hhu:%hhu",
|
||||||
&llopts.mtu,
|
&llopts.mtu,
|
||||||
&llopts.tx_dl,
|
&llopts.tx_dl,
|
||||||
&llopts.tx_flags) != 3) {
|
&llopts.tx_flags) != 3) {
|
||||||
printf("unknown link layer options '%s'.\n", optarg);
|
printf("unknown link layer options '%s'.\n", optarg);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case '?':
|
case '?':
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(0);
|
exit(0);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "Unknown option %c\n", opt);
|
fprintf(stderr, "Unknown option %c\n", opt);
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(1);
|
exit(1);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
|
#define BC_FLAGS (CAN_ISOTP_SF_BROADCAST | CAN_ISOTP_CF_BROADCAST)
|
||||||
|
|
||||||
if ((argc - optind != 1) ||
|
if ((argc - optind != 1) ||
|
||||||
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
(addr.can_addr.tp.tx_id == NO_CAN_ID) ||
|
||||||
((opts.flags & BC_FLAGS) == BC_FLAGS) ||
|
((opts.flags & BC_FLAGS) == BC_FLAGS) ||
|
||||||
((addr.can_addr.tp.rx_id == NO_CAN_ID) &&
|
((addr.can_addr.tp.rx_id == NO_CAN_ID) &&
|
||||||
(!(opts.flags & BC_FLAGS)))) {
|
(!(opts.flags & BC_FLAGS)))) {
|
||||||
print_usage(basename(argv[0]));
|
print_usage(basename(argv[0]));
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
|
||||||
|
|
||||||
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
|
||||||
perror("socket");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)) < 0) {
|
|
||||||
perror("sockopt");
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
if (llopts.tx_dl) {
|
|
||||||
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
|
||||||
perror("link layer sockopt");
|
|
||||||
exit(1);
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (opts.flags & CAN_ISOTP_FORCE_TXSTMIN)
|
if ((s = socket(PF_CAN, SOCK_DGRAM, CAN_ISOTP)) < 0) {
|
||||||
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_TX_STMIN, &force_tx_stmin, sizeof(force_tx_stmin));
|
perror("socket");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
addr.can_family = AF_CAN;
|
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_OPTS, &opts, sizeof(opts)) < 0) {
|
||||||
addr.can_ifindex = if_nametoindex(argv[optind]);
|
perror("sockopt");
|
||||||
if (!addr.can_ifindex) {
|
exit(1);
|
||||||
perror("if_nametoindex");
|
}
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
|
||||||
perror("bind");
|
|
||||||
close(s);
|
|
||||||
exit(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!datalen) {
|
if (llopts.tx_dl) {
|
||||||
while (buflen < BUFSIZE && scanf("%hhx", &buf[buflen]) == 1)
|
if (setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_LL_OPTS, &llopts, sizeof(llopts)) < 0) {
|
||||||
buflen++;
|
perror("link layer sockopt");
|
||||||
} else {
|
exit(1);
|
||||||
for (buflen = 0; buflen < datalen; buflen++)
|
}
|
||||||
buf[buflen] = ((buflen % 0xFF) + 1) & 0xFF;
|
}
|
||||||
}
|
|
||||||
|
if (opts.flags & CAN_ISOTP_FORCE_TXSTMIN)
|
||||||
|
setsockopt(s, SOL_CAN_ISOTP, CAN_ISOTP_TX_STMIN, &force_tx_stmin, sizeof(force_tx_stmin));
|
||||||
|
|
||||||
|
addr.can_family = AF_CAN;
|
||||||
|
addr.can_ifindex = if_nametoindex(argv[optind]);
|
||||||
|
if (!addr.can_ifindex) {
|
||||||
|
perror("if_nametoindex");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
|
||||||
|
perror("bind");
|
||||||
|
close(s);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!datalen) {
|
||||||
|
while (buflen < BUFSIZE && scanf("%hhx", &buf[buflen]) == 1)
|
||||||
|
buflen++;
|
||||||
|
} else {
|
||||||
|
for (buflen = 0; buflen < datalen; buflen++)
|
||||||
|
buf[buflen] = ((buflen % 0xFF) + 1) & 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
loop:
|
loop:
|
||||||
if (usecs)
|
if (usecs)
|
||||||
usleep(usecs);
|
usleep(usecs);
|
||||||
|
|
||||||
retval = write(s, buf, buflen);
|
retval = write(s, buf, buflen);
|
||||||
if (retval < 0) {
|
if (retval < 0) {
|
||||||
perror("write");
|
perror("write");
|
||||||
return retval;
|
return retval;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (retval != buflen)
|
if (retval != buflen)
|
||||||
fprintf(stderr, "wrote only %d from %d byte\n", retval, buflen);
|
fprintf(stderr, "wrote only %d from %d byte\n", retval, buflen);
|
||||||
|
|
||||||
if (loops) {
|
if (loops) {
|
||||||
if (--loops)
|
if (--loops)
|
||||||
goto loop;
|
goto loop;
|
||||||
} else {
|
} else {
|
||||||
goto loop;
|
goto loop;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* due to a Kernel internal wait queue the PDU is sent completely
|
* due to a Kernel internal wait queue the PDU is sent completely
|
||||||
* before close() returns.
|
* before close() returns.
|
||||||
*/
|
*/
|
||||||
close(s);
|
close(s);
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -41,17 +41,23 @@ static void gmtime_to_j1939_pgn_65254_td(struct j1939_time_date_packet *tdp)
|
|||||||
utc_tm = gmtime_r(&now, &utc_tm_buf);
|
utc_tm = gmtime_r(&now, &utc_tm_buf);
|
||||||
local_tm = localtime_r(&now, &local_tm_buf);
|
local_tm = localtime_r(&now, &local_tm_buf);
|
||||||
|
|
||||||
/* Calculate the offsets */
|
if (local_tm) {
|
||||||
hour_offset = local_tm->tm_hour - utc_tm->tm_hour;
|
/* Calculate the offsets */
|
||||||
minute_offset = local_tm->tm_min - utc_tm->tm_min;
|
hour_offset = local_tm->tm_hour - utc_tm->tm_hour;
|
||||||
|
minute_offset = local_tm->tm_min - utc_tm->tm_min;
|
||||||
|
|
||||||
/* Handle date rollover */
|
/* Handle date rollover */
|
||||||
if (local_tm->tm_mday != utc_tm->tm_mday) {
|
if (local_tm->tm_mday != utc_tm->tm_mday) {
|
||||||
if (local_tm->tm_hour < 12)
|
if (local_tm->tm_hour < 12)
|
||||||
hour_offset += 24; /* past midnight */
|
hour_offset += 24; /* past midnight */
|
||||||
else
|
else
|
||||||
hour_offset -= 24; /* before midnight */
|
hour_offset -= 24; /* before midnight */
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
/* The local time offsets cannot be determined at the moment */
|
||||||
|
hour_offset = 0xF9;
|
||||||
|
minute_offset = 0xFF;
|
||||||
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Seconds (spn959):
|
* Seconds (spn959):
|
||||||
|
|||||||
@@ -51,7 +51,7 @@ struct j1939_vp_err_msg {
|
|||||||
#define J1939_VP1_PRIO_DEFAULT 6
|
#define J1939_VP1_PRIO_DEFAULT 6
|
||||||
#define J1939_VP1_MAX_TRANSFER_LENGH \
|
#define J1939_VP1_MAX_TRANSFER_LENGH \
|
||||||
sizeof(struct j1939_vp1_packet)
|
sizeof(struct j1939_vp1_packet)
|
||||||
#define J1939_VP1_REPETITION_RATE_MS 5000
|
#define J1939_VP1_REPETITION_RATE_MS 1000
|
||||||
#define J1939_VP1_JITTER_MS 500
|
#define J1939_VP1_JITTER_MS 500
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@@ -63,8 +63,8 @@ struct j1939_vp_err_msg {
|
|||||||
* - Data Length: 4 bytes
|
* - Data Length: 4 bytes
|
||||||
* - Resolution: 10^-7 deg/bit
|
* - Resolution: 10^-7 deg/bit
|
||||||
* - Offset: -210 degrees
|
* - Offset: -210 degrees
|
||||||
* - Range: -210 to +211.1008122 degrees
|
* - Range: -210 to +211.10081215 degrees
|
||||||
* - Operating Range: -210 degrees (SOUTH) to +211.108122 degrees
|
* - Operating Range: -210 degrees (SOUTH) to +211.1081215 degrees
|
||||||
* (NORTH)
|
* (NORTH)
|
||||||
*
|
*
|
||||||
* @longitude: Raw longitude position of the vehicle
|
* @longitude: Raw longitude position of the vehicle
|
||||||
@@ -72,8 +72,8 @@ struct j1939_vp_err_msg {
|
|||||||
* - Data Length: 4 bytes
|
* - Data Length: 4 bytes
|
||||||
* - Resolution: 10^-7 deg/bit
|
* - Resolution: 10^-7 deg/bit
|
||||||
* - Offset: -210 degrees
|
* - Offset: -210 degrees
|
||||||
* - Range: -210 to +211.1008122 degrees
|
* - Range: -210 to +211.10081215 degrees
|
||||||
* - Operating Range: -210 degrees (WEST) to +211.108122 degrees
|
* - Operating Range: -210 degrees (WEST) to +211.1081215 degrees
|
||||||
* (EAST)
|
* (EAST)
|
||||||
*
|
*
|
||||||
* This structure defines each component of the Vehicle Position as described in
|
* This structure defines each component of the Vehicle Position as described in
|
||||||
@@ -142,42 +142,48 @@ j1939_vp1_set_longitude(struct j1939_vp1_packet *packet, int32_t longitude)
|
|||||||
/**
|
/**
|
||||||
* struct j1939_vp2_packet - Represents the PGN 64502 Vehicle
|
* struct j1939_vp2_packet - Represents the PGN 64502 Vehicle
|
||||||
* Position 2 packet
|
* Position 2 packet
|
||||||
* FIXME: current packet layout is guessed based on limited information:
|
|
||||||
* https://www.isobus.net/isobus/pGNAndSPN/10801?type=PGN
|
|
||||||
*
|
*
|
||||||
* @total_satellites: Total number of satellites in view
|
* @total_satellites: Total number of satellites in view
|
||||||
* - SPN: 8128
|
* - SPN: 8128
|
||||||
* - Data Length: 1 byte
|
* - Data Length: 1 byte
|
||||||
|
* - Range: 0 to 250
|
||||||
*
|
*
|
||||||
* @hdop: Horizontal dilution of precision
|
* @hdop: Horizontal dilution of precision
|
||||||
* - SPN: 8129
|
* - SPN: 8129
|
||||||
* - Data Length: 1 byte
|
* - Data Length: 1 byte
|
||||||
* - Resolution: 0.1
|
* - Resolution: 0.1
|
||||||
|
* - Range: 0.0 to 25.0
|
||||||
*
|
*
|
||||||
* @vdop: Vertical dilution of precision
|
* @vdop: Vertical dilution of precision
|
||||||
* - SPN: 8130
|
* - SPN: 8130
|
||||||
* - Data Length: 1 byte
|
* - Data Length: 1 byte
|
||||||
* - Resolution: 0.1
|
* - Resolution: 0.1
|
||||||
|
* - Range: 0.0 to 25.0
|
||||||
*
|
*
|
||||||
* @pdop: Position dilution of precision
|
* @pdop: Position dilution of precision
|
||||||
* - SPN: 8131
|
* - SPN: 8131
|
||||||
* - Data Length: 1 byte
|
* - Data Length: 1 byte
|
||||||
* - Resolution: 0.1
|
* - Resolution: 0.1
|
||||||
|
* - Range: 0.0 to 25.0
|
||||||
*
|
*
|
||||||
* @tdop: Time dilution of precision
|
* @tdop: Time dilution of precision
|
||||||
* - SPN: 8132
|
* - SPN: 8132
|
||||||
* - Data Length: 1 byte
|
* - Data Length: 1 byte
|
||||||
* - Resolution: 0.1
|
* - Resolution: 0.1
|
||||||
|
* - Range: 0.0 to 25.0
|
||||||
*
|
*
|
||||||
* This structure defines each component of the Vehicle Position 2 as described
|
* This structure defines each component of the Vehicle Position 2 as described
|
||||||
* in PGN 64502.
|
* in PGN 64502.
|
||||||
*/
|
*/
|
||||||
struct j1939_vp2_packet {
|
struct j1939_vp2_packet {
|
||||||
uint8_t total_satellites; /* SPN 8128 */
|
uint8_t total_satellites; /* SPN 8128 */
|
||||||
uint8_t hdop; /* SPN 8129 */
|
uint8_t hdop; /* SPN 8129 */
|
||||||
uint8_t vdop; /* SPN 8130 */
|
uint8_t vdop; /* SPN 8130 */
|
||||||
uint8_t pdop; /* SPN 8131 */
|
uint8_t pdop; /* SPN 8131 */
|
||||||
uint8_t tdop; /* SPN 8132 */
|
uint8_t tdop; /* SPN 8132 */
|
||||||
|
uint8_t unused5; /* Always 0xFF */
|
||||||
|
uint8_t unused6; /* Always 0xFF */
|
||||||
|
uint8_t unused7; /* Always 0xFF */
|
||||||
} __attribute__((__packed__));
|
} __attribute__((__packed__));
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -270,6 +270,12 @@ static int j1939_vp2_get_data(struct j1939_vp_srv_priv *priv,
|
|||||||
j1939_vp2_set_pdop(vp2p, pdop);
|
j1939_vp2_set_pdop(vp2p, pdop);
|
||||||
j1939_vp2_set_tdop(vp2p, tdop);
|
j1939_vp2_set_tdop(vp2p, tdop);
|
||||||
|
|
||||||
|
/* This PG's last 3 bytes are not assigned and hence must be set
|
||||||
|
* to 0xFF as per J1939-71, section 5.2 */
|
||||||
|
vp2p->unused5 = 0xFF;
|
||||||
|
vp2p->unused6 = 0xFF;
|
||||||
|
vp2p->unused7 = 0xFF;
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
+8
-8
@@ -112,10 +112,10 @@ static struct {
|
|||||||
int sig_alrm;
|
int sig_alrm;
|
||||||
int sig_usr1;
|
int sig_usr1;
|
||||||
int state;
|
int state;
|
||||||
#define STATE_INITIAL 0
|
#define STATE_INITIAL 0
|
||||||
#define STATE_REQ_SENT 1
|
#define STATE_REQ_SENT 1
|
||||||
#define STATE_REQ_PENDING 2 /* wait 1250 msec for first claim */
|
#define STATE_REQ_PENDING 2 /* wait 1250 msec for first claim */
|
||||||
#define STATE_OPERATIONAL 3
|
#define STATE_OPERATIONAL 3
|
||||||
} s = {
|
} s = {
|
||||||
.intf = default_intf,
|
.intf = default_intf,
|
||||||
.ranges = default_range,
|
.ranges = default_range,
|
||||||
@@ -126,8 +126,8 @@ static struct {
|
|||||||
struct {
|
struct {
|
||||||
uint64_t name;
|
uint64_t name;
|
||||||
int flags;
|
int flags;
|
||||||
#define F_USE 0x01
|
#define F_USE 0x01
|
||||||
#define F_SEEN 0x02
|
#define F_SEEN 0x02
|
||||||
} addr[J1939_IDLE_ADDR /* =254 */];
|
} addr[J1939_IDLE_ADDR /* =254 */];
|
||||||
|
|
||||||
/* lookup by name */
|
/* lookup by name */
|
||||||
@@ -209,7 +209,7 @@ static int open_socket(const char *device, uint64_t name)
|
|||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_FILTER, <filter>, %zd);\n", sizeof(filt));
|
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_FILTER, <filter>, %zd);\n", sizeof(filt));
|
||||||
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER,
|
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_FILTER,
|
||||||
&filt, sizeof(filt));
|
&filt, sizeof(filt));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
err(1, "setsockopt filter");
|
err(1, "setsockopt filter");
|
||||||
|
|
||||||
@@ -217,7 +217,7 @@ static int open_socket(const char *device, uint64_t name)
|
|||||||
if (s.verbose)
|
if (s.verbose)
|
||||||
fprintf(stderr, "- setsockopt(, SOL_SOCKET, SO_BROADCAST, %d, %zd);\n", value, sizeof(value));
|
fprintf(stderr, "- setsockopt(, SOL_SOCKET, SO_BROADCAST, %d, %zd);\n", value, sizeof(value));
|
||||||
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
|
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST,
|
||||||
&value, sizeof(value));
|
&value, sizeof(value));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
err(1, "setsockopt set broadcast");
|
err(1, "setsockopt set broadcast");
|
||||||
|
|
||||||
|
|||||||
+18
-18
@@ -31,11 +31,11 @@
|
|||||||
* strict type-checking.. See the
|
* strict type-checking.. See the
|
||||||
* "unnecessary" pointer comparison.
|
* "unnecessary" pointer comparison.
|
||||||
*/
|
*/
|
||||||
#define min(x, y) ({ \
|
#define min(x, y) ({ \
|
||||||
typeof(x) _min1 = (x); \
|
typeof(x) _min1 = (x); \
|
||||||
typeof(y) _min2 = (y); \
|
typeof(y) _min2 = (y); \
|
||||||
(void) (&_min1 == &_min2); \
|
(void) (&_min1 == &_min2); \
|
||||||
_min1 < _min2 ? _min1 : _min2; })
|
_min1 < _min2 ? _min1 : _min2; })
|
||||||
|
|
||||||
|
|
||||||
struct j1939cat_stats {
|
struct j1939cat_stats {
|
||||||
@@ -98,7 +98,7 @@ static const char help_msg[] =
|
|||||||
static const char optstring[] = "?hi:vs:rp:P:R:B";
|
static const char optstring[] = "?hi:vs:rp:P:R:B";
|
||||||
|
|
||||||
static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
||||||
const void *buf, size_t buf_size)
|
const void *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
ssize_t num_sent;
|
ssize_t num_sent;
|
||||||
int flags = 0;
|
int flags = 0;
|
||||||
@@ -132,7 +132,7 @@ static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *name,
|
static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *name,
|
||||||
struct timespec *cur)
|
struct timespec *cur)
|
||||||
{
|
{
|
||||||
struct j1939cat_stats *stats = &priv->stats;
|
struct j1939cat_stats *stats = &priv->stats;
|
||||||
|
|
||||||
@@ -140,8 +140,8 @@ static void j1939cat_print_timestamp(struct j1939cat_priv *priv, const char *nam
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
fprintf(stderr, " %s: %llu s %llu us (seq=%03u, send=%07u)",
|
fprintf(stderr, " %s: %llu s %llu us (seq=%03u, send=%07u)",
|
||||||
name, (unsigned long long)cur->tv_sec, (unsigned long long)cur->tv_nsec / 1000,
|
name, (unsigned long long)cur->tv_sec, (unsigned long long)cur->tv_nsec / 1000,
|
||||||
stats->tskey, stats->send);
|
stats->tskey, stats->send);
|
||||||
|
|
||||||
fprintf(stderr, "\n");
|
fprintf(stderr, "\n");
|
||||||
}
|
}
|
||||||
@@ -226,7 +226,7 @@ static int j1939cat_extract_serr(struct j1939cat_priv *priv)
|
|||||||
stats->tskey = serr->ee_data;
|
stats->tskey = serr->ee_data;
|
||||||
|
|
||||||
j1939cat_print_timestamp(priv, j1939cat_tstype_to_str(serr->ee_info),
|
j1939cat_print_timestamp(priv, j1939cat_tstype_to_str(serr->ee_info),
|
||||||
&tss->ts[0]);
|
&tss->ts[0]);
|
||||||
|
|
||||||
if (serr->ee_info == SCM_TSTAMP_SCHED)
|
if (serr->ee_info == SCM_TSTAMP_SCHED)
|
||||||
return -EINTR;
|
return -EINTR;
|
||||||
@@ -338,7 +338,7 @@ static int j1939cat_recv_err(struct j1939cat_priv *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
|
static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
|
||||||
size_t buf_size)
|
size_t buf_size)
|
||||||
{
|
{
|
||||||
struct j1939cat_stats *stats = &priv->stats;
|
struct j1939cat_stats *stats = &priv->stats;
|
||||||
ssize_t count;
|
ssize_t count;
|
||||||
@@ -411,7 +411,7 @@ static int j1939cat_send_loop(struct j1939cat_priv *priv, int out_fd, char *buf,
|
|||||||
}
|
}
|
||||||
|
|
||||||
static int j1939cat_sendfile(struct j1939cat_priv *priv, int out_fd, int in_fd,
|
static int j1939cat_sendfile(struct j1939cat_priv *priv, int out_fd, int in_fd,
|
||||||
off_t *offset, size_t count)
|
off_t *offset, size_t count)
|
||||||
{
|
{
|
||||||
int ret = EXIT_SUCCESS;
|
int ret = EXIT_SUCCESS;
|
||||||
off_t orig = 0;
|
off_t orig = 0;
|
||||||
@@ -617,7 +617,7 @@ static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
|
|||||||
|
|
||||||
if (priv->todo_prio >= 0) {
|
if (priv->todo_prio >= 0) {
|
||||||
ret = setsockopt(priv->sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
ret = setsockopt(priv->sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
||||||
&priv->todo_prio, sizeof(priv->todo_prio));
|
&priv->todo_prio, sizeof(priv->todo_prio));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
warn("set priority %i", priv->todo_prio);
|
warn("set priority %i", priv->todo_prio);
|
||||||
return EXIT_FAILURE;
|
return EXIT_FAILURE;
|
||||||
@@ -633,11 +633,11 @@ static int j1939cat_sock_prepare(struct j1939cat_priv *priv)
|
|||||||
}
|
}
|
||||||
|
|
||||||
sock_opt = SOF_TIMESTAMPING_SOFTWARE |
|
sock_opt = SOF_TIMESTAMPING_SOFTWARE |
|
||||||
SOF_TIMESTAMPING_OPT_CMSG |
|
SOF_TIMESTAMPING_OPT_CMSG |
|
||||||
SOF_TIMESTAMPING_TX_ACK |
|
SOF_TIMESTAMPING_TX_ACK |
|
||||||
SOF_TIMESTAMPING_TX_SCHED |
|
SOF_TIMESTAMPING_TX_SCHED |
|
||||||
SOF_TIMESTAMPING_OPT_STATS | SOF_TIMESTAMPING_OPT_TSONLY |
|
SOF_TIMESTAMPING_OPT_STATS | SOF_TIMESTAMPING_OPT_TSONLY |
|
||||||
SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_RX_SOFTWARE;
|
SOF_TIMESTAMPING_OPT_ID | SOF_TIMESTAMPING_RX_SOFTWARE;
|
||||||
|
|
||||||
if (setsockopt(priv->sock, SOL_SOCKET, SO_TIMESTAMPING,
|
if (setsockopt(priv->sock, SOL_SOCKET, SO_TIMESTAMPING,
|
||||||
(char *) &sock_opt, sizeof(sock_opt)))
|
(char *) &sock_opt, sizeof(sock_opt)))
|
||||||
|
|||||||
+4
-4
@@ -76,7 +76,7 @@ static struct {
|
|||||||
static const int ival_1 = 1;
|
static const int ival_1 = 1;
|
||||||
|
|
||||||
static char ctrlmsg[
|
static char ctrlmsg[
|
||||||
CMSG_SPACE(sizeof(struct timeval))
|
CMSG_SPACE(sizeof(struct timeval))
|
||||||
+ CMSG_SPACE(sizeof(uint8_t)) /* dest addr */
|
+ CMSG_SPACE(sizeof(uint8_t)) /* dest addr */
|
||||||
+ CMSG_SPACE(sizeof(uint64_t)) /* dest name */
|
+ CMSG_SPACE(sizeof(uint64_t)) /* dest name */
|
||||||
+ CMSG_SPACE(sizeof(uint8_t)) /* priority */
|
+ CMSG_SPACE(sizeof(uint8_t)) /* priority */
|
||||||
@@ -264,9 +264,9 @@ abs_time:
|
|||||||
struct tm tm;
|
struct tm tm;
|
||||||
tm = *localtime(&tdut.tv_sec);
|
tm = *localtime(&tdut.tv_sec);
|
||||||
printf("(%04u%02u%02uT%02u%02u%02u.%04llu)",
|
printf("(%04u%02u%02uT%02u%02u%02u.%04llu)",
|
||||||
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||||
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
tm.tm_hour, tm.tm_min, tm.tm_sec,
|
||||||
(unsigned long long)tdut.tv_usec/100);
|
(unsigned long long)tdut.tv_usec/100);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
printf(" %s ", libj1939_addr2str(&src));
|
printf(" %s ", libj1939_addr2str(&src));
|
||||||
|
|||||||
@@ -68,9 +68,9 @@ static struct {
|
|||||||
int pkt_len;
|
int pkt_len;
|
||||||
int priority;
|
int priority;
|
||||||
int defined;
|
int defined;
|
||||||
#define DEF_SRC 1
|
#define DEF_SRC 1
|
||||||
#define DEF_DST 2
|
#define DEF_DST 2
|
||||||
#define DEF_PRIO 4
|
#define DEF_PRIO 4
|
||||||
struct sockaddr_can src, dst;
|
struct sockaddr_can src, dst;
|
||||||
} s = {
|
} s = {
|
||||||
.priority = 6,
|
.priority = 6,
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ static inline void _put_id(char *buf, int end_offset, canid_t id)
|
|||||||
|
|
||||||
/* CAN DLC to real data length conversion helpers */
|
/* CAN DLC to real data length conversion helpers */
|
||||||
|
|
||||||
static const unsigned char dlc2len[] = {0, 1, 2, 3, 4, 5, 6, 7,
|
static const unsigned char dlc2len[] = {
|
||||||
8, 12, 16, 20, 24, 32, 48, 64};
|
0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
|
||||||
|
|
||||||
/* get data length from raw data length code (DLC) */
|
/* get data length from raw data length code (DLC) */
|
||||||
unsigned char can_fd_dlc2len(unsigned char dlc)
|
unsigned char can_fd_dlc2len(unsigned char dlc)
|
||||||
@@ -92,16 +92,17 @@ unsigned char can_fd_dlc2len(unsigned char dlc)
|
|||||||
return dlc2len[dlc & 0x0F];
|
return dlc2len[dlc & 0x0F];
|
||||||
}
|
}
|
||||||
|
|
||||||
static const unsigned char len2dlc[] = {0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
|
static const unsigned char len2dlc[] = {
|
||||||
9, 9, 9, 9, /* 9 - 12 */
|
0, 1, 2, 3, 4, 5, 6, 7, 8, /* 0 - 8 */
|
||||||
10, 10, 10, 10, /* 13 - 16 */
|
9, 9, 9, 9, /* 9 - 12 */
|
||||||
11, 11, 11, 11, /* 17 - 20 */
|
10, 10, 10, 10, /* 13 - 16 */
|
||||||
12, 12, 12, 12, /* 21 - 24 */
|
11, 11, 11, 11, /* 17 - 20 */
|
||||||
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
|
12, 12, 12, 12, /* 21 - 24 */
|
||||||
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
|
13, 13, 13, 13, 13, 13, 13, 13, /* 25 - 32 */
|
||||||
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
|
14, 14, 14, 14, 14, 14, 14, 14, /* 33 - 40 */
|
||||||
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
|
14, 14, 14, 14, 14, 14, 14, 14, /* 41 - 48 */
|
||||||
15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
|
15, 15, 15, 15, 15, 15, 15, 15, /* 49 - 56 */
|
||||||
|
15, 15, 15, 15, 15, 15, 15, 15}; /* 57 - 64 */
|
||||||
|
|
||||||
/* map the sanitized data length to an appropriate data length code */
|
/* map the sanitized data length to an appropriate data length code */
|
||||||
unsigned char can_fd_len2dlc(unsigned char len)
|
unsigned char can_fd_len2dlc(unsigned char len)
|
||||||
@@ -154,7 +155,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int parse_canframe(char *cs, cu_t *cu)
|
int parse_canframe(char *cs, union cfu *cu)
|
||||||
{
|
{
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
@@ -169,21 +170,23 @@ int parse_canframe(char *cs, cu_t *cu)
|
|||||||
|
|
||||||
memset(cu, 0, sizeof(*cu)); /* init CAN CC/FD/XL frame, e.g. LEN = 0 */
|
memset(cu, 0, sizeof(*cu)); /* init CAN CC/FD/XL frame, e.g. LEN = 0 */
|
||||||
|
|
||||||
if (len < 4)
|
if (len >= 4 && cs[3] == CANID_DELIM) { /* 3 digits SFF CAN ID */
|
||||||
return 0;
|
|
||||||
|
|
||||||
if (cs[3] == CANID_DELIM) { /* 3 digits SFF */
|
idx = 4; /* start of frame data */
|
||||||
|
|
||||||
idx = 4;
|
/* get 3 digits SFF CAN ID value */
|
||||||
for (i = 0; i < 3; i++) {
|
for (i = 0; i < 3; i++) {
|
||||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||||
return 0;
|
return 0;
|
||||||
cu->cc.can_id |= tmp << (2 - i) * 4;
|
cu->cc.can_id |= tmp << (2 - i) * 4;
|
||||||
}
|
}
|
||||||
|
|
||||||
} else if (cs[5] == CANID_DELIM) { /* 5 digits CAN XL VCID/PRIO*/
|
} else if (len >= 21 && cs[5] == CANID_DELIM && cs[20] == CANID_DELIM) {
|
||||||
|
/* 5 digits CAN XL VCID/PRIO - but also check for 2nd '#' here */
|
||||||
|
|
||||||
idx = 6;
|
idx = 6; /* start of CAN XL frame extra content (AF, SDT, etc) */
|
||||||
|
|
||||||
|
/* get 5 digits CAN XL VCID/PRIO */
|
||||||
for (i = 0; i < 5; i++) {
|
for (i = 0; i < 5; i++) {
|
||||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -195,9 +198,11 @@ int parse_canframe(char *cs, cu_t *cu)
|
|||||||
cu->xl.prio &= CANXL_PRIO_MASK;
|
cu->xl.prio &= CANXL_PRIO_MASK;
|
||||||
cu->xl.prio |= tmp;
|
cu->xl.prio |= tmp;
|
||||||
|
|
||||||
} else if (cs[8] == CANID_DELIM) { /* 8 digits EFF */
|
} else if (len >= 9 && cs[8] == CANID_DELIM) { /* 8 digits EFF CAN ID */
|
||||||
|
|
||||||
idx = 9;
|
idx = 9; /* start of frame data */
|
||||||
|
|
||||||
|
/* get 8 digits EFF CAN ID value */
|
||||||
for (i = 0; i < 8; i++) {
|
for (i = 0; i < 8; i++) {
|
||||||
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
if ((tmp = asc2nibble(cs[i])) > 0x0F)
|
||||||
return 0;
|
return 0;
|
||||||
@@ -238,11 +243,12 @@ int parse_canframe(char *cs, cu_t *cu)
|
|||||||
cu->fd.flags |= CANFD_FDF; /* dual-use */
|
cu->fd.flags |= CANFD_FDF; /* dual-use */
|
||||||
idx += 2;
|
idx += 2;
|
||||||
|
|
||||||
} else if (cs[idx + 14] == CANID_DELIM) { /* CAN XL frame '#80:00:11223344#' */
|
} else if (idx == 6) { /* CAN XL frame extra content '#80:00:11223344#' */
|
||||||
maxdlen = CANXL_MAX_DLEN;
|
maxdlen = CANXL_MAX_DLEN;
|
||||||
mtu = CANXL_MTU;
|
mtu = CANXL_MTU;
|
||||||
data = cu->xl.data; /* fill CAN XL data */
|
data = cu->xl.data; /* overwrite pointer to CAN XL data */
|
||||||
|
|
||||||
|
/* get CAN XL frame extra content */
|
||||||
if ((cs[idx + 2] != XL_HDR_DELIM) || (cs[idx + 5] != XL_HDR_DELIM))
|
if ((cs[idx + 2] != XL_HDR_DELIM) || (cs[idx + 5] != XL_HDR_DELIM))
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
@@ -276,6 +282,7 @@ int parse_canframe(char *cs, cu_t *cu)
|
|||||||
idx++; /* skip CANID_DELIM */
|
idx++; /* skip CANID_DELIM */
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* copy CAN frame data content */
|
||||||
for (i = 0, dlen = 0; i < maxdlen; i++) {
|
for (i = 0, dlen = 0; i < maxdlen; i++) {
|
||||||
if (cs[idx] == DATA_SEPERATOR) /* skip (optional) separator */
|
if (cs[idx] == DATA_SEPERATOR) /* skip (optional) separator */
|
||||||
idx++;
|
idx++;
|
||||||
@@ -308,7 +315,7 @@ int parse_canframe(char *cs, cu_t *cu)
|
|||||||
return mtu;
|
return mtu;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep)
|
int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep)
|
||||||
{
|
{
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
@@ -432,7 +439,7 @@ int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep)
|
|||||||
return offset;
|
return offset;
|
||||||
}
|
}
|
||||||
|
|
||||||
int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view)
|
int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view)
|
||||||
{
|
{
|
||||||
/* documentation see lib.h */
|
/* documentation see lib.h */
|
||||||
|
|
||||||
@@ -777,8 +784,8 @@ static int snprintf_error_ctrl(char *buf, size_t len, const struct canfd_frame *
|
|||||||
|
|
||||||
n += snprintf(buf + n, len - n, "{");
|
n += snprintf(buf + n, len - n, "{");
|
||||||
n += snprintf_error_data(buf + n, len - n, cf->data[1],
|
n += snprintf_error_data(buf + n, len - n, cf->data[1],
|
||||||
controller_problems,
|
controller_problems,
|
||||||
ARRAY_SIZE(controller_problems));
|
ARRAY_SIZE(controller_problems));
|
||||||
n += snprintf(buf + n, len - n, "}");
|
n += snprintf(buf + n, len - n, "}");
|
||||||
|
|
||||||
return n;
|
return n;
|
||||||
@@ -793,8 +800,8 @@ static int snprintf_error_prot(char *buf, size_t len, const struct canfd_frame *
|
|||||||
|
|
||||||
n += snprintf(buf + n, len - n, "{{");
|
n += snprintf(buf + n, len - n, "{{");
|
||||||
n += snprintf_error_data(buf + n, len - n, cf->data[2],
|
n += snprintf_error_data(buf + n, len - n, cf->data[2],
|
||||||
protocol_violation_types,
|
protocol_violation_types,
|
||||||
ARRAY_SIZE(protocol_violation_types));
|
ARRAY_SIZE(protocol_violation_types));
|
||||||
n += snprintf(buf + n, len - n, "}{");
|
n += snprintf(buf + n, len - n, "}{");
|
||||||
if (cf->data[3] > 0 &&
|
if (cf->data[3] > 0 &&
|
||||||
cf->data[3] < ARRAY_SIZE(protocol_violation_locations))
|
cf->data[3] < ARRAY_SIZE(protocol_violation_locations))
|
||||||
@@ -819,7 +826,7 @@ static int snprintf_error_cnt(char *buf, size_t len, const struct canfd_frame *c
|
|||||||
}
|
}
|
||||||
|
|
||||||
int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf,
|
int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf,
|
||||||
const char* sep)
|
const char* sep)
|
||||||
{
|
{
|
||||||
canid_t class, mask;
|
canid_t class, mask;
|
||||||
int i, n = 0, classes = 0;
|
int i, n = 0, classes = 0;
|
||||||
@@ -858,7 +865,7 @@ int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf
|
|||||||
n += tmp_n;
|
n += tmp_n;
|
||||||
if (mask == CAN_ERR_LOSTARB)
|
if (mask == CAN_ERR_LOSTARB)
|
||||||
n += snprintf_error_lostarb(buf + n, len - n,
|
n += snprintf_error_lostarb(buf + n, len - n,
|
||||||
cf);
|
cf);
|
||||||
if (mask == CAN_ERR_CRTL)
|
if (mask == CAN_ERR_CRTL)
|
||||||
n += snprintf_error_ctrl(buf + n, len - n, cf);
|
n += snprintf_error_ctrl(buf + n, len - n, cf);
|
||||||
if (mask == CAN_ERR_PROT)
|
if (mask == CAN_ERR_PROT)
|
||||||
@@ -878,7 +885,7 @@ int snprintf_can_error_frame(char *buf, size_t len, const struct canfd_frame *cf
|
|||||||
}
|
}
|
||||||
|
|
||||||
int64_t timespec_diff_ms(struct timespec *ts1,
|
int64_t timespec_diff_ms(struct timespec *ts1,
|
||||||
struct timespec *ts2)
|
struct timespec *ts2)
|
||||||
{
|
{
|
||||||
int64_t diff = (ts1->tv_sec - ts2->tv_sec) * 1000;
|
int64_t diff = (ts1->tv_sec - ts2->tv_sec) * 1000;
|
||||||
|
|
||||||
|
|||||||
@@ -49,6 +49,8 @@
|
|||||||
#include <stddef.h>
|
#include <stddef.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
|
#include <linux/can.h>
|
||||||
|
|
||||||
#ifdef DEBUG
|
#ifdef DEBUG
|
||||||
#define pr_debug(fmt, args...) printf(fmt, ##args)
|
#define pr_debug(fmt, args...) printf(fmt, ##args)
|
||||||
#else
|
#else
|
||||||
@@ -57,11 +59,11 @@ static inline int pr_debug(const char* fmt, ...) {return 0;}
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
/* CAN CC/FD/XL frame union */
|
/* CAN CC/FD/XL frame union */
|
||||||
typedef union {
|
union cfu {
|
||||||
struct can_frame cc;
|
struct can_frame cc;
|
||||||
struct canfd_frame fd;
|
struct canfd_frame fd;
|
||||||
struct canxl_frame xl;
|
struct canxl_frame xl;
|
||||||
} cu_t;
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The buffer size for ASCII CAN frame string representations
|
* The buffer size for ASCII CAN frame string representations
|
||||||
@@ -108,7 +110,7 @@ int hexstring2data(char *arg, unsigned char *data, int maxdlen);
|
|||||||
*
|
*
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int parse_canframe(char *cs, cu_t *cu);
|
int parse_canframe(char *cs, union cfu *cu);
|
||||||
/*
|
/*
|
||||||
* Transfers a valid ASCII string describing a CAN frame into the CAN union
|
* Transfers a valid ASCII string describing a CAN frame into the CAN union
|
||||||
* containing CAN CC/FD/XL structs.
|
* containing CAN CC/FD/XL structs.
|
||||||
@@ -178,7 +180,7 @@ int parse_canframe(char *cs, cu_t *cu);
|
|||||||
* - CAN FD frames do not have a RTR bit
|
* - CAN FD frames do not have a RTR bit
|
||||||
*/
|
*/
|
||||||
|
|
||||||
int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep);
|
int snprintf_canframe(char *buf, size_t size, union cfu *cu, int sep);
|
||||||
/*
|
/*
|
||||||
* Creates a CAN frame hexadecimal output in compact format.
|
* Creates a CAN frame hexadecimal output in compact format.
|
||||||
* The CAN data[] is separated by '.' when sep != 0.
|
* The CAN data[] is separated by '.' when sep != 0.
|
||||||
@@ -211,7 +213,7 @@ int snprintf_canframe(char *buf, size_t size, cu_t *cu, int sep);
|
|||||||
|
|
||||||
#define SWAP_DELIMITER '`'
|
#define SWAP_DELIMITER '`'
|
||||||
|
|
||||||
int snprintf_long_canframe(char *buf, size_t size, cu_t *cu, int view);
|
int snprintf_long_canframe(char *buf, size_t size, union cfu *cu, int view);
|
||||||
/*
|
/*
|
||||||
* Creates a CAN frame hexadecimal output in user readable format.
|
* Creates a CAN frame hexadecimal output in user readable format.
|
||||||
*
|
*
|
||||||
|
|||||||
@@ -183,7 +183,7 @@ static void canfd_asc(struct canfd_frame *cf, int devno, int mtu,
|
|||||||
fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags);
|
fprintf(outfile, " %8d %4d %8X 0 0 0 0 0", 130000, 130, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void canxl_asc(cu_t *cu, int devno, int mtu,
|
static void canxl_asc(union cfu *cu, int devno, int mtu,
|
||||||
char *extra_info, FILE *outfile)
|
char *extra_info, FILE *outfile)
|
||||||
{
|
{
|
||||||
char id[10];
|
char id[10];
|
||||||
@@ -314,7 +314,7 @@ int main(int argc, char **argv)
|
|||||||
{
|
{
|
||||||
static char buf[BUFSZ], device[DEVSZ], afrbuf[AFRSZ], extra_info[EXTRASZ];
|
static char buf[BUFSZ], device[DEVSZ], afrbuf[AFRSZ], extra_info[EXTRASZ];
|
||||||
|
|
||||||
static cu_t cu;
|
static union cfu cu;
|
||||||
static struct timeval tv, start_tv;
|
static struct timeval tv, start_tv;
|
||||||
FILE *infile = stdin;
|
FILE *infile = stdin;
|
||||||
FILE *outfile = stdout;
|
FILE *outfile = stdout;
|
||||||
|
|||||||
+1
-1
@@ -68,7 +68,7 @@
|
|||||||
int main(void)
|
int main(void)
|
||||||
{
|
{
|
||||||
static char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ];
|
static char buf[BUFSZ], timestamp[TIMESZ], device[DEVSZ], afrbuf[AFRSZ];
|
||||||
static cu_t cu;
|
static union cfu cu;
|
||||||
int mtu;
|
int mtu;
|
||||||
|
|
||||||
while (fgets(buf, BUFSZ-1, stdin)) {
|
while (fgets(buf, BUFSZ-1, stdin)) {
|
||||||
|
|||||||
@@ -72,8 +72,7 @@ int mcp251xfd_regmap_read(struct mcp251xfd_priv *priv,
|
|||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
/* maybe it's something like "spi0.0" */
|
/* maybe it's something like "spi0.0" */
|
||||||
tmp = strchr(file_path, '/');
|
if (strchr(file_path, '/'))
|
||||||
if (tmp)
|
|
||||||
return -ENOENT;
|
return -ENOENT;
|
||||||
|
|
||||||
/* first try literally */
|
/* first try literally */
|
||||||
|
|||||||
+5
-5
@@ -197,7 +197,7 @@ int main(int argc, char *argv[])
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_SEND_PRIO, &%i);\n", todo_prio);
|
fprintf(stderr, "- setsockopt(, SOL_CAN_J1939, SO_J1939_SEND_PRIO, &%i);\n", todo_prio);
|
||||||
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
||||||
&todo_prio, sizeof(todo_prio));
|
&todo_prio, sizeof(todo_prio));
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
err(1, "set priority %i", todo_prio);
|
err(1, "set priority %i", todo_prio);
|
||||||
}
|
}
|
||||||
@@ -246,7 +246,7 @@ int main(int argc, char *argv[])
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "- sendto(, <dat>, %i, 0, %s, %zi);\n", todo_send, libj1939_addr2str(&peername), sizeof(peername));
|
fprintf(stderr, "- sendto(, <dat>, %i, 0, %s, %zi);\n", todo_send, libj1939_addr2str(&peername), sizeof(peername));
|
||||||
ret = sendto(sock, dat, todo_send, 0,
|
ret = sendto(sock, dat, todo_send, 0,
|
||||||
(void *)&peername, sizeof(peername));
|
(void *)&peername, sizeof(peername));
|
||||||
} else {
|
} else {
|
||||||
/*
|
/*
|
||||||
* we may do sendto(sock, dat, todo_send, 0, NULL, 0)
|
* we may do sendto(sock, dat, todo_send, 0, NULL, 0)
|
||||||
@@ -273,7 +273,7 @@ int main(int argc, char *argv[])
|
|||||||
fprintf(stderr, "- recvfrom(, <dat>, %zi, 0, &<peername>, %zi);\n", sizeof(peername), sizeof(peername));
|
fprintf(stderr, "- recvfrom(, <dat>, %zi, 0, &<peername>, %zi);\n", sizeof(peername), sizeof(peername));
|
||||||
peernamelen = sizeof(peername);
|
peernamelen = sizeof(peername);
|
||||||
ret = recvfrom(sock, dat, sizeof(dat), 0,
|
ret = recvfrom(sock, dat, sizeof(dat), 0,
|
||||||
(void *)&peername, &peernamelen);
|
(void *)&peername, &peernamelen);
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
if (EINTR == errno) {
|
if (EINTR == errno) {
|
||||||
if (verbose)
|
if (verbose)
|
||||||
@@ -287,7 +287,7 @@ int main(int argc, char *argv[])
|
|||||||
if (verbose)
|
if (verbose)
|
||||||
fprintf(stderr, "- sendto(, <dat>, %i, 0, %s, %i);\n", ret, libj1939_addr2str(&peername), peernamelen);
|
fprintf(stderr, "- sendto(, <dat>, %i, 0, %s, %i);\n", ret, libj1939_addr2str(&peername), peernamelen);
|
||||||
ret = sendto(sock, dat, ret, 0,
|
ret = sendto(sock, dat, ret, 0,
|
||||||
(void *)&peername, peernamelen);
|
(void *)&peername, peernamelen);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
err(1, "sendto");
|
err(1, "sendto");
|
||||||
}
|
}
|
||||||
@@ -297,7 +297,7 @@ int main(int argc, char *argv[])
|
|||||||
if (todo_names && peername.can_addr.j1939.name)
|
if (todo_names && peername.can_addr.j1939.name)
|
||||||
printf("%016llx ", peername.can_addr.j1939.name);
|
printf("%016llx ", peername.can_addr.j1939.name);
|
||||||
printf("%02x %05x:", peername.can_addr.j1939.addr,
|
printf("%02x %05x:", peername.can_addr.j1939.addr,
|
||||||
peername.can_addr.j1939.pgn);
|
peername.can_addr.j1939.pgn);
|
||||||
for (i = 0, j = 0; i < ret; ++i, j++) {
|
for (i = 0, j = 0; i < ret; ++i, j++) {
|
||||||
if (j == 8) {
|
if (j == 8) {
|
||||||
printf("\n%05x ", i);
|
printf("\n%05x ", i);
|
||||||
|
|||||||
Reference in New Issue
Block a user