2 * Copyright 2017 Max Staudt
4 * This program is free software: you can redistribute it and/or modify
5 * it under the terms of the GNU General Public License 2 as published
6 * by the Free Software Foundation.
14 #include <sys/types.h>
15 #include <sys/socket.h>
16 #include <linux/can.h>
17 #include <linux/can/raw.h>
19 #include <sys/ioctl.h>
24 static unsigned hex2bin(char c) {
25 if (c >= '0' && c <= '9') {
27 } else if (c >= 'A' && c <= 'F') {
29 } else if (c >= 'a' && c <= 'f') {
38 static int net_init(char *ifname)
42 struct sockaddr_can addr;
45 s = socket(PF_CAN, SOCK_RAW, CAN_RAW);
51 /* Convert interface name to index */
52 memset(&ifr.ifr_name, 0, sizeof(ifr.ifr_name));
53 strncpy(ifr.ifr_name, ifname, IFNAMSIZ);
54 if (ioctl(s, SIOCGIFINDEX, &ifr) < 0) {
55 perror("SIOCGIFINDEX");
59 /* Open the CAN interface */
60 memset(&addr, 0, sizeof(addr));
61 addr.can_family = AF_CAN;
62 addr.can_ifindex = ifr.ifr_ifindex;
63 if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
68 recv_own_msgs = 1; /* 0 = disabled (default), 1 = enabled */
69 setsockopt(s, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
70 &recv_own_msgs, sizeof(recv_own_msgs));
77 static void can_tx(int socket, struct can_frame *frame)
81 ret = write(socket, frame, sizeof(*frame));
82 if (ret != sizeof(*frame)) {
83 perror("write to CAN socket");
91 int main(int argc, char **argv)
95 struct can_frame frame;
97 struct BAP_Frame *bap_frame;
99 unsigned bap_multiframe;
105 printf("syntax: %s IFNAME CAN_ID multiframe bap_opcode bap_node bap_port bap_data\n", argv[0]);
109 /* Parse arguments */
110 can_id = strtoul(argv[2], NULL, 0);
111 bap_multiframe = strtoul(argv[3], NULL, 0);
112 bap_opcode = strtoul(argv[4], NULL, 0);
113 bap_node = strtoul(argv[5], NULL, 0);
114 bap_port = strtoul(argv[6], NULL, 0);
118 bap = vw_bap_txer_alloc();
120 printf("Out of memory allocating BAP TXer struct.\n");
124 bap_frame = vw_bap_frame_alloc();
126 printf("Out of memory allocating BAP frame.\n");
133 bap_frame->is_multiframe = !(!bap_multiframe);
134 bap_frame->opcode = bap_opcode & 0x7;
135 bap_frame->node = bap_node & 0x3f;
136 bap_frame->port = bap_port & 0x3f;
140 while(bap_frame->len < 4095) {
142 unsigned i = bap_frame->len;
144 if (!argv[7][2*i] || !argv[7][2*i + 1]) {
148 high = hex2bin(argv[7][2*i]);
152 low = hex2bin(argv[7][2*i + 1]);
157 bap_frame->data[i] = (high << 4) | low;
163 s = net_init(argv[1]);
168 printf("Will send frame:\n");
169 vw_bap_frame_dump(bap_frame);
171 ret = vw_bap_txer_queue(bap, bap_frame, &frame);
172 frame.can_id = can_id;
175 /* HACK since we don't have continuation frames yet */
185 retval = select(s+1, NULL, &wfds, NULL, NULL);
186 /* We currently rely on Linux timeout behavior here,
187 * i.e. the timeout now reflects the remaining time */
191 } else if (!retval) {
192 /* Timeout, we NEED to check this first */
193 } else if (FD_ISSET(s, &wfds)) {
201 vw_bap_txer_free(bap);