blob: 752db1704ded7d31ab28706f1d22fdbe723fe5ba [file] [log] [blame]
/******************************************************************************
* Copyright (c) 2010, 2016 Ericsson AB
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*
* Contributors:
* Michael Josenhans
******************************************************************************/
//
// File: SocketCAN_PT.cc
// Description: SocketCAN_PT test port source
//
// Revision R1A
#include "SocketCAN_PT.hh"
#include "SocketCAN_PortType.hh"
#include <Addfunc.hh>
#include <Bitstring.hh>
#include <Charstring.hh>
#include <errno.h>
#include <Error.hh>
#include <Hexstring.hh>
#include <Integer.hh>
#include <linux/can/bcm.h>
#include <linux/can/raw.h>
#include <linux/if.h>
#include <Logger.hh>
#include <memory.h>
#include <Octetstring.hh>
#include <Optional.hh>
#include <Port.hh>
#include <stdlib.h>
#include <sys/ioctl.h>
#include <Template.hh>
#include <unistd.h>
#include <algorithm>
#include <cerrno>
#include <cstdarg>
#include <cstddef>
#include <cstring>
#include <iostream>
struct bcm_msg_head;
struct can_frame;
struct canfd_frame;
#define DEFAULT_NUM_SOCK 10
#define BCM_FRAME_BUFFER_SIZE 256
#define BCM_FRAME_FLAGS_SIZE 32 // size of SocketCAN_bcm_frame in Bit
#define ISOTP_RECIEVE_BUFSIZE 5000
// workaround, as some of those below may not yet be defined in "linux/can/raw.h":
#define CAN_RAW_FILTER 1 /* set 0 .. n can_filter(s) */
#define CAN_RAW_ERR_FILTER 2 /* set filter for error frames */
#define CAN_RAW_LOOPBACK 3 /* local loopback (default:on) */
#define CAN_RAW_RECV_OWN_MSGS 4 /* receive my own msgs (default:off) */
#define CAN_RAW_FD_FRAMES 5 /* allow CAN FD frames (default:off) */
#define CAN_RAW_JOIN_FILTERS 6 /* all filters must match to trigger */
// workaround, as not yet defined in all versions of "linux/Can.h":
#ifndef CAN_MAX_DLEN
#define CAN_MAX_DLEN 8
#endif
// workaround, as not defined in some older kernel versions
#ifndef CAN_MTU
#define CAN_MTU (sizeof(struct can_frame))
#endif //CAN_MTU
#ifndef CANFD_MTU
#define CANFD_MTU (sizeof(struct canfd_frame))
#endif //CANFD_MTU
// workaround, as canfd not defined in some older kernel versions
// and thus canfd frames can not be used for data transfer between
// kernel module and userspace.
#ifdef CANFD_MTU
#define CANFD_FRAME_STRUCT_DEFINED true
#define RAW_CANFD_SUPPORT true
#endif //CANFD_MTU
// has to be defined in later kernel versions in bcm.h as #define CAN_FD_FRAME 0x0800
#ifdef CAN_FD_FRAME
#define BCM_CANFD_SUPPORT true
#endif
namespace SocketCAN__PortType {
SocketCAN__PT_PROVIDER::SocketCAN__PT_PROVIDER(const char *par_port_name) :
PORT(par_port_name), num_of_sock(0), sock_list_length(0), target_fd(-1), can_interface_name(
NULL), debugging(false), debugging_configured(false), config_finished(
false) {
sock_list = NULL;
//&num_of_sock = 0;
//sock_list_length = 0;
}
SocketCAN__PT_PROVIDER::~SocketCAN__PT_PROVIDER() {
Free(sock_list);
reset_configuration();
}
void SocketCAN__PT_PROVIDER::set_parameter(const char * parameter_name,
const char * parameter_value) {
log("entering SocketCAN__PT_PROVIDER::set_parameter(%s, %s)",
parameter_name, parameter_value);
if (config_finished) {
reset_configuration();
config_finished = false;
}
if (strcmp(parameter_name, "SocketCAN_can_interface_name") == 0) {
InitStrPar(can_interface_name, parameter_name, parameter_value);
} else if (strcmp(parameter_name, "SocketCAN_debugging") == 0) {
if (strcmp(parameter_value, "YES") == 0) {
debugging = true;
debugging_configured = true;
log("Reading testport parameter debugging: ", debugging);
} else if (strcmp(parameter_value, "NO") == 0) {
debugging = false;
debugging_configured = true;
log("Reading testport parameter debugging: ", debugging);
}
} else {
TTCN_error(
"SocketCAN parameter configuration error: Configuration file does not correctly configure parameter 'SocketCAN_debugging' however parameter name '%s' as parameter value: '%s'!!\nExpecting: \n*.*.SocketCAN_debugging := \"YES\"\n or \n*.*.SocketCAN_debugging := \"NO\"",
parameter_name, parameter_value);
}
log("leaving SocketCAN__PT_PROVIDER::set_parameter(%s, %s)", parameter_name,
parameter_value);
}
/*void SocketCAN__PT_PROVIDER::Handle_Fd_Event(int fd, boolean is_readable,
boolean is_writable, boolean is_error) {}*/
void SocketCAN__PT_PROVIDER::Handle_Fd_Event_Error(int /*fd*/) {
}
void SocketCAN__PT_PROVIDER::Handle_Fd_Event_Writable(int /*fd*/) {
}
void SocketCAN__PT_PROVIDER::Handle_Fd_Event_Readable(int sock) {
log("entering SocketCAN__PT_PROVIDER::Handle_Fd_Event_Readable()");
int res;
for (int a = 0; a < sock_list_length; a++) {
if ((sock == sock_list[a].fd)
and (sock_list[a].status != SOCKET_NOT_ALLOCATED)) {
switch (sock_list[a].protocol_family) {
case SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_ISOTP: {
SocketCAN__Types::SocketCAN__receive__isotp__pdu parameters;
unsigned char msg[ISOTP_RECIEVE_BUFSIZE];
int nbytes = 0;
struct sockaddr_can addr;
socklen_t addr_len = sizeof(addr);
//ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
// struct sockaddr *src_addr, socklen_t *addrlen);
nbytes = recvfrom(sock, msg, ISOTP_RECIEVE_BUFSIZE, 0,
(struct sockaddr*) &addr, &addr_len);
//nbytes = read(sock, msg, ISOTP_RECIEVE_BUFSIZE);
if (nbytes > 0 && nbytes < ISOTP_RECIEVE_BUFSIZE) {
struct ifreq ifr;
ifr.ifr_ifindex = addr.can_ifindex;
parameters.ifr().if__index() = ifr.ifr_ifindex;
parameters.ifr().if__name() = ifr.ifr_name;
parameters.id() = a;
parameters.pdu() = OCTETSTRING(nbytes, msg);
incoming_message(parameters);
}
}
break;
case SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_RAW: {
SocketCAN__Types::SocketCAN__receive__CAN__or__CAN__FD__frame parameters;
struct sockaddr_can addr;
socklen_t addr_len = sizeof(addr);
//ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
// struct sockaddr *src_addr, socklen_t *addrlen);
#ifdef CANFD_FRAME_STRUCT_DEFINED // struct canfd_frame is supported
struct canfd_frame frame; // always assume a CANFD_Frame shall be received
ssize_t nbytes = recvfrom(sock, &frame, CANFD_MTU, 0,
(struct sockaddr*) &addr, &addr_len);
#else //CANFD_FRAME_STRUCT_DEFINED
struct can_frame frame; // CANFD_Frame is not supported by this kernel version
ssize_t nbytes = recvfrom(sock, &frame, CAN_MTU, 0,
(struct sockaddr*) &addr, &addr_len);
#endif //CANFD_FRAME_STRUCT_DEFINED
if (nbytes <= 0) {
//there is an empty message, or error in receive
//remove the socket
TTCN_error(
"Closing socket %d with interface index %d due to an empty message or error in reception\n",
sock, addr.can_ifindex);
std::cout << "close_fd" << sock << std::endl;
sock_list[a].status = SOCKET_NOT_ALLOCATED;
sock_list[a].protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_NO_PROTOCOL;
num_of_sock--;
Handler_Remove_Fd_Read(sock);
close(sock);
} else
if ((nbytes == CAN_MTU)
#ifdef CANFD_FRAME_STRUCT_DEFINED
or (nbytes == CANFD_MTU)
#endif //CANFD_FRAME_STRUCT_DEFINED
) {
// A CAN Frame has been received. However use the struct canfd_frame to access it.
// As it is a CAN frame, the flags field contains invalid data and the can_dlc field
// is here called len as in CAN FD.
struct ifreq ifr;
ifr.ifr_ifindex = addr.can_ifindex;
/* get interface name of the received CAN frame */
res = ioctl(sock, SIOCGIFNAME, &ifr);
if (res != 0) {
TTCN_error(
"SocketCAN frame reception: Ioctl failed while retrieving the interface name from the socket: %d with interface index %d\n",
sock, ifr.ifr_ifindex);
parameters.ifr().if__index() = ifr.ifr_ifindex;
parameters.ifr().if__name() =
"SocketCAN : device name unknown, ioctl failed";
} else {
#ifdef CANFD_FRAME_STRUCT_DEFINED
if (nbytes == CANFD_MTU) {
log(
"SocketCAN: Received a CANFD frame from interface %s",
ifr.ifr_name, nbytes, frame.len);
} else {
log(
"SocketCAN: Received a CAN frame from interface %s",
ifr.ifr_name, nbytes, frame.len);
}
#else //CANFD_FRAME_STRUCT_DEFINED
log("SocketCAN: Received a CAN frame from interface %s",
ifr.ifr_name, nbytes, frame.can_dlc);
#endif //CANFD_FRAME_STRUCT_DEFINED
parameters.ifr().if__index() = ifr.ifr_ifindex;
parameters.ifr().if__name() = ifr.ifr_name;
}
struct timeval tv;
res = ioctl(sock, SIOCGSTAMP, &tv);
if (res != 0) {
TTCN_error(
"SocketCAN frame reception: Ioctl failed while retrieving the timestamp from the socket: %d with interface name %s\n",
sock, ifr.ifr_name);
} else {
parameters.timestamp().tv__sec() = tv.tv_sec;
parameters.timestamp().tv__usec() = tv.tv_usec;
}
parameters.ifr().if__index() = ifr.ifr_ifindex;
parameters.ifr().if__name() = ifr.ifr_name;
parameters.id() = a;
INTEGER can_id;
can_id.set_long_long_val(frame.can_id);
#ifdef CANFD_FRAME_STRUCT_DEFINED
const INTEGER len = frame.len;
#else //CANFD_FRAME_STRUCT_DEFINED
const INTEGER len = frame.can_dlc;
#endif //CANFD_FRAME_STRUCT_DEFINED
// frame type specific part:
if (nbytes == CAN_MTU) {
// CAN frame received:
Can::CAN__frame& frameref =
parameters.frame().can__frame();
log(
"Received a CAN frame from interface %s of %d bytes and with payload length %d",
ifr.ifr_name, nbytes, (int) len);
parameters.ifr().if__index() = ifr.ifr_ifindex;
parameters.ifr().if__name() = ifr.ifr_name;
parameters.id() = a;
frameref.can__id() = int2oct(can_id, 4);
frameref.can__pdu() = OCTETSTRING(len, frame.data);
} else {
// CAN FD frame received:
Can::CANFD__frame& frameref =
parameters.frame().canfd__frame();
log(
"Received a CAN FD frame from interface %s of %d bytes and with payload length %d",
ifr.ifr_name, nbytes, (int) len);
frameref.can__id() = int2oct(can_id, 4);
#ifdef CANFD_FRAME_STRUCT_DEFINED
if (nbytes == CANFD_MTU) {
frameref.can__flags() = BITSTRING(
int2bit(frame.flags, 8));
}
#endif //CANFD_FRAME_STRUCT_DEFINED
frameref.can__pdu() = OCTETSTRING(len, frame.data);
}
incoming_message(parameters);
}
}
break;
case SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_BCM: {
SocketCAN__Types::SocketCAN__receive__BCM__message parameters;
struct sockaddr_can addr;
struct {
struct bcm_msg_head msg_head;
#ifdef CANFD_FRAME_STRUCT_DEFINED
struct canfd_frame frame[BCM_FRAME_BUFFER_SIZE];
#else //CANFD_FRAME_STRUCT_DEFINED
struct can_frame frame[BCM_FRAME_BUFFER_SIZE];
#endif //CANFD_FRAME_STRUCT_DEFINED
} bcm_msg;
struct ifreq ifr;
socklen_t addr_len = sizeof(addr);
ssize_t nbytes = recvfrom(sock, &bcm_msg,
sizeof(struct can_frame), 0, (struct sockaddr*) &addr,
&addr_len);
if (nbytes < 0) {
//there is an empty message, or error in receive
//remove the socket
TTCN_error(
"Closing socket %d with interface index %d due to an empty BCM message or error in reception\n",
sock, addr.can_ifindex);
std::cout << "close_fd" << sock << std::endl;
sock_list[a].status = SOCKET_NOT_ALLOCATED;
sock_list[a].protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_NO_PROTOCOL;
num_of_sock--;
Handler_Remove_Fd_Read(sock);
close(sock);
} else {
ifr.ifr_ifindex = addr.can_ifindex;
// get interface name of the received CAN frame
// currently handling of can_ifindex == 0 (= any interface) is unclear.
// res = ioctl(sock, SIOCGIFNAME, &ifr);
// if (res == -1) {
// TTCN_error(
// "Ioctl failed while receiving a BCM message frame on socket: %d with interface index %d with errno: %d\n",
// sock, ifr.ifr_ifindex, errno);
// }
const INTEGER msg_head_flags = bcm_msg.msg_head.flags;
log(
"Received a BCM message from interface index %d of bytes %d",
ifr.ifr_ifindex, nbytes);
parameters.id() = bcm_msg.msg_head.can_id;
parameters.ifr().if__index() = ifr.ifr_ifindex;
parameters.ifr().if__name() = ifr.ifr_name;
uint32_t nframes = bcm_msg.msg_head.nframes;
INTEGER opcode;
opcode.set_long_long_val(bcm_msg.msg_head.opcode);
parameters.frame().opcode() = int2oct(opcode, 4);
parameters.frame().flags() = BITSTRING(
int2bit(INTEGER(msg_head_flags),
BCM_FRAME_FLAGS_SIZE));
parameters.frame().count() = bcm_msg.msg_head.count;
parameters.frame().ival1().tv__sec() =
bcm_msg.msg_head.ival1.tv_sec;
parameters.frame().ival1().tv__usec() =
bcm_msg.msg_head.ival1.tv_usec;
parameters.frame().ival2().tv__sec() =
bcm_msg.msg_head.ival2.tv_sec;
parameters.frame().ival2().tv__usec() =
bcm_msg.msg_head.ival2.tv_usec;
INTEGER bcm_head_can_id;
bcm_head_can_id.set_long_long_val(bcm_msg.msg_head.can_id);
parameters.frame().can__id() = int2oct(bcm_head_can_id, 4);
#ifdef BCM_CANFD_SUPPORT
long flags = bcm_msg.msg_head.flags;
if ((flags & CAN_FD_FRAME ) == CAN_FD_FRAME ) {
// Handle CAN FD frames
parameters.frame().frames().can__frame().set_size(nframes);
for (uint32_t i = 0; i < nframes; i++) {
INTEGER len;
len = bcm_msg.frame[i].len;
if (len > CANFD_MAX_DLEN) {
TTCN_error("Writing data: CAN FD pdu size too large\n");
};
INTEGER can_id;
can_id.set_long_long_val(bcm_msg.frame[i].can_id);
parameters.frame().frames().canfd__frame()[i].can__id() = int2oct(can_id, 4);
//Here the bitstring shall be stored into a
parameters.frame().frames().canfd__frame()[i].can__flags() =
BITSTRING(32,
(const unsigned char*) &(bcm_msg.frame[i].flags));
parameters.frame().frames().canfd__frame()[i].can__pdu() =
OCTETSTRING(len,
(const unsigned char*) &(bcm_msg.frame[i].data));
}
incoming_message(parameters);
}
else
#endif //BCM_CANFD_SUPPORT
{
parameters.frame().frames().can__frame().set_size(
nframes);
for (uint32_t i = 0; i < nframes; i++) {
INTEGER len;
#ifdef CANFD_FRAME_STRUCT_DEFINED // struct canfd_frame is supported
len = bcm_msg.frame[i].len;
#else //CANFD_FRAME_STRUCT_DEFINED // struct canfd_frame is supported
len = bcm_msg.frame[i].can_dlc;
#endif //CANFD_FRAME_STRUCT_DEFINED // struct canfd_frame is supported
// Handle legacy CAN frames
if (len > CAN_MAX_DLEN) {
TTCN_error(
"Writing data: CAN pdu size too large\n");
len = CAN_MAX_DLEN;
};
INTEGER can_id;
can_id.set_long_long_val(bcm_msg.frame[i].can_id);
parameters.frame().frames().can__frame()[i].can__id() =
int2oct(can_id, 4);
parameters.frame().frames().can__frame()[i].can__pdu() =
OCTETSTRING(len,
(const unsigned char*) &(bcm_msg.frame[i].data));
}
incoming_message(parameters);
}
}
}
break;
default: {
TTCN_error(
"SocketCAN Handle_Fd_Event_Readable (%d): unhandled protocol configured",
sock);
}
break;
}
}
}
log("leaving SocketCAN__PT_PROVIDER::Handle_Fd_Event_Readable()");
}
void SocketCAN__PT_PROVIDER::user_map(const char */*system_port */) {
log("entering SocketCAN__PT_PROVIDER::user_map()");
config_finished = true;
if (debugging_configured == false) {
// The debugging mode has not been defined in TTCN configuration file.
TTCN_error(
"Missing mandatory parameter: SocketCAN_debuhhing for can_interface_name %s \n",
can_interface_name);
}
if (sock_list != NULL)
TTCN_error("SocketCAN Test Port (%s): Internal error: "
"sock_list is not NULL when mapping.", port_name);
sock_list = (sock_data*) Malloc(DEFAULT_NUM_SOCK * sizeof(*sock_list));
num_of_sock = 0;
sock_list_length = DEFAULT_NUM_SOCK;
for (int a = 0; a < sock_list_length; a++) {
sock_list[a].fd = 0;
sock_list[a].status = SOCKET_NOT_ALLOCATED;
sock_list[a].protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_NO_PROTOCOL;
}
log("leaving SocketCAN__PT_PROVIDER::user_map()");
}
void SocketCAN__PT_PROVIDER::user_unmap(const char * /*system_port*/) {
log("entering SocketCAN__PT_PROVIDER::user_unmap()");
closeDownSocket();
log("leaving SocketCAN__PT_PROVIDER::user_unmap()");
}
void SocketCAN__PT_PROVIDER::user_start() {
}
void SocketCAN__PT_PROVIDER::user_stop() {
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__socket& send_par) {
log("entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__socket)");
int cn;
SocketCAN__Types::SocketCAN__socket__result result;
if (num_of_sock < sock_list_length) {
cn = 0;
while (sock_list[cn].status == SOCKET_OPEN) {
cn++;
}
} else {
sock_list = (sock_data*) Realloc(sock_list,
2 * sock_list_length * sizeof(*sock_list));
for (int a = sock_list_length; a < sock_list_length * 2; a++) {
sock_list[a].status = SOCKET_NOT_ALLOCATED;
}
cn = sock_list_length;
sock_list_length *= 2;
}
//extern int socket (int __domain, int __type, int __protocol) __THROW;
target_fd = socket(send_par.domain(), send_par.ptype(),
send_par.protocol());
if (target_fd <= 0) {
TTCN_error("Cannot open socket \n");
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() = "Cannot open socket";
} else {
log("SocketCAN opened socket %d \n", target_fd);
sock_list[cn].fd = target_fd;
sock_list[cn].status = SOCKET_OPEN;
num_of_sock++;
//Handler_Add_Fd_Read(target_fd);
result.id() = cn;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
incoming_message(result);
log("leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__socket)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__ioctl& send_par) {
log("entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__ioctl)");
struct ifreq ifr;
int sock;
int cn = send_par.id();
int res;
SocketCAN__Types::SocketCAN__ioctl__result result;
if ((cn < sock_list_length) and (sock_list[cn].status == SOCKET_OPEN)) {
sock = sock_list[cn].fd;
if (send_par.ifu().is_present()) {
const OPTIONAL<SocketCAN__Types::SocketCAN__ioctl__ifu>& ifu =
send_par.ifu();
switch (ifu().get_selection()) {
case SocketCAN__Types::SocketCAN__ioctl__ifu::ALT_if__name:
strcpy(ifr.ifr_name, ifu().if__name());
res = ioctl(sock, SIOCGIFINDEX, &ifr);
if (res != 0) {
TTCN_error(
"Ioctl failed on socket: %d with interface name %s\n",
sock, (const char *) ifu().if__name());
result.ifr().if__name() = ifu().if__name();
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() = "Ioctl failed";
} else {
log("SocketCAN ioctl successful on socket %d \n", sock);
result.ifr().if__name() = ifu().if__name();
result.ifr().if__index() = ifr.ifr_ifindex;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
break;
case SocketCAN__Types::SocketCAN__ioctl__ifu::ALT_if__index:
res = ioctl(sock, SIOCGIFNAME, &ifr);
if (res != 0) {
TTCN_error(
"Ioctl failed on socket: %d with interface index %llu \n",
sock, ifu().if__index().get_long_long_val());
result.ifr().if__index() = ifr.ifr_ifindex;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() = "Ioctl failed";
} else {
log("SocketCAN ioctl successful on socket %d \n", sock);
result.ifr().if__name() = ifr.ifr_name;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
break;
default:
TTCN_error("Ioctl failed due to unknown union selection");
break;
}
} else {
// optional ifu filed is not present, set take interface name from applicable TTCN configuration file
if (can_interface_name == NULL) {
TTCN_error(
"Missing mandatory parameter: \"SocketCAN_can_interface_name\" has not been defined in function call to Send Data nor in test configuration file! ");
} else {
strcpy(ifr.ifr_name, can_interface_name);
res = ioctl(sock, SIOCGIFINDEX, &ifr);
if (res != 0) {
TTCN_error(
"Ioctl failed on socket: %d with interface name %s \n",
sock, can_interface_name);
result.ifr().if__index() = ifr.ifr_ifindex;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() = "Ioctl failed";
} else {
log("SocketCAN ioctl successful on socket %d \n", sock);
result.ifr().if__name() = ifr.ifr_name;
result.ifr().if__index() = ifr.ifr_ifindex;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
if (strlen(can_interface_name) <= IFNAMSIZ) {
std::strcpy(ifr.ifr_name, can_interface_name);
} else {
TTCN_error(
"Ioctl failed due to interface name too long.\n");
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"Ioctl failed due to interface name too long";
}
}
}
} else {
TTCN_error("Ioctl failed due to unknown socket reference: %d \n", cn);
result.ifr().if__name() = ifr.ifr_name;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"Ioctl failed due to unknown socket reference";
}
incoming_message(result);
log("SocketCAN__PT::outgoing_send(SocketCAN__ioctl)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__connect& send_par) {
//Client connects to BCM
log("entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__connect)");
int sock;
struct sockaddr_can addr = { };
int cn = send_par.id();
int res;
SocketCAN__Types::SocketCAN__connect__result result;
if ((cn < sock_list_length) and (sock_list[cn].status == SOCKET_OPEN)) {
if (sock_list[cn].protocol_family
== SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_NO_PROTOCOL) {
sock = sock_list[cn].fd;
addr.can_family = AF_CAN;
SocketCAN__Types::SocketCAN__connectu connectu =
send_par.connectu();
switch (connectu.get_selection()) {
case SocketCAN__Types::SocketCAN__connectu::ALT_bcm:
addr.can_ifindex = connectu.bcm().if__index();
sock_list[cn].protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_BCM;
break;
default:
TTCN_error(
"connectu union selection does not exist on socket %d: \n",
sock);
break;
}
log("Connecting socket: %d with index: %d", sock, addr.can_ifindex);
//extern int connect (int __fd, __CONST_SOCKADDR_ARG __addr, socklen_t __len);
res = connect(sock, (struct sockaddr *) &addr, sizeof(addr));
if (res != 0) {
TTCN_error("Connecting to socket %d failed: \n", sock);
log("Connecting to socket %d failed", sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() = "Connecting to socket failed";
} else {
log("Connecting socket %d was successful", sock);
sock_list[cn].protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_BCM;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
sock_list[cn].remote_Addr.can_family = AF_CAN;
Handler_Add_Fd_Read(target_fd);
}
} else {
TTCN_error("Socket reference already connected or bound: %d \n",
cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"Socket reference already connected or bound";
}
} else {
TTCN_error("Unknown socket reference: %d \n", cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() = "Unknown socket reference";
}
incoming_message(result);
log("leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__connect)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__bind& send_par) {
//Client binds
log("entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__bind)");
int sock;
struct sockaddr_can addr = { };
int cn = send_par.id();
int res;
SocketCAN__Types::SocketCAN__bind__result result;
if ((cn < sock_list_length) and (sock_list[cn].status == SOCKET_OPEN)) {
if (sock_list[cn].protocol_family
== SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_NO_PROTOCOL) {
int if_index;
SocketCAN__PortType::SocketCAN__PT_PROVIDER::socket_protocol_family_enum protocol_family;
sock = sock_list[cn].fd;
addr.can_family = AF_CAN;
SocketCAN__Types::SocketCAN__bindu bindu = send_par.bindu();
switch (bindu.get_selection()) {
case SocketCAN__Types::SocketCAN__bindu::ALT_raw: {
const int canfd_on = 1;
setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &canfd_on,
sizeof(canfd_on));
if_index = bindu.raw().if__index();
protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_RAW;
}
break;
case SocketCAN__Types::SocketCAN__bindu::ALT_isotp:
if_index = bindu.isotp().if__index();
addr.can_addr.tp.rx_id = oct2int(bindu.isotp().rx__can__id());
addr.can_addr.tp.tx_id = oct2int(bindu.isotp().tx__can__id());
protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_ISOTP;
break;
default:
TTCN_error(
"bindu union selection does not exist on socket %d: \n",
sock);
break;
}
addr.can_ifindex = if_index;
log("Binding socket: %d with index: %d", sock, if_index);
res = bind(sock, (struct sockaddr *) &addr, sizeof(addr));
if (res != 0) {
log("Binding to socket %d failed", sock);
TTCN_error("Binding to socket %d failed:\n", sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
} else {
log("Binding socket %d was successful", sock);
sock_list[cn].protocol_family = protocol_family;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
sock_list[cn].remote_Addr.can_family = AF_CAN;
Handler_Add_Fd_Read(target_fd);
}
} else {
TTCN_error("Socket reference already connected or bound: %d \n",
cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"Socket reference already connected or bound";
}
} else {
TTCN_error("Unknown socket reference: %d \n", cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() = "Unknown socket reference";
}
incoming_message(result);
log("leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__bind)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__send__data& send_par) {
log(
"entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__send__data)");
SocketCAN__Types::SocketCAN__send__data__result result;
int res = 0;
int sock;
int cn = send_par.id();
if ((cn < sock_list_length)) {
struct sockaddr_can addr;
struct ifreq ifr;
int nrOfBytesSent, nrOfBytestoSend;
sock = sock_list[cn].fd;
if (send_par.ifu().is_present()) {
const OPTIONAL<SocketCAN__Types::SocketCAN__send__data__ifu>& ifu =
send_par.ifu();
switch (ifu().get_selection()) {
case SocketCAN__Types::SocketCAN__send__data__ifu::ALT_if__index:
addr.can_ifindex = ifu().if__index();
addr.can_family = AF_CAN;
break;
case SocketCAN__Types::SocketCAN__send__data__ifu::ALT_if__name:
strcpy(ifr.ifr_name, ifu().if__name());
res = ioctl(sock, SIOCGIFINDEX, &ifr);
if (res != 0) {
TTCN_error(
"SocketCAN: Send CAN frame: Ioctl failed while retrieving the interface : %d with interface index %s\n",
sock, ifr.ifr_name);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN: Send CAN frame: Ioctl failed while retrieving the interface";
}
addr.can_ifindex = ifr.ifr_ifindex;
addr.can_family = AF_CAN;
break;
case SocketCAN__Types::SocketCAN__send__data__ifu::ALT_if__any:
addr.can_ifindex = 0;
addr.can_family = AF_CAN;
break;
default:
TTCN_error(
"SocketCAN: Send CAN frame: Unknown union selection");
res = -1;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN: Send CAN frame: Unknown union selection";
}
} else {
// optional ifu filed is not present, thus send to any interface:
addr.can_ifindex = 0;
addr.can_family = AF_CAN;
}
if (res == 0) { // check if previous interface inquiry step failed
switch (send_par.frame().get_selection()) {
case SocketCAN__Types::SocketCAN__CAN__or__CAN__FD__frame::ALT_can__frame: {
struct can_frame frame;
log("SocketCAN: Sending CAN frame)");
logOctet(" to can id: ",
send_par.frame().can__frame().can__id());
logOctet("containing data: ",
send_par.frame().can__frame().can__pdu());
size_t can_dlc =
send_par.frame().can__frame().can__pdu().lengthof();
frame.can_id = oct2int(send_par.frame().can__frame().can__id());
memcpy(frame.data, send_par.frame().can__frame().can__pdu(),
can_dlc);
frame.can_dlc = can_dlc;
nrOfBytestoSend = sizeof(frame);
if (send_par.ifu().is_present()) {
nrOfBytesSent = sendto(sock, &frame, nrOfBytestoSend, 0,
(struct sockaddr*) &addr, sizeof(addr));
if (nrOfBytesSent < 0) {
log(
"SocketCAN: Sent CAN frame with sendto of size %d failed",
nrOfBytesSent);
TTCN_error(
"SocketCAN send with sendto() error while trying to send %d bytes",
nrOfBytestoSend);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN send with sendto() error";
} else {
log(
"SocketCAN send data with sendto() successful on socket %d \n",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
} else {
nrOfBytesSent = send(sock, &frame, nrOfBytestoSend, 0);
log("Sent CAN frame with send of size %d", nrOfBytesSent);
if (nrOfBytesSent < 0) {
log("Sent CAN frame with send of size %d failed",
nrOfBytesSent);
TTCN_error(
"SocketCAN send with send() error while trying to send CAN frame of %d bytes",
nrOfBytestoSend);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN send with send() error";
} else {
log(
"SocketCAN send data with send() successful on socket %d \n",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
}
break;
#ifdef RAW_CANFD_SUPPORT
case SocketCAN__Types::SocketCAN__CAN__or__CAN__FD__frame::ALT_canfd__frame: {
{
// Enabling FD support had been successful!
log(
"SocketCAN: Enabling FD support had been successful on socket %d",
sock);
struct canfd_frame fd_frame;
log("SocketCAN: Sending CAN FD frame)");
logOctet(" to can id: ",
send_par.frame().canfd__frame().can__id());
logBitstring("with flags: ",
send_par.frame().canfd__frame().can__flags());
logOctet("containing data: ",
send_par.frame().canfd__frame().can__pdu());
size_t len =
send_par.frame().canfd__frame().can__pdu().lengthof();
fd_frame.can_id = oct2int(
send_par.frame().canfd__frame().can__id());
fd_frame.flags = bit2int(
send_par.frame().canfd__frame().can__flags());
memcpy(fd_frame.data,
send_par.frame().canfd__frame().can__pdu(), len);
fd_frame.len = len;
fd_frame.__res0 = 0x00;
fd_frame.__res1 = 0x00;
nrOfBytestoSend = sizeof(fd_frame);
if (send_par.ifu().is_present()) {
nrOfBytesSent = sendto(sock, &fd_frame, nrOfBytestoSend,
0, (struct sockaddr*) &addr, sizeof(addr));
if (nrOfBytesSent < 0) {
TTCN_error(
"SocketCAN FD send with sendto() error while trying to send %d bytes with error code: %d",
nrOfBytestoSend, nrOfBytesSent);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN FD send with sendto() error";
} else {
log(
"SocketCAN: Sent CAN FD frame with sendto() of size %d",
nrOfBytesSent);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
} else {
nrOfBytesSent = send(sock, &fd_frame, nrOfBytestoSend,
0);
if (nrOfBytesSent < 0) {
TTCN_error(
"SocketCAN FD send with send() error while trying to send %d bytes",
nrOfBytestoSend);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN FD send with send() error";
} else {
log(
"SocketCAN: Sent CAN FD frame with send() of size %d",
nrOfBytesSent);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
}
}
break;
#else // RAW_CANFD_SUPPORT
case SocketCAN__Types::SocketCAN__CAN__or__CAN__FD__frame::ALT_canfd__frame: {
TTCN_error(
"SocketCAN: CAN FD is not supported by your current kernel error");
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN: CAN FD is not supported by your current kernel error";
}
break;
#endif // RAW_CANFD_SUPPORT
default:
TTCN_error("SocketCAN send unknown frame type error");
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN send unknown frame type error";
break;
}
log("SocketCAN: Nr of bytes sent = %d", nrOfBytesSent);
if ((nrOfBytesSent > 0) and (nrOfBytesSent != nrOfBytestoSend)
and (nrOfBytestoSend != 0)) {
TTCN_error(
"Send system call failed: %d bytes were sent instead of %d",
nrOfBytesSent, nrOfBytestoSend);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN write failed as wrong number of bytes have been written";
}
}
} else {
TTCN_error("SocketCAN: Unknown socket reference: %d \n", cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() = "Unknown socket reference";
}
incoming_message(result);
log("leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__send__data)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__write__data& send_par) {
log(
"entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__write__data)");
SocketCAN__Types::SocketCAN__write__data__result result;
int sock;
int cn = send_par.id();
if ((cn < sock_list_length)
and (sock_list[cn].protocol_family
== SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_BCM)
and (sock_list[cn].status == SOCKET_OPEN)) {
sock = sock_list[cn].fd;
switch (send_par.bcm__tx__msg().frames().get_selection()) {
case Bcm::SocketCAN__bcm__frame_frames::ALT_can__frame: {
int nrOfBytesSent = 0;
int nrOfBytestoSend = 0;
struct {
struct bcm_msg_head msg_head;
struct can_frame frame[BCM_FRAME_BUFFER_SIZE];
} bcm_msg = { };
const Bcm::SocketCAN__bcm__frame& bcm__tx__msg =
send_par.bcm__tx__msg();
int nframes = bcm__tx__msg.frames().can__frame().lengthof();
if (nframes > BCM_FRAME_BUFFER_SIZE) {
TTCN_error(
"SocketCAN: Writing data: number of CAN frames too large: %d \n",
nframes);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN sending CAN data with write() failed, as more than BCM_FRAME_BUFFER_SIZE number of CAN frames to be sent";
TTCN_error(
"SocketCAN sending CAN data with write() failed, as more than BCM_FRAME_BUFFER_SIZE number of CAN frames to be sent");
} else {
const Bcm::SocketCAN__bcm__frame& bcm__tx__msg =
send_par.bcm__tx__msg();
bcm_msg.msg_head.opcode = oct2int(bcm__tx__msg.opcode());
bcm_msg.msg_head.flags = bit2int(
send_par.bcm__tx__msg().flags());
bcm_msg.msg_head.count = bcm__tx__msg.count();
bcm_msg.msg_head.ival1.tv_sec = bcm__tx__msg.ival1().tv__sec();
bcm_msg.msg_head.ival1.tv_usec =
bcm__tx__msg.ival1().tv__usec();
bcm_msg.msg_head.ival2.tv_sec = bcm__tx__msg.ival2().tv__sec();
bcm_msg.msg_head.ival2.tv_usec =
bcm__tx__msg.ival2().tv__usec();
bcm_msg.msg_head.can_id = oct2int(bcm__tx__msg.can__id());
bcm_msg.msg_head.nframes = nframes;
log("SocketCAN: Sending BCM Message)");
logOctet(" opcode: ", bcm__tx__msg.opcode());
logBitstring(" flags: ", bcm__tx__msg.flags());
logInteger(" count: ", bcm__tx__msg.count());
logInteger(" ival1: ", bcm__tx__msg.ival1().tv__sec());
logInteger(" ival1: ", bcm__tx__msg.ival1().tv__usec());
logInteger(" ival2: ", bcm__tx__msg.ival2().tv__sec());
logInteger(" ival2: ", bcm__tx__msg.ival2().tv__usec());
logOctet(" can_id: ", bcm__tx__msg.can__id());
logInteger(" nframes: ", nframes);
for (int i = 0; i < nframes; i++) {
const Bcm::SocketCAN__bcm__frame_frames_can__frame& frame =
bcm__tx__msg.frames().can__frame();
bcm_msg.frame[i].can_id = oct2int(frame[i].can__id());
unsigned int can_dlc;
can_dlc = frame[i].can__pdu().lengthof();
if (can_dlc > CAN_MAX_DLEN) {
TTCN_error(
"SocketCAN writing data: CAN pdu size too large\n");
can_dlc = CAN_MAX_DLEN;
};
log(" containing CAN frame:)");
logOctet(" can id: ", frame[i].can__id());
logInteger(" can dlc: ", can_dlc);
bcm_msg.frame[i].can_dlc = can_dlc;
for (unsigned int j = 0; j < can_dlc; j++) {
bcm_msg.frame[i].data[j] = oct2int(
frame[i].can__pdu()[j]);
logOctet(" data: ", frame[i].can__pdu()[j]);
}
}
// assuming that the struct within the structure are aligned cm_msg without passing
// BCM_write does not calculate unused fields from nframes to BCM_FRAME_BUFFER_SIZE
nrOfBytestoSend = sizeof(struct bcm_msg_head)
+ nframes * sizeof(struct can_frame);
nrOfBytesSent = write(sock, &bcm_msg, (int) nrOfBytestoSend);
if ((nrOfBytesSent) < 0) {
int myerrno = errno;
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = myerrno;
result.result().err__text() =
"SocketCAN sending CAN data with write() failed";
logInteger("bcm_msg.msg_head.can_id: ",
(bcm_msg.msg_head.can_id));
logInteger("bcm_msg.msg_head.count: ",
bcm_msg.msg_head.count);
logInteger("bcm_msg.msg_head.flags: ",
bcm_msg.msg_head.flags);
logInteger("bcm_msg.msg_head.ival1.tv_sec: ",
bcm_msg.msg_head.ival1.tv_sec);
logInteger("bcm_msg.msg_head.ival1.tv_usec: ",
bcm_msg.msg_head.ival1.tv_usec);
logInteger("bcm_msg.msg_head.ival2.tv_sec: ",
bcm_msg.msg_head.ival2.tv_sec);
logInteger("bcm_msg.msg_head.ival2.tv_usec: ",
bcm_msg.msg_head.ival2.tv_usec);
logInteger("bcm_msg.msg_head.nframes: ",
bcm_msg.msg_head.nframes);
logInteger("bcm_msg.msg_head.opcode: ",
bcm_msg.msg_head.opcode);
TTCN_error(
//"SocketCAN sending CAN data with write() failed");
"SocketCAN sending CAN data with write() failed. nrOfBytestoSend: %d, sizeof(struct bcm_msg_head): %d, nframes: %d, sizeof(struct can_frame): %d, nrOfBytesSent: %d, errno: %d\n",
nrOfBytestoSend,
((int) sizeof(struct bcm_msg_head)),
((int) nframes), ((int) sizeof(struct can_frame)),
(int) nrOfBytesSent, (int) myerrno);
} else {
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = nrOfBytesSent;
result.result().err__text() = OMIT_VALUE;
}
log("Nr of bytes sent = %d", nrOfBytesSent);
if (nrOfBytesSent != nrOfBytestoSend) {
TTCN_error(
"SocketCAN frame write failed: %d bytes were sent instead of %d",
nrOfBytesSent, nrOfBytestoSend);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN write failed as wrong number of bytes have been written";
}
}
}
break;
#ifdef BCM_CANFD_SUPPORT
case Bcm::SocketCAN__bcm__frame_frames::ALT_canfd__frame: {
int nrOfBytesSent = 0;
int nrOfBytestoSend = 0;
struct {
struct bcm_msg_head msg_head;
struct canfd_frame frame[BCM_FRAME_BUFFER_SIZE];
}bcm_msg;
const Bcm::SocketCAN__bcm__frame& bcm__tx__msg =
send_par.bcm__tx__msg();
unsigned int nframes =
bcm__tx__msg.frames().canfd__frame().lengthof();
if (nframes > BCM_FRAME_BUFFER_SIZE) {
TTCN_error(
"SocketCAN writing data: number of CAN FD frames too large: %d \n",
nframes);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN sending CAN FD data with write() failed, as more than BCM_FRAME_BUFFER_SIZE number of CAN FD frames to be sent";
TTCN_error(
"SocketCAN sending CAN FD data with write() failed, as more than BCM_FRAME_BUFFER_SIZE number of CAN FD frames to be sent");
} else {
const Bcm::SocketCAN__bcm__frame& bcm__tx__msg =
send_par.bcm__tx__msg();
bcm_msg.msg_head.opcode = oct2int(bcm__tx__msg.opcode());
bcm_msg.msg_head.flags = bit2int(
send_par.bcm__tx__msg().flags()) | CAN_FD_FRAME;
// set CAN_FD_FRAME-flag to indicate canfd frames are following
bcm_msg.msg_head.count = bcm__tx__msg.count();
bcm_msg.msg_head.ival1.tv_sec = bcm__tx__msg.ival1().tv__sec();
bcm_msg.msg_head.ival1.tv_usec =
bcm__tx__msg.ival1().tv__usec();
bcm_msg.msg_head.ival2.tv_sec = bcm__tx__msg.ival2().tv__sec();
bcm_msg.msg_head.ival2.tv_usec =
bcm__tx__msg.ival2().tv__usec();
bcm_msg.msg_head.nframes = nframes;
log("SocketCAN: Sending BCM Message)");
logOctet(" opcode: ", bcm__tx__msg.opcode());
logBitstring(" flags: ", bcm__tx__msg.flags());
logInteger(" count: ", bcm__tx__msg.count());
logInteger(" ival1: ", bcm__tx__msg.ival1().tv__sec());
logInteger(" ival1: ", bcm__tx__msg.ival1().tv__usec());
logInteger(" ival2: ", bcm__tx__msg.ival2().tv__sec());
logInteger(" ival2: ", bcm__tx__msg.ival2().tv__usec());
logOctet(" can_id: ", send_par.bcm__tx__msg().can__id());
logInteger(" nframes: ", nframes);
for (unsigned int i = 0; i < nframes; i++) {
const Bcm::SocketCAN__bcm__frame_frames_canfd__frame& frame =
bcm__tx__msg.frames().canfd__frame();
bcm_msg.frame[i].can_id = oct2int(frame[i].can__id());
bcm_msg.frame[i].flags = bit2int(frame[i].can__flags());
unsigned int len = frame[i].can__pdu().lengthof();
if (len > CANFD_MAX_DLEN) {
TTCN_error("Writing data: CAN FD pdu size too large\n");
len = CANFD_MAX_DLEN;
};
log(" containing CAN FD frame:)");
logOctet(" can id: ", frame[i].can__id());
logInteger(" can len: ", len);
bcm_msg.frame[i].len = len;
for (unsigned int j = 0; j < len; j++) {
bcm_msg.frame[i].data[j] = oct2int(
frame[i].can__pdu()[j]);
logOctet(" data: ", frame[i].can__pdu()[j]);
}
}
// assuming that the structs within the structure are aligned cm_msg without passing
// BCM_write does not calculate unused fields from nframes to BCM_FRAME_BUFFER_SIZE
nrOfBytestoSend = sizeof(struct bcm_msg_head)
+ nframes * sizeof(struct canfd_frame);
nrOfBytesSent = write(sock, &bcm_msg, nrOfBytestoSend);
if (nrOfBytesSent < 0) {
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN sending CAN FD data with write() failed";
TTCN_error(
"SocketCAN sending CAN FD data with write() failed");
} else {
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
log("Nr of bytes sent = %d", nrOfBytesSent);
if (nrOfBytesSent != nrOfBytestoSend) {
TTCN_error(
"SocketCAN CAN fd frame write failed: %d bytes were sent instead of %d",
nrOfBytesSent, nrOfBytestoSend);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN write failed as wrong number of bytes have been written";
}
}
break;
#endif //BCM_CANFD_SUPPORT
default:
TTCN_error("SocketCAN write unknown frame type error");
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN write unknown frame type error";
break;
}
} else {
TTCN_error(
"SocketCAN write data failed due to unknown socket reference: %d \n",
cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN write data failed due to unknown socket reference";
}
incoming_message(result);
log(
"leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__write__data)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__write__isotp& send_par) {
log(
"entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__write__isotp)");
SocketCAN__Types::SocketCAN__write__isotp__result result;
int sock;
int cn = send_par.id();
if ((cn < sock_list_length)
and (sock_list[cn].protocol_family
== SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_PROTOCOL_CAN_ISOTP)
and (sock_list[cn].status == SOCKET_OPEN)) {
sock = sock_list[cn].fd;
int nrOfBytesSent = 0;
int nrOfBytestoSend = send_par.pdu().lengthof();
logOctet("Writing ISOTP data on socket: ", send_par.pdu());
nrOfBytesSent = write(sock, send_par.pdu(), nrOfBytestoSend);
log(
"Written to ISOTP %d bytes data of the expected %d bytes on socket %d: ",
nrOfBytesSent, nrOfBytestoSend, sock);
if (nrOfBytesSent != nrOfBytestoSend) {
TTCN_warning(
"SocketCAN write isotp has written %d bytes, which are fewer than expected %d bytes to socket: %d \n",
nrOfBytesSent, nrOfBytestoSend, sock);
}
if (nrOfBytesSent < 0) {
TTCN_error("SocketCAN write isotp failed with error code %d:\n",
errno);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() = "SocketCAN write isotp failed";
} else {
log("SocketCAN: write isotp successful on socket %d", sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
} else {
TTCN_error(
"SocketCAN write isotp failed due to unknown socket reference: %d with protocol family %d and status %d\n",
cn, sock_list[cn].protocol_family, sock_list[cn].status);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN write isotp failed due to unknown socket reference";
}
incoming_message(result);
log(
"leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__write__isotp)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__setsockopt& send_par) {
log(
"entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__setsockopt)");
int sock;
int cn = send_par.id();
int res;
SocketCAN__Types::SocketCAN__setsockopt__result result;
if ((cn < sock_list_length) and (sock_list[cn].status == SOCKET_OPEN)) {
sock = sock_list[cn].fd;
SocketCAN__Types::SocketCAN__setsockopt__commandu::union_selection_type command_selection =
send_par.command().get_selection();
switch (command_selection) {
case SocketCAN__Types::SocketCAN__setsockopt__commandu::ALT_rfilter: {
std::size_t rfilter_size = (sizeof(send_par.command().rfilter())
/ sizeof(send_par.command().rfilter()[0]));
struct can_filter rfilter[rfilter_size];
if (rfilter_size == 0) {
// deactivate filters
res = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, NULL, 0);
} else {
for (std::size_t i = 0; i < rfilter_size; i++) {
rfilter[i].can_id = oct2int(
send_par.command().rfilter()[i].can__id());
rfilter[i].can_mask = oct2int(
send_par.command().rfilter()[i].can__mask());
};
res = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FILTER, &rfilter,
sizeof(rfilter));
}
if (res < 0) {
TTCN_error(
"SocketCAN setsockopt rfilter failed with error code %d:\n",
errno);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN setsockopt rfilter failed";
} else {
log("SocketCAN: setsockopt rfilter successful on socket %d",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
break;
case SocketCAN__Types::SocketCAN__setsockopt__commandu::ALT_err__mask: {
can_err_mask_t err_mask = bit2int(send_par.command().err__mask());
res = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_ERR_FILTER, &err_mask,
sizeof(err_mask));
if (res < 0) {
int myerrno = errno;
TTCN_error(
"SocketCAN setsockopt can__err__mask failed with error code %d:\n",
myerrno);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = myerrno;
result.result().err__text() =
"SocketCAN setsockopt can__err__mask failed";
} else {
log(
"SocketCAN: setsockopt can__err__mask successful on socket %d",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
break;
case SocketCAN__Types::SocketCAN__setsockopt__commandu::ALT_loopback: {
int loopback = send_par.command().loopback();
res = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_LOOPBACK, &loopback,
sizeof(loopback));
if (res < 0) {
int myerrno = errno;
TTCN_error(
"SocketCAN setsockopt loopbackfailed with error code %d:\n",
myerrno);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = myerrno;
result.result().err__text() =
"SocketCAN setsockopt loopback failed";
} else {
log("SocketCAN: setsockopt loopback successful on socket %d",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
break;
case SocketCAN__Types::SocketCAN__setsockopt__commandu::ALT_recv__own__msgs: {
int recv_own_msgs = send_par.command().recv__own__msgs();
res = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_RECV_OWN_MSGS,
&recv_own_msgs, sizeof(recv_own_msgs));
if (res < 0) {
TTCN_error(
"SocketCAN setsockopt recv__own__msg failed with error code %d:\n",
errno);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN setsockopt recv__own__msg failed";
} else {
log(
"SocketCAN: setsockopt recv__own__msg successful on socket %d",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
break;
case SocketCAN__Types::SocketCAN__setsockopt__commandu::ALT_fd__frames: {
int fd_frames = send_par.command().fd__frames();
res = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_FD_FRAMES, &fd_frames,
sizeof(fd_frames));
if (res < 0) {
TTCN_error(
"SocketCAN setsockopt fd__frames failed with error code %d:\n",
errno);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN setsockopt fd__frames failed";
} else {
log("SocketCAN: setsockopt fd__frames successful on socket %d",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
break;
case SocketCAN__Types::SocketCAN__setsockopt__commandu::ALT_join__filters: {
{
int join_filters = send_par.command().join__filters();
res = setsockopt(sock, SOL_CAN_RAW, CAN_RAW_JOIN_FILTERS,
&join_filters, sizeof(join_filters));
if (res < 0) {
TTCN_error(
"SocketCAN setsockopt join__filters failed with error code %d:\n",
errno);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() =
"SocketCAN setsockopt join__filters failed";
} else {
log(
"SocketCAN: setsockopt join__filterssuccessful on socket %d",
sock);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__SUCCESS;
result.result().err() = OMIT_VALUE;
result.result().err__text() = OMIT_VALUE;
}
}
}
break;
default: {
TTCN_error(
"SocketCAN: Unknown SocketCAN_setsockopt commandu union selection: %d \n",
cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = OMIT_VALUE;
result.result().err__text() =
"SocketCAN: Unknown SocketCAN_setsockopt commandu union selection";
break;
}
}
} else {
TTCN_error("SocketCAN: Unknown socket reference: %d \n", cn);
result.result().result__code() =
SocketCAN__Types::SocketCAN__Result__code::SocketCAN__ERROR;
result.result().err() = errno;
result.result().err__text() = "SocketCAN: Unknown socket reference";
}
incoming_message(result);
log("leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__setsockopt)");
}
void SocketCAN__PT_PROVIDER::outgoing_send(
const SocketCAN__Types::SocketCAN__close& send_par) {
log("entering SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__close)");
int sock = sock_list[send_par.id()].fd;
sock_list[send_par.id()].status = SOCKET_NOT_ALLOCATED;
sock_list[send_par.id()].fd = 0;
sock_list[send_par.id()].protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_NO_PROTOCOL;
num_of_sock--;
Handler_Remove_Fd_Read(sock);
close(sock);
log("leaving SocketCAN__PT_PROVIDER::outgoing_send(SocketCAN__close)");
}
void SocketCAN__PT_PROVIDER::reset_configuration() {
free(can_interface_name);
can_interface_name = NULL;
debugging = false;
debugging_configured = false;
}
void SocketCAN__PT_PROVIDER::InitStrPar(char *&par, const char* name,
const char* val) {
if (name)
log("%s: Reading testport parameter: "
"%s = %s", port_name, name, val);
if (par)
free(par);
par = (char*) malloc(strlen(val) + 1);
if (par == NULL)
TTCN_error("Not enough memory.");
strcpy(par, val);
}
void SocketCAN__PT_PROVIDER::log(const char *fmt, ...) {
if (debugging == true) {
TTCN_Logger::begin_event (TTCN_DEBUG);
TTCN_Logger::log_event("SocketCAN test port (%s): ", get_name());
va_list args;
va_start(args, fmt);
TTCN_Logger::log_event_va_list(fmt, args);
va_end(args);
TTCN_Logger::end_event();
}
}
void SocketCAN__PT_PROVIDER::logOctet(const char *prompt,
const OCTETSTRING& msg) {
if (debugging == true) { //if debug
TTCN_Logger::begin_event (TTCN_DEBUG);
TTCN_Logger::log_event_str(prompt);
TTCN_Logger::log_event("Size: %d,\nMsg: ", msg.lengthof());
for (int i = 0; i < msg.lengthof(); i++) {
TTCN_Logger::log_event(" %02x", ((const unsigned char*) msg)[i]);
}
TTCN_Logger::log_event("\n");
TTCN_Logger::end_event();
}
}
void SocketCAN__PT_PROVIDER::logHex(const char *prompt, const HEXSTRING& msg) {
if (debugging == true) { //if debug
TTCN_Logger::begin_event (TTCN_DEBUG);
TTCN_Logger::log_event_str(prompt);
TTCN_Logger::log_event("Size: %d,\nMsg: ", msg.lengthof());
for (int i = 0; i < msg.lengthof(); i++) {
TTCN_Logger::log_event(" %02x", ((const unsigned char*) msg)[i]);
}
TTCN_Logger::log_event("\n");
TTCN_Logger::end_event();
}
}
void SocketCAN__PT_PROVIDER::logInteger(const char *prompt, const int number) {
if (debugging) { //if debug
TTCN_Logger::begin_event (TTCN_DEBUG);
TTCN_Logger::log_event_str(prompt);
TTCN_Logger::log_event("Value: %d,\n: ", number);
TTCN_Logger::log_event("\n");
TTCN_Logger::end_event();
}
}
void SocketCAN__PT_PROVIDER::logBitstring(const char *prompt,
const BITSTRING& msg) {
if (debugging == true) { //if debug
TTCN_Logger::begin_event (TTCN_DEBUG);
TTCN_Logger::log_event_str(prompt);
int len = msg.lengthof();
TTCN_Logger::log_event("Size: %d,\nMsg: 0b", len);
for (int i = 0; i < msg.lengthof(); i++) {
TTCN_Logger::log_event("%d", (int) bit2int(msg[i]));
}
TTCN_Logger::log_event("\n");
TTCN_Logger::end_event();
}
}
void SocketCAN__PT_PROVIDER::setUpSocket() {
log("entering SocketCAN__PT_PROVIDER::setUpSocket()");
log("leaving SocketCAN__PT_PROVIDER::setUpSocket()");
}
void SocketCAN__PT_PROVIDER::closeDownSocket() {
log("entering SocketCAN__PT_PROVIDER::closeDownSocket()");
for (int a = 0; a < sock_list_length; a++) {
if (sock_list[a].status == SOCKET_OPEN) {
sock_list[a].status = SOCKET_NOT_ALLOCATED;
sock_list[a].protocol_family =
SocketCAN__PortType::SocketCAN__PT_PROVIDER::SOCKET_NO_PROTOCOL;
close(sock_list[a].fd);
Handler_Remove_Fd_Read(sock_list[a].fd);
}
}
Free(sock_list);
sock_list = NULL;
log("leaving SocketCAN__PT_PROVIDER::closeDownSocket()");
}
}
/* end of namespace */