Linux内核Socket CAN中文文档 联系客服

发布时间 : 星期一 文章Linux内核Socket CAN中文文档更新完毕开始阅读c7eae43b5a8102d276a22f91

从一个CAN_RAW套接字上读取CAN帧也就是读取struct can_frame结构体:

struct can_frame frame;

nbytes = read(s, &frame, sizeof(struct can_frame));

if (nbytes < 0) {

perror(\ return 1; }

/* paranoid check ... */

if (nbytes < sizeof(struct can_frame)) {

fprintf(stderr, \ return 1; }

/* do something with the received CAN frame */

写CAN帧也是类似的,需要用到write (2)函数:

nbytes = write(s, &frame, sizeof(struct can_frame));

如果套接字跟所有的CAN接口都绑定了(addr.can_index = 0),推荐使用recvfrom(2)获取数据源接口的信息:

struct sockaddr_can addr; struct ifreq ifr;

socklen_t len = sizeof(addr); struct can_frame frame;

nbytes = recvfrom(s, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr, &len);

/* get interface name of the received CAN frame */

ifr.ifr_ifindex = addr.can_ifindex; ioctl(s, SIOCGIFNAME, &ifr);

printf(\

对于绑定了所有接口的套接字,向某个端口发送数据必须指定接口的详细信息:

strcpy(ifr.ifr_name, \ ioctl(s, SIOCGIFINDEX, &ifr); addr.can_ifindex = ifr.ifr_ifindex; addr.can_family = AF_CAN;

nbytes = sendto(s, &frame, sizeof(struct can_frame), 0, (struct sockaddr*)&addr, sizeof(addr));

4.1 使用can_filter的原始套接字 (RAW socket) ----------------------------------------------------

CAN_RAW套接字的用法和CAN字符设备的用法是类似的。为了使用CAN套接字的新特性,在绑定原始套接字的时候将会默认开启以下特性:

- filter将会接收所有的数据

- 套接字仅仅接收有效的数据帧(=> no error frames) - 发送帧的回环功能被开启(参见 3.2节) - (回环模式下)套接字不接收它自己发送的帧

这些特性的设置可以在绑定之前和之后修改。为了使用CAN_RAW套接字相关的选项,必须包含

?

4.1.1 原始套接字选项 CAN_RAW_FILTER

CAN_RAW套接字的接收可以使用CAN_RAW_FILTER套接字选项指定的多个过滤规则(过滤器)来过滤。

过滤规则(过滤器)的定义在 include/linux/can.h中:

struct can_filter { canid_t can_id; canid_t can_mask; };

过滤规则的匹配:

& mask == can_id & mask

/*

#define CAN_INV_FILTER 0x20000000U /* to be set in can_filter.can_id */ #define CAN_ERR_FLAG 0x20000000U /* error frame */

*/

这和大家所熟知的CAN控制器硬件过滤非常相似。可以使用 CAN_INV_FILTER这个宏

将can_filter结构体的成员can_id中的比特位反转。和CAN控制器的硬件过滤形成鲜明对比的是,用户可以为每一个打开的套接字设置多个独立的过滤规则(过滤器):

/*

/* valid bits in CAN ID for frame formats */

#define CAN_SFF_MASK 0x000007FFU /* 标准帧格式 (SFF) */ #define CAN_EFF_MASK 0x1FFFFFFFU /* 扩展帧格式 (EFF) */

#define CAN_ERR_MASK 0x1FFFFFFFU /* 忽略EFF, RTR, ERR标志 */

*/

struct can_filter rfilter[2];

rfilter[0].can_id = 0x123; rfilter[0].can_mask = CAN_SFF_MASK; rfilter[1].can_id = 0x200; rfilter[1].can_mask = 0x700;

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter, sizeof(rfilter));

为了在指定的CAN_RAW套接字上禁用接收过滤规则,可以这样:

setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);

在一些极端情况下不需要读取数据,可以把过滤规则清零(所有成员设为0),这样原始套接字就会忽略接收到的CAN帧。在这种仅仅发送数据(不读取)的应用中可以在内核中省略接收队列,以此减少CPU的负载(虽然只能减少一点点)。

?

4.1.2 原始套接字选项 CAN_RAW_ERR_FILTER

正如3.4节所说,CAN接口驱动可以选择性的产生错误帧,错误帧和正常帧以相同的方式传给应用程序。可能产生的错误被分为不同的种类,使用适当的错误掩码可以过滤它们。为了注册所有可能的错误情况,CAN_ERR_MASK(0x1FFFFFFFU)这个宏可以用来作为错误掩码。这个错误掩码定义在linux/can/error.h。

can_err_mask_t err_mask = ( CAN_ERR_TX_TIMEOUT | CAN_ERR_BUSOFF );

setsockopt(s, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask, sizeof(err_mask));

?

4.1.3 原始套接字选项 CAN_RAW_LOOPBACK

为了满足众多应用程序的需要,本地回环功能默认是开启的(详细情况参考3.2节)。但是在一些嵌入式应用场景中(比如只有一个用户在使用CAN总线),回环功能可以被关闭(各个套接字之间是独立的):

int loopback = 0; /* 0 = disabled, 1 = enabled (default) */

setsockopt(s, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));

?

4.1.4 原始套接字选项 CAN_RAW_RECV_OWN_MSGS