/* ###################################################################
** Filename : CAN.c
** Project : SNV_EMS
** Processor : ARM
** Component :
** Version :
** Compiler : GCC
** Date/Time : 2024
** Author : lulu
** Copyright SNVOA
** All Rights Reserved.
**
** THIS SOFTWARE IS PROVIDED BY SNV “AS IS” AND ANY EXPRESSED OR
** IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
** OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
** ###################################################################*/
#include “CAN.h”
#include <stdio.h>
#include <pthread.h>
#include <sys/ioctl.h>
#include <arpa/inet.h>
#include <linux/socket.h>
#include <linux/can/error.h>
#include <linux/can/raw.h>
#include <fcntl.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#ifndef AF_CAN
#define AF_CAN 29
#endif
#ifndef PF_CAN
#define PF_CAN AF_CAN
#endif
#define errout(_s) fprintf(stderr, “error class: %s\n”, (_s))
#define errcode(_d) fprintf(stderr, “error code: %02x\n”, (_d))
#define myerr(str) fprintf(stderr, “%s, %s, %d: %s\n”, FILE, func, LINE, str)
#define IF_NAMESIZE 16
struct ifmap1
{
unsigned long int mem_start;
unsigned long int mem_end;
unsigned short int base_addr;
unsigned char irq;
unsigned char dma;
unsigned char port;
/* 3 bytes spare */
};
struct ifreq1
{
define IFHWADDRLEN 6
define IFNAMSIZ IF_NAMESIZE
union
{
char ifrn_name[IFNAMSIZ]; /* Interface name, e.g. "en0". */
} ifr_ifrn;
union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap1 ifru_map;
char ifru_slave[IFNAMSIZ]; /* Just fits the size */
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_data;
} ifr_ifru;
};
define ifr_name ifr_ifrn.ifrn_name /* interface name */
define ifr_hwaddr ifr_ifru.ifru_hwaddr /* MAC address */
define ifr_addr ifr_ifru.ifru_addr /* address */
define ifr_dstaddr ifr_ifru.ifru_dstaddr /* other end of p-p lnk */
define ifr_broadaddr ifr_ifru.ifru_broadaddr /* broadcast address */
define ifr_netmask ifr_ifru.ifru_netmask /* interface net mask */
define ifr_flags ifr_ifru.ifru_flags /* flags */
define ifr_metric ifr_ifru.ifru_ivalue /* metric */
define ifr_mtu ifr_ifru.ifru_mtu /* mtu */
define ifr_map ifr_ifru.ifru_map /* device map */
define ifr_slave ifr_ifru.ifru_slave /* slave device */
define ifr_data ifr_ifru.ifru_data /* for use by interface */
define ifr_ifindex ifr_ifru.ifru_ivalue /* interface index */
define ifr_bandwidth ifr_ifru.ifru_ivalue /* link bandwidth */
define ifr_qlen ifr_ifru.ifru_ivalue /* queue length */
define ifr_newname ifr_ifru.ifru_newname /* New name */
define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)
struct ifreq1 ifr;
struct can_frame temp_frame;
static void handle_err_frame(const struct can_frame *fr)
{
if (fr->can_id & CAN_ERR_TX_TIMEOUT) {
errout(“CAN_ERR_TX_TIMEOUT”);
}
if (fr->can_id & CAN_ERR_LOSTARB) {
errout(“CAN_ERR_LOSTARB”);
errcode(fr->data[0]);
}
if (fr->can_id & CAN_ERR_CRTL) {
errout(“CAN_ERR_CRTL”);
errcode(fr->data[1]);
}
if (fr->can_id & CAN_ERR_PROT) {
errout(“CAN_ERR_PROT”);
errcode(fr->data[2]);
errcode(fr->data[3]);
}
if (fr->can_id & CAN_ERR_TRX) {
errout(“CAN_ERR_TRX”);
errcode(fr->data[4]);
}
if (fr->can_id & CAN_ERR_ACK) {
errout(“CAN_ERR_ACK”);
}
if (fr->can_id & CAN_ERR_BUSOFF) {
errout(“CAN_ERR_BUSOFF”);
}
if (fr->can_id & CAN_ERR_BUSERROR) {
errout(“CAN_ERR_BUSERROR”);
}
if (fr->can_id & CAN_ERR_RESTARTED) {
errout(“CAN_ERR_RESTARTED”);
}
}
int CAN_Init(char *canName)//return can_sock
{
int can_sock;
int ret;
struct sockaddr_can addr;
int master;
srand(time(NULL));
can_sock = socket(PF_CAN, SOCK_RAW, CAN_RAW); /* 创建套接字 */
if (can_sock < 0) {
perror("socket PF_CAN failed");
return -1;
}
/* 把套接字绑定到can0接口 */
strcpy(ifr.ifr_name, canName);
ret = ioctl(can_sock, SIOCGIFINDEX, &ifr);
if (ret < 0) {
perror("ioctl failed");
return -1;
}
addr.can_family = PF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
ret = bind(can_sock, (struct sockaddr *)&addr, sizeof(addr));
if (ret < 0) {
perror("bind failed");
return -1;
}
/* 设置过滤规则 */
if (0) {
struct can_filter filter[2];
/* 第1个规则是可以接收ID为0x200 & 0xFFF的数据帧 */
filter[0].can_id = 0x200 | CAN_EFF_FLAG;
filter[0].can_mask = 0xFFF;
/* 第2个规则是可以接收ID为0x20F& 0xFFF的数据帧 */
filter[1].can_id = 0x20F | CAN_EFF_FLAG;
filter[1].can_mask = 0xFFF;
/* 启用过滤规则,只要CAN0接收到的数据帧满足上面2个规则中的任何一个也被接受*/
ret = setsockopt(can_sock, SOL_CAN_RAW, CAN_RAW_FILTER, &filter, sizeof(filter));
//ret = setsockopt(s, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);//禁用filter
if(ret < 0) {
perror("setsockopt failed");
return 1;
}
}
return can_sock;
}
void CAN_SendOneFrame(int can_sock,struct can_frame frame)
{
print_frame(&frame); /* 打印数据帧信息 /
int ret = write(can_sock, &frame, sizeof(frame)); / 把接收到的数据帧发送出去 */
if (ret < 0)
{
myerr(“write failed”);
}
}
int CAN_RecvOneFrame(int can_sock,struct can_frame *frame)
{
int nbytes = read(can_sock, frame, sizeof(temp_frame)); //接收报文
if(nbytes > 0)
{
print_frame(frame);
}
return nbytes;
}