Skip to content

SocketCAN Programming Practice

API

SocketCAN official API: https://docs.kernel.org/networking/can.html

Examples

kcanfdtest

KH-UCANFD_Linux_SDK contains test code such as kcanfd_test.c, cantx_1KHz.c, etc. Following is part of code in kcanfd_test.c, used for creating socket, sending, and receiving:

For detailed code content, you can download to view: https://gitee.com/ChengDu-KunHong/KH-UCANFD_Linux_SDK/releases/download/latest/KH-UCANFD_Linux_SDK.zip

Creating Socket

c
if ((sockfd = socket(family, type, proto)) < 0) // Create CAN raw socket
{
    perror("socket");
    return 1;
}

if (echo_gen) // Enable echo mode { if (setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &enable_socket_option, sizeof(enable_socket_option)) == -1) { perror("setsockopt CAN_RAW_RECV_OWN_MSGS"); return 1; } }

if (is_can_fd) // Enable CAN FD frames { if (setsockopt(sockfd, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &enable_socket_option, sizeof(enable_socket_option)) == -1) { perror("setsockopt CAN_RAW_FD_FRAMES"); return 1; } }


#### Sending Frames

```c
static int send_frame(struct canfd_frame *frame)
{
    ssize_t ret, len;

    if (is_can_fd)
        len = sizeof(struct canfd_frame);
    else
        len = sizeof(struct can_frame);

    if (bit_rate_switch)
        frame->flags |= CANFD_BRS;

    while ((ret = send(sockfd, frame, len, 0)) != len)
    {
        if (ret >= 0)
        {
            fprintf(stderr, "send returned %zd", ret);
            return -1;
        }
        if (errno != ENOBUFS)
        {
            perror("send failed");
            return -1;
        }
        if (verbose)
        {
            printf("n");
            fflush(stdout);
        }
    }
    return 0;
}

Receiving Frames

c
static int recv_frame(struct canfd_frame *frame, int *flags)
{
    struct iovec iov = {
        .iov_base = frame,
        .iov_len = is_can_fd ? sizeof(struct canfd_frame) : sizeof(struct can_frame),
    };
    struct msghdr msg = {
        .msg_iov = &iov,
        .msg_iovlen = 1,
    };
    ssize_t ret;

    ret = recvmsg(sockfd, &msg, 0);
    if (ret < 0)
    {
        perror("recvmsg() failed");
        return -1;
    }
    if ((size_t)ret != iov.iov_len)
    {
        fprintf(stderr, "recvmsg() returned %zd", ret);
        return -1;
    }
    if (flags)
        *flags = msg.msg_flags;

    return 0;
}

can-utils

can-utils is implemented based on SocketCAN. All tools provided in the project are good reference examples.

can-utils open source project: https://gitee.com/ChengDu-KunHong/can-utils

openarm_can

openarm_can is part of the OpenArm project, which is a library for CAN communication, providing applications and test code specifically for motors, which can serve as reference.

openarmcan open source project: https://gitee.com/ChengDu-KunHong/openarmcan

Driving Intelligent Connections, Empowering the Future