-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathcanping.c
166 lines (140 loc) · 3.72 KB
/
canping.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
#include <inttypes.h>
#include <libgen.h>
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <net/if.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <linux/can.h>
#include <linux/can/raw.h>
void print_usage(char* argv0) {
char* my_name = basename(argv0);
printf("%s: Send a counter message to CAN Bus every second.\n\n", my_name);
printf("Usage:\n");
printf(" %s -n [interface] -i [id]\n", my_name);
printf(" -n [interface] : CAN interface. Required.\n");
printf(" -i [id] : CAN ID for pings. Default: 0x7FF\n");
printf("Example:\n");
printf(" %s -n can0\n", my_name);
}
int parse_cmdline(int argc, char** argv, char *ifname, canid_t *id) {
int c;
opterr = 0;
while ((c = getopt(argc, argv, "hi:n:")) != -1)
switch (c) {
case 'h':
print_usage(argv[0]);
return 1;
case 'i':
*id = strtoumax(optarg, NULL, 0);
break;
case 'n':
strncpy(ifname, optarg, IFNAMSIZ-1);
break;
case '?':
if (optopt == 'i' || optopt == 'n')
fprintf (stderr, "Option -%c requires an argument.\n", optopt);
else if (isprint (optopt))
fprintf (stderr, "Unknown option `-%c'.\n", optopt);
else
fprintf (stderr,
"Unknown option character `\\x%x'.\n",
optopt);
print_usage(argv[0]);
return 1;
default:
print_usage(argv[0]);
abort();
}
if (ifname[0] == '\0') {
fputs("option -n [ifname] is required.\n", stderr);
print_usage(argv[0]);
return 1;
}
return 0;
}
int main(int argc, char** argv) {
int status;
int sfd;
struct sockaddr_can addr;
struct can_frame frame;
struct ifreq ifr;
struct sigaction sa;
struct itimerval timer;
// default values for opts
char ifname[IFNAMSIZ] = "";
canid_t id = 0x7FF;
// parse opts
status = parse_cmdline(argc, argv, ifname, &id);
if (status != 0) {
return EXIT_FAILURE;
}
printf("using interface %s and id %02X\n", ifname, id);
// open can socket
sfd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (sfd < 0) {
perror("opening socket");
return EXIT_FAILURE;
}
// find interface index
strcpy(ifr.ifr_name, ifname);
status = ioctl(sfd, SIOCGIFINDEX, &ifr);
if (status < 0) {
perror("finding interface index");
return EXIT_FAILURE;
}
// init can socket binding
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
// bind can socket
status = bind(sfd, (struct sockaddr *)&addr, sizeof(addr));
if (status < 0) {
perror("binding socket");
return EXIT_FAILURE;
}
// init can frame
frame.can_id = id;
frame.can_dlc = 1;
// define timer callback
void ping(int signum) {
static unsigned char counter = 0;
int nbytes;
#ifdef DEBUG
printf("ping : %02X\n", counter);
#endif
frame.data[0] = counter++;
nbytes = write(sfd, &frame, sizeof(struct can_frame));
if (nbytes != sizeof(frame)) {
fprintf(stderr, "ERROR: Wrote %d bytes, expected %u\n", nbytes, sizeof(frame));
//abort();
}
}
// set timer callback
memset (&sa, 0, sizeof(sa));
sa.sa_handler = &ping;
status = sigaction(SIGALRM, &sa, NULL);
if (status < 0) {
perror("setting sigaction");
return EXIT_FAILURE;
}
// init timer
timer.it_value.tv_sec = 1;
timer.it_value.tv_usec = 0;
timer.it_interval.tv_sec = 0;
timer.it_interval.tv_usec = 500000;
// start timer
status = setitimer (ITIMER_REAL, &timer, NULL);
if (status < 0) {
perror("setting timer");
return EXIT_FAILURE;
}
while (1) {
pause();
}
return EXIT_SUCCESS;
}