从一个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; };
过滤规则的匹配:
/*
#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
相关推荐: