can-utils源码解析cansend
前言
本文主要介绍socketCan中的发送函数cansend的源码解析.
代码
/*
* 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 <linux-can@vger.kernel.org>
*
*/ #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 = ;
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 ;
} /* open socket */
if ((s = socket(PF_CAN, SOCK_RAW, CAN_RAW)) < ) {
perror("socket");
return ;
} 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 ;
} memset(&addr, , 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;
}
mtu = ifr.ifr_mtu; if (mtu != 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, ); if (bind(s, (struct sockaddr *)&addr, sizeof(addr)) < ) {
perror("bind");
return ;
} /* 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 ;
} close(s); return ;
}
解析
1.message的格式;
char* input = "008#abcd1234cdef567830";
其中‘008表示can_id,必须是三位十六进制数据,可以表示标准帧或者扩展帧;符号#“是can_id和can数据的分界符,最后的数据是报文的数据,标准帧一次最多只能发送8bits的数据,多余的数据自动丢弃;
2.parse_canframe函数,具体内容可参考lib.h和lib.c文件;
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.创建socket;
s = socket(PF_CAN, SOCK_RAW, CAN_RAW)
创建socket套接字
PF_CAN 为域位,同网络编程中的AF_INET,即ipv4协议;
SOCK_RAW使用的协议类型,SOCK_RAW表示原始套接字,报文头由自己创建;
CAN_RAW为使用的具体协议,为can总线协议;
4. 指定can口名称;
const char* ifrname = "can1";
5.发送数据则禁止过滤;
setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, ); //Disable filter.
6.绑定socketCan;
bind(s, (struct sockaddr *)&addr, sizeof(addr)
bind函数用于绑定套接字,即将套接字和canbus外设进行绑定;
7.发送数据;
/* send frame */
if (write(s, &frame, required_mtu) != required_mtu) { //发送数据!
perror("write");
return ;
}
8.数据格式的定义;
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()));
};
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()));
}; #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;
参考
完
can-utils源码解析cansend的更多相关文章
- 【原】Android热更新开源项目Tinker源码解析系列之一:Dex热更新
[原]Android热更新开源项目Tinker源码解析系列之一:Dex热更新 Tinker是微信的第一个开源项目,主要用于安卓应用bug的热修复和功能的迭代. Tinker github地址:http ...
- 【原】Android热更新开源项目Tinker源码解析系列之二:资源文件热更新
上一篇文章介绍了Dex文件的热更新流程,本文将会分析Tinker中对资源文件的热更新流程. 同Dex,资源文件的热更新同样包括三个部分:资源补丁生成,资源补丁合成及资源补丁加载. 本系列将从以下三个方 ...
- Retrofit2 源码解析
原文链接:http://bxbxbai.github.io/2015/12/13/retrofit2-analysis/ 公司里最近做的项目中网络框架用的就是Retrofit,用的多了以后觉得这个框架 ...
- Retrofit2.0源码解析
欢迎访问我的个人博客 ,原文链接:http://wensibo.net/2017/09/05/retrofit/ ,未经允许不得转载! 今天是九月的第四天了,学校也正式开学,趁着大学最后一年的这大好时 ...
- iview源码解析(1)
概述 公司技术栈开始用vue主导开发,但因为公司前端会vue的不多所以在项目中用到vue的技术不是很深,之前出去面试被接连打击,而且本来打算开始为公司vue的项目构建自己的组件库所以去下载了iview ...
- elementUi源码解析(1)--项目结构篇
因为在忙其他事情好久没有更新iview的源码,也是因为后面的一些组件有点复杂在考虑用什么方式把复杂的功能逻辑简单的展示出来,还没想到方法,突然想到element的组件基本也差不多,内部功能的逻辑也差不 ...
- element-ui 源码解析 二
Carousel 走马灯源码解析 1. 基本原理:页面切换 页面切换使用的是 transform 2D 转换和 transition 过渡 可以看出是采用内联样式来实现的 举个栗子 <div : ...
- 第三十六节,目标检测之yolo源码解析
在一个月前,我就已经介绍了yolo目标检测的原理,后来也把tensorflow实现代码仔细看了一遍.但是由于这个暑假事情比较大,就一直搁浅了下来,趁今天有时间,就把源码解析一下.关于yolo目标检测的 ...
- t-io 集群解决方案以及源码解析
t-io 集群解决方案以及源码解析 0x01 概要说明 本博客是基于老谭t-io showcase中的tio-websocket-showcase 示例来实现集群.看showcase 入门还是挺容易的 ...
随机推荐
- Qt5_加载DLL
1.QLibrary 加载普通 DLL //写清楚库的路径,如果放在当前工程的目录下,路径为./Oracle.so QLibrary *libOCI = new QLibrary("F:\\ ...
- 数据库使用SSIS进行数据清洗教程
OLTP系统的后端关系数据库用于存储不同种类的数据,理论上来讲,数据库中每一列的值都有其所代表的特定含义,数据也应该在存入数据库之前进行规范化处理,比如说“age”列,用于存储人的年龄,设置的数据类型 ...
- node 循序渐进
1. 执行 node helloworld.js 2. http 服务器 建 server.js 文件 - node server.js 跑起来 - 浏览器访问 http://localho ...
- Codeforces 38B - Chess
38B - Chess 思路:懂点象棋的规则就可以,看看哪些点可以放马. 代码: #include<bits/stdc++.h> using namespace std; #define ...
- javascript对象使用总结
javascript对象使用总结 一.总结 一句话总结:js对象的主要知识点是创建对象和继承,并且创建对象和继承的方法都是逐步层层递进的 创建对象 继承 原型 创建对象 1 <script> ...
- 雷林鹏分享:Ruby 判断
Ruby 判断 Ruby 提供了其他现代语言中很常见的条件结构.在这里,我们将解释所有的条件语句和 Ruby 中可用的修饰符. Ruby if...else 语句 语法 if conditional ...
- mac 无法打开xx ,因为无法确认开发者身份
系统偏好与设置 - 安全性与隐私 - 通用 允许从以下位置下载的应用: 选择 [任何来源],如果没有这个选项,使用终端执行下面的命令: spctl --master-disable (spctl空格 ...
- axios构建缓存池存储基础数据
项目中经常出现需要多次使用的后端数据,通常的做法是通过变量缓存数据,或者通过类似vuex的东西来进行缓存,但是麻烦在于很可能需要判断一大堆的条件,或者说如果有权限控制的时候数据能否读取也是很麻烦的事情 ...
- Dubbo 环境搭建
CentOS7 x64 JDK1.8 1. wget https://mirrors.tuna.tsinghua.edu.cn/apache/zookeeper/zookeeper-3.4.8/zoo ...
- 基于binlog的增量备份
1.1 增量备份简介 增量备份是指在一次全备份或上一次增量备份后,以后每次的备份只需备份与前一次相比增加或者被修改的文件.这就意味着,第一次增量备份的对象是进行全备后所产生的增加和修改的文件:第二次增 ...