guowenxue
2024-07-26 9cf87703eb60e121b47e6d577ea2bc6b63bd4ac4
commit | author | age
1e563e 1 /*********************************************************************************
G 2  *      Copyright:  (C) 2024 LingYun IoT System Studio
3  *                  All rights reserved.
4  *
5  *       Filename:  can_test.c
6  *    Description:  This file is socket CAN loop test program
7  *
8  *        Version:  1.0.0(05/26/2024)
9  *         Author:  Guo Wenxue <guowenxue@gmail.com>
10  *      ChangeLog:  1, Release initial version on "05/26/2024 05:42:49 PM"
11  *
12  ********************************************************************************/
13
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <string.h>
17 #include <unistd.h>
18 #include <sys/ioctl.h>
19 #include <net/if.h>
20 #include <sys/socket.h>
21 #include <linux/can.h>
22 #include <linux/can/raw.h>
23 #include <getopt.h>
24
25 // 打印使用帮助信息
26 void print_usage(const char *progname)
27 {
28     printf("Usage: %s -i <can_interface> -m <mode>\n", progname);
29     printf("Options:\n");
30     printf("  -i, --interface    CAN interface (e.g., can0)\n");
31     printf("  -m, --mode         Mode: send or receive\n");
32     printf("  -h, --help         Display this help message\n");
33 }
34
35 void send_can_message(const char *ifname)
36 {
37     int                     fd;
38     struct sockaddr_can     addr;
39     struct ifreq            ifr;
40     struct can_frame        frame;
41
42     // 创建socket
43     fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
44     if (fd < 0)
45     {
46         perror("socket");
47         exit(1);
48     }
49
50     // 指定CAN接口
51     strcpy(ifr.ifr_name, ifname);
52     ioctl(fd, SIOCGIFINDEX, &ifr);
53     addr.can_family = AF_CAN;
54     addr.can_ifindex = ifr.ifr_ifindex;
55
56     // 绑定socket到CAN接口
57     if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
58     {
59         perror("bind");
60         exit(1);
61     }
62
63     // 构造CAN帧
64     frame.can_id = 0x123; // 设置CAN ID
65     frame.can_dlc = 2;    // 数据长度
66     frame.data[0] = 0x11; // 数据
67     frame.data[1] = 0x22; // 数据
68
69     // 发送CAN帧
70     if (write(fd, &frame, sizeof(struct can_frame)) != sizeof(struct can_frame))
71     {
72         perror("write");
73         exit(1);
74     }
75
76     // 关闭socket
77     close(fd);
78 }
79
80 void receive_can_message(const char *ifname)
81 {
82     int                     fd;
83     struct sockaddr_can     addr;
84     struct ifreq            ifr;
85     struct can_frame        frame;
86
87     // 创建socket
88     fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
89     if (fd < 0) {
90         perror("socket");
91         exit(1);
92     }
93
94     // 指定CAN接口
95     strcpy(ifr.ifr_name, ifname);
96     ioctl(fd, SIOCGIFINDEX, &ifr);
97     addr.can_family = AF_CAN;
98     addr.can_ifindex = ifr.ifr_ifindex;
99
100     // 绑定socket到CAN接口
101     if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
102     {
103         perror("bind");
104         exit(1);
105     }
106
107     // 接收CAN帧
108     while (1)
109     {
110         int nbytes = read(fd, &frame, sizeof(struct can_frame));
111         if (nbytes < 0)
112         {
113             perror("read");
114             exit(1);
115         }
116
117         if (nbytes < sizeof(struct can_frame))
118         {
119             fprintf(stderr, "read: incomplete CAN frame\n");
120             exit(1);
121         }
122
123         // 打印接收到的CAN帧
124         printf("Received CAN frame: ID=0x%X DLC=%d data=", frame.can_id, frame.can_dlc);
125         for (int i = 0; i < frame.can_dlc; i++)
126             printf("%02X ", frame.data[i]);
127
128         printf("\n");
129     }
130
131     // 关闭socket
132     close(fd);
133 }
134
135 int main(int argc, char **argv)
136 {
137     int              opt, index = 0;
138     const char      *ifname = NULL;
139     const char      *mode = NULL;
140
141     // 定义长选项
142     static struct option long_options[] =
143     {
144         {"interface", required_argument, 0, 'i'},
145         {"mode",      required_argument, 0, 'm'},
146         {"help",      no_argument,       0, 'h'},
147         {0, 0, 0, 0}
148     };
149
150     while ((opt = getopt_long(argc, argv, "i:m:h", long_options, &index)) != -1)
151     {
152         switch (opt) {
153             case 'i':
154                 ifname = optarg;
155                 break;
156             case 'm':
157                 mode = optarg;
158                 break;
159             case 'h':
160                 print_usage(argv[0]);
161                 return 0;
162             default:
163                 print_usage(argv[0]);
164                 return 1;
165         }
166     }
167
168     if (ifname == NULL || mode == NULL)
169     {
170         print_usage(argv[0]);
171         return 1;
172     }
173
174     if (strcmp(mode, "send") == 0)
175     {
176         send_can_message(ifname);
177     }
178     else if (strcmp(mode, "receive") == 0)
179     {
180         receive_can_message(ifname);
181     }
182     else
183     {
184         fprintf(stderr, "Invalid mode: %s\n", mode);
185         print_usage(argv[0]);
186         return 1;
187     }
188
189     return 0;
190 }
191