EMS/drv/drv_can.c

301 lines
7.9 KiB
C
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#include "drv_can.h"
#include <errno.h>
#include <stdio.h>
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <fcntl.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <linux/can.h>
#include <linux/can/raw.h>
#include <termios.h> /*PPSIX 终端控制定义*/
#include "drv_can.h"
/*
* @description : 字符串按格式输出
* @param - *destpoint : 字符串格式缓冲区
* @param - *fmt : 多个参数
* @return : 按格式输出字符串缓冲区首指针
*/
char func_dprintf(char *destpoint, char *fmt, ...)
{
va_list arg_ptr;
char ulen, *tmpBuf;
tmpBuf = destpoint;
va_start(arg_ptr, fmt);
ulen = vsprintf(tmpBuf, fmt, arg_ptr);
va_end(arg_ptr);
return ulen;
}
/*
* @description : 打开can外设设置波特率创建文件描述符
* @param - *device : 设备名称
* @param - para : can应用参数
* @return : 打开设备执成功返回文件描述符,失败返回-1
*/
int func_open_can(char *device, struct_can_param para)
{
FILE *fstream = NULL;
char buff[300] = {0}, command[50] = {0};
int fd = -1;
struct sockaddr_can addr;
struct ifreq ifr;
/*关闭can设备 ifconfig can0 down*/
memset(buff, 0, sizeof(buff));
memset(command, 0, sizeof(command));
func_dprintf(command, "ifconfig %s down", device);
printf("%s \n", command);
if (NULL == (fstream = popen(command, "w")))
{
fprintf(stderr, "execute command failed: %s", strerror(errno));
}
while (NULL != fgets(buff, sizeof(buff), fstream))
{
printf("%s\n", buff);
if (strstr(buff, "No such device") || strstr(buff, "Cannot find device"))
return -1;
}
pclose(fstream);
sleep(1);
/*设置can波特率 ip link set can0 up type can bitrate 250000 triple-sampling on*/
memset(buff, 0, sizeof(buff));
memset(command, 0, sizeof(command));
if (para.loopback_mode == 1)
{
func_dprintf(command, "ip link set %s up type can bitrate %d triple-sampling on loopback on", device, para.baudrate);
}
else
{
func_dprintf(command, "ip link set %s up type can bitrate %d triple-sampling on loopback off", device, para.baudrate);
}
printf("%s \n", command);
if (NULL == (fstream = popen(command, "w")))
{
fprintf(stderr, "execute command failed: %s", strerror(errno));
}
while (NULL != fgets(buff, sizeof(buff), fstream))
{
printf("%s\n", buff);
if (strstr(buff, "No such device") || strstr(buff, "Cannot find device"))
return -1;
}
pclose(fstream);
sleep(1);
/*打开can设备 ifconfig can0 up*/
memset(buff, 0, sizeof(buff));
memset(command, 0, sizeof(command));
func_dprintf(command, "ifconfig %s up", device);
printf("%s \n", command);
if (NULL == (fstream = popen(command, "w")))
{
fprintf(stderr, "execute command failed: %s", strerror(errno));
}
while (NULL != fgets(buff, sizeof(buff), fstream))
{
printf("%s\n", buff);
if (strstr(buff, "No such device") || strstr(buff, "Cannot find device"))
return -1;
}
pclose(fstream);
sleep(3);
/* 创建 socket */
fd = socket(PF_CAN, SOCK_RAW, CAN_RAW);
if (fd < 0)
{
printf("socket:%s", strerror(errno));
return -1;
}
/* 设置接口设备名称 */
strcpy(ifr.ifr_name, device);
/* 确定接口 index */
if (ioctl(fd, SIOCGIFINDEX, &ifr) < 0)
{
printf("SIOCGIFINDEX:%s\n", strerror(errno));
return -1;
}
memset(&addr, 0, sizeof(addr));
addr.can_family = AF_CAN;
addr.can_ifindex = ifr.ifr_ifindex;
/* 绑定 socket到 CAN 接口 */
if (bind(fd, (struct sockaddr *)&addr, sizeof(addr)) < 0)
{
printf("bind:%s\n", strerror(errno));
return -1;
}
return fd;
}
/*
* @description : 设置can回环模式和过滤规则
* @param - fd : 文件描述符
* @param - para: can应用参数
* @return : 设置成功返回1失败返回-1
*/
int func_set_can(int fd, struct_can_param para)
{
int loopback = 1;
int reciveown = 1;
if (para.loopback_mode == 1)
{
//回环设置 0 关闭回环 1 打开回环
setsockopt(fd, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback, sizeof(loopback));
//接收自己的帧 0 不接收自己帧 1 接收自己帧
setsockopt(fd, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS, &reciveown, sizeof(reciveown));
}
/* 设置过滤规则 */
if (setsockopt(fd, SOL_CAN_RAW, CAN_RAW_FILTER, &para.filter, sizeof(para.filter)) < 0)
{
printf("error when set filter\n");
return -1;
}
return 1;
}
/*
* @description : can接收一个can帧
* @param - fd : 文件描述符
* @param - *pframe: 一个can帧结构体指针
* @return : 接收数据长度
*/
int func_receive_can_frame(int fd, struct can_frame *pframe)
{
int rx_count = 0;
rx_count = recv(fd, pframe, sizeof(*pframe), 0);
if (rx_count <= 0)
{
return rx_count;
}
else
{
if (pframe->can_id & CAN_EFF_FLAG) /*如果是扩展帧,清除扩展帧标识*/
{
pframe->can_id &= (~CAN_EFF_FLAG);
}
else
{
pframe->can_id &= (~CAN_SFF_MASK);
}
}
return pframe->can_dlc;
}
/*
* @description : can接收一组数据包
* @param - fd : 文件描述符
* @param - *buff: 要接收can一组数据的缓冲区首指针
* @param - len : 接收到一组数据的长度
* @return : 接收数据长度
*/
int func_receive_can_buff(int fd, unsigned char *buff, int len)
{
int receive_len = 0, total_receive_len = 0;
struct can_frame frame;
int i = 0;
while (1)
{
receive_len = func_receive_can_frame(fd, &frame);
for (i = 0; i < receive_len; i++)
{
*(buff + total_receive_len) = frame.data[i];
total_receive_len++;
}
if ((receive_len < 8) || (total_receive_len > (len - 8)))
{
return total_receive_len;
}
}
return total_receive_len;
}
/*
* @description : can发送一个can帧
* @param - fd : 文件描述符
* @param - *pframe: 一个can帧结构体指针
* @param - param : can应用参数
* @return : 发送数据长度,发送失败返回-1
*/
int func_send_can_frame(int fd, struct can_frame *pframe, struct_can_param param)
{
int result = 0;
if (param.extend == 1) /*扩展帧增加扩展帧标志*/
{
pframe->can_id &= CAN_EFF_MASK;
pframe->can_id |= CAN_EFF_FLAG;
}
else
{
pframe->can_id &= CAN_SFF_MASK;
}
result = send(fd, pframe, sizeof(struct can_frame), 0);
if (result == -1)
{
printf("send:%s\n", strerror(errno));
return -1;
}
return result;
}
/*
* @description : can发送一组数据包
* @param - fd : 文件描述符
* @param - *buff: 要发送can一组数据的缓冲区首指针
* @param - len : 发送数据的长度
* @param - param: can应用参数
* @return : 实际发送数据长度
*/
int func_send_can_buff(int fd, unsigned char *buff, int len, struct_can_param param)
{
int remain_frame_len = 0, frame_numb = 0;
struct can_frame frame;
int i = 0;
remain_frame_len = len;
while (1)
{
if (remain_frame_len >= 8)
{
frame.can_dlc = 8; /*填充发送长度*/
remain_frame_len -= 8; /*剩余数据长度*/
}
else
{
frame.can_dlc = remain_frame_len; /*填充发送长度*/
remain_frame_len = 0; //
}
frame.can_id = param.id; /*填充发送id*/
for (i = 0; i < frame.can_dlc; i++)
{
frame.data[i] = buff[frame_numb * 8 + i]; /*填充发送数据*/
}
func_send_can_frame(fd, &frame, param);
frame_numb++;
if (remain_frame_len == 0)
{
return len;
}
}
return len;
}