can-utils source code analysis cansend

foreword

This article mainly introduces the source code analysis of the send function cansend in socketCan.

code

/*
 * cansend.c - simple command line tool to send CAN-frames via CAN_RAW sockets
 *
 * Copyright (c) 2002-2007 Volkswagen Group Electronic Research
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions and the following disclaimer.
 * 2. Redistributions in binary form must reproduce the above copyright
 *    notice, this list of conditions and the following disclaimer in the
 *    documentation and/or other materials provided with the distribution.
 * 3. Neither the name of Volkswagen nor the names of its contributors
 *    may be used to endorse or promote products derived from this software
 *    without specific prior written permission.
 *
 * Alternatively, provided that this notice is retained in full, this
 * software may be distributed under the terms of the GNU General
 * Public License ("GPL") version 2, in which case the provisions of the
 * GPL apply INSTEAD OF those given above.
 *
 * The provided data structures and external interfaces from this code
 * are not restricted to be used by modules with a GPL compatible license.
 *
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH
 * DAMAGE.
 *
 * Send feedback to <[email protected]>
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>

#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>

#include <linux/can.h>
#include <linux/can/raw.h>

#include "lib.h"

int main( )
{
    int s; /* can raw socket */ 
    int required_mtu;
    int mtu;
    int enable_canfd = 1;
    struct sockaddr_can addr;
    struct canfd_frame frame;
    struct ifreq ifr;
    
    char* input = "008#abcd1234cdef567830";
    /* parse CAN frame */
    required_mtu = parse_canframe(input, &frame);
    printf("required_mtu is %d\n", required_mtu);
    printf("CAN_MTU is %d\n", (long unsigned int)CAN_MTU);
    //printf("CANID_DELIM is %d\n", CANID_DELIM);//#-35-0x23.
    printf("IFNAMSIZ is %d\n", IFNAMSIZ);
    if (!required_mtu){
        fprintf(stderr, "\nWrong CAN-frame format! Try:\n\n");
        fprintf(stderr, "    <can_id>#{R|data}          for CAN 2.0 frames\n");
        fprintf(stderr, "    <can_id>##<flags>{data}    for CAN FD frames\n\n");
        fprintf(stderr, "<can_id> can have 3 (SFF) or 8 (EFF) hex chars\n");
        fprintf(stderr, "{data} has 0..8 (0..64 CAN FD) ASCII hex-values (optionally");
        fprintf(stderr, " separated by '.')\n");
        fprintf(stderr, "<flags> a single ASCII Hex value (0 .. F) which defines");
        fprintf(stderr, " canfd_frame.flags\n\n");
        fprintf(stderr, "e.g. 5A1#11.2233.44556677.88 / 123#DEADBEEF / 5AA# / ");
        fprintf(stderr, "123##1 / 213##311\n     1F334455#1122334455667788 / 123#R ");
        fprintf(stderr, "for remote transmission request.\n\n");
        return 1;
    }

    /* open socket */
    if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < 0) {
        perror("socket");
        return 1;
    }

    const char* ifrname = "can1";
    strcpy(ifr.ifr_name, ifrname);
    ifr.ifr_ifindex = if_nametoindex(ifr.ifr_name);
    if (!ifr.ifr_ifindex) {
        perror("if_nametoindex");
        return 1;
    }

    memset(&addr, 0, sizeof(addr));
    addr.can_family = AF_CAN;
    addr.can_ifindex = ifr.ifr_ifindex;
/*
    if (required_mtu > CAN_MTU) {

        //* check if the frame fits into the CAN netdevice
        if (ioctl(s, SIOCGIFMTU, &ifr) < 0) {
            perror("SIOCGIFMTU");
            return 1;
        }
        person = ifr.ifr_some;

        if (person! = CANFD_MTU) {
            printf("CAN interface is not CAN FD capable - sorry.\n");
            return 1;
        }

        //* interface is ok - try to switch the socket into CAN FD mode
        if (setsockopt(s, SOL_CAN_RAW, CAN_RAW_FD_FRAMES,
                   &enable_canfd, sizeof(enable_canfd))){
            printf("error when enabling CAN FD support\n");
            return 1;
        }

        //* ensure discrete CAN FD length values 0..8, 12, 16, 20, 24, 32, 64
        frame.len = can_dlc2len(can_len2dlc(frame.len));
    }
*/

    /* disable default receive filter on this RAW socket */
    /* This is obsolete as we do not read from the socket at all, but for */
    /* this reason we can remove the receive list in the Kernel to save a */
    /* little (really a very little!) CPU usage.                          */
    setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

    if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
        perror("bind");
        return 1;
    }

    /* send frame */
    printf("frame.len is %d\n", frame.len);
    printf("frame.can_id is %x\n", frame.can_id);
    if (write(s, &frame, required_mtu) != required_mtu) {
        perror("write");
        return 1;
    }

    close(s);

    return 0;
}
View Code

Parse

1. The format of the message;

    char* input = "008#abcd1234cdef567830";

Among them, '008 means can_id, which must be three-digit hexadecimal data, which can represent standard frame or extended frame; the symbol #" is the delimiter between can_id and can data, and the last data is the data of the message. The standard frame can only contain at most one time. It can send 8bits of data, and the excess data is automatically discarded;

2. The parse_canframe function, please refer to the lib.h and lib.c files for details;

int parse_canframe(char *cs, struct canfd_frame *cf);
 /* parse CAN frame */
 required_mtu = parse_canframe(input, &frame);

function -- Transfers a valid ASCII string decribing a CAN frame into struct canfd_frame.

3. Create socket;

s = socket(PF_CAN, SOCK_RAW, CAN_RAW)

Create socket socket

PF_CAN is a field bit, the same as AF_INET in network programming, that is, ipv4 protocol; 

The protocol type used by SOCK_RAW, SOCK_RAW represents a raw socket, and the message header is created by itself; 

CAN_RAW is the specific protocol used, which is the can bus protocol;

4. Specify the name of the can port;

const char* ifrname = "can1";

5. Filtering is prohibited when sending data;

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0); //Disable filter.

6. Bind socketCan;

bind(s, (struct sockaddr *)&addr, sizeof(addr)

The bind function is used to bind the socket, that is, to bind the socket to the canbus peripheral;

7. Send data;

  /* send frame */  
    if (write(s, &frame, required_mtu) != required_mtu) {       //发送数据!  
        perror("write");  
        return 1;  
    }  

8. Definition of data format;

struct can_frame {
    canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    can_dlc; /* frame payload length in byte (0 .. CAN_MAX_DLEN) */
    __u8    __pad;   /* padding */
    __u8    __res0;  /* reserved / padding */
    __u8    __res1;  /* reserved / padding */
    __u8    data[CAN_MAX_DLEN] __attribute__((aligned(8)));
};
struct canfd_frame {
    canid_t can_id;  /* 32 bit CAN_ID + EFF/RTR/ERR flags */
    __u8    len;     /* frame payload length in byte */
    __u8    flags;   /* additional flags for CAN FD */
    __u8    __res0;  /* reserved / padding */
    __u8    __res1;  /* reserved / padding */
    __u8    data[CANFD_MAX_DLEN] __attribute__((aligned(8)));
};

#define CAN_MTU        (sizeof(struct can_frame))
#define CANFD_MTU    (sizeof(struct canfd_frame))

struct can_frame - basic CAN frame structure;

struct canfd_frame - CAN flexible data rate frame structure;

refer to

1. Can bus programming model of linux platform ;

2.can-utils-git

over

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=324648133&siteId=291194637