move part of isobusfs code to the libj1939
Move part of isobusfs which can be reused by other applications to the libj1939. By the way, reuse some of new libj1939 code in the j1939cat. Signed-off-by: Oleksij Rempel <linux@rempel-privat.de>pull/524/head
parent
69c1e8289d
commit
af95ee0c6d
|
|
@ -105,6 +105,10 @@ if(NOT ANDROID)
|
||||||
libj1939.c
|
libj1939.c
|
||||||
)
|
)
|
||||||
|
|
||||||
|
target_link_libraries(j1939
|
||||||
|
PRIVATE can
|
||||||
|
)
|
||||||
|
|
||||||
add_library(isobusfs SHARED
|
add_library(isobusfs SHARED
|
||||||
isobusfs/isobusfs_cmn.c
|
isobusfs/isobusfs_cmn.c
|
||||||
isobusfs/isobusfs_cmn_dh.c
|
isobusfs/isobusfs_cmn_dh.c
|
||||||
|
|
@ -134,7 +138,7 @@ if(NOT ANDROID)
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(isobusfs-cli
|
target_link_libraries(isobusfs-cli
|
||||||
PRIVATE isobusfs can
|
PRIVATE isobusfs can j1939
|
||||||
)
|
)
|
||||||
|
|
||||||
add_executable(isobusfs-srv
|
add_executable(isobusfs-srv
|
||||||
|
|
@ -148,7 +152,7 @@ if(NOT ANDROID)
|
||||||
)
|
)
|
||||||
|
|
||||||
target_link_libraries(isobusfs-srv
|
target_link_libraries(isobusfs-srv
|
||||||
PRIVATE isobusfs can
|
PRIVATE isobusfs can j1939
|
||||||
)
|
)
|
||||||
|
|
||||||
install(TARGETS
|
install(TARGETS
|
||||||
|
|
@ -167,7 +171,7 @@ foreach(name ${PROGRAMS})
|
||||||
|
|
||||||
if("${name}" IN_LIST PROGRAMS_J1939)
|
if("${name}" IN_LIST PROGRAMS_J1939)
|
||||||
target_link_libraries(${name}
|
target_link_libraries(${name}
|
||||||
PRIVATE j1939
|
PRIVATE j1939 can
|
||||||
)
|
)
|
||||||
elseif("${name}" IN_LIST PROGRAMS_CANLIB)
|
elseif("${name}" IN_LIST PROGRAMS_CANLIB)
|
||||||
target_link_libraries(${name}
|
target_link_libraries(${name}
|
||||||
|
|
|
||||||
|
|
@ -336,7 +336,7 @@ int isobusfs_cli_process_events_and_tasks(struct isobusfs_priv *priv)
|
||||||
if (priv->state == ISOBUSFS_CLI_STATE_SELFTEST)
|
if (priv->state == ISOBUSFS_CLI_STATE_SELFTEST)
|
||||||
dont_wait = true;
|
dont_wait = true;
|
||||||
|
|
||||||
ret = isobusfs_cmn_prepare_for_events(&priv->cmn, &nfds, dont_wait);
|
ret = libj1939_prepare_for_events(&priv->cmn, &nfds, dont_wait);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -354,7 +354,7 @@ static int isobusfs_cli_sock_main_prepare(struct isobusfs_priv *priv)
|
||||||
struct sockaddr_can addr = priv->sockname;
|
struct sockaddr_can addr = priv->sockname;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -362,7 +362,7 @@ static int isobusfs_cli_sock_main_prepare(struct isobusfs_priv *priv)
|
||||||
|
|
||||||
/* TODO: this is TX only socket */
|
/* TODO: this is TX only socket */
|
||||||
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_FS_TO_CL;
|
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_FS_TO_CL;
|
||||||
ret = isobusfs_cmn_bind_socket(priv->sock_main, &addr);
|
ret = libj1939_bind_socket(priv->sock_main, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -370,7 +370,7 @@ static int isobusfs_cli_sock_main_prepare(struct isobusfs_priv *priv)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_socket_prio(priv->sock_main, ISOBUSFS_PRIO_DEFAULT);
|
ret = libj1939_socket_prio(priv->sock_main, ISOBUSFS_PRIO_DEFAULT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -378,7 +378,7 @@ static int isobusfs_cli_sock_main_prepare(struct isobusfs_priv *priv)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd,
|
||||||
priv->sock_main, EPOLLIN);
|
priv->sock_main, EPOLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -398,7 +398,7 @@ static int isobusfs_cli_sock_int_prepare(struct isobusfs_priv *priv)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd,
|
||||||
STDIN_FILENO, EPOLLIN);
|
STDIN_FILENO, EPOLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -407,7 +407,7 @@ static int isobusfs_cli_sock_ccm_prepare(struct isobusfs_priv *priv)
|
||||||
struct sockaddr_can addr = priv->sockname;
|
struct sockaddr_can addr = priv->sockname;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -419,7 +419,7 @@ static int isobusfs_cli_sock_ccm_prepare(struct isobusfs_priv *priv)
|
||||||
|
|
||||||
/* TODO: this is TX only socket */
|
/* TODO: this is TX only socket */
|
||||||
addr.can_addr.j1939.pgn = J1939_NO_PGN;
|
addr.can_addr.j1939.pgn = J1939_NO_PGN;
|
||||||
ret = isobusfs_cmn_bind_socket(priv->sock_ccm, &addr);
|
ret = libj1939_bind_socket(priv->sock_ccm, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -427,7 +427,7 @@ static int isobusfs_cli_sock_ccm_prepare(struct isobusfs_priv *priv)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_socket_prio(priv->sock_ccm, ISOBUSFS_PRIO_DEFAULT);
|
ret = libj1939_socket_prio(priv->sock_ccm, ISOBUSFS_PRIO_DEFAULT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -436,7 +436,7 @@ static int isobusfs_cli_sock_ccm_prepare(struct isobusfs_priv *priv)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* poll for errors to get confirmation if our packets are send */
|
/* poll for errors to get confirmation if our packets are send */
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_ccm,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_ccm,
|
||||||
EPOLLERR);
|
EPOLLERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -445,23 +445,23 @@ static int isobusfs_cli_sock_nack_prepare(struct isobusfs_priv *priv)
|
||||||
struct sockaddr_can addr = priv->sockname;
|
struct sockaddr_can addr = priv->sockname;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->sock_nack = ret;
|
priv->sock_nack = ret;
|
||||||
|
|
||||||
addr.can_addr.j1939.pgn = ISOBUS_PGN_ACK;
|
addr.can_addr.j1939.pgn = ISOBUS_PGN_ACK;
|
||||||
ret = isobusfs_cmn_bind_socket(priv->sock_nack, &addr);
|
ret = libj1939_bind_socket(priv->sock_nack, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_socket_prio(priv->sock_nack, ISOBUSFS_PRIO_ACK);
|
ret = libj1939_socket_prio(priv->sock_nack, ISOBUSFS_PRIO_ACK);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* poll for errors to get confirmation if our packets are send */
|
/* poll for errors to get confirmation if our packets are send */
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd,
|
||||||
priv->sock_nack, EPOLLIN);
|
priv->sock_nack, EPOLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -471,7 +471,7 @@ static int isobusfs_cli_sock_bcast_prepare(struct isobusfs_priv *priv)
|
||||||
struct sockaddr_can addr = priv->sockname;
|
struct sockaddr_can addr = priv->sockname;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -481,11 +481,11 @@ static int isobusfs_cli_sock_bcast_prepare(struct isobusfs_priv *priv)
|
||||||
addr.can_addr.j1939.name = J1939_NO_NAME;
|
addr.can_addr.j1939.name = J1939_NO_NAME;
|
||||||
addr.can_addr.j1939.addr = J1939_NO_ADDR;
|
addr.can_addr.j1939.addr = J1939_NO_ADDR;
|
||||||
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_FS_TO_CL;
|
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_FS_TO_CL;
|
||||||
ret = isobusfs_cmn_bind_socket(priv->sock_bcast_rx, &addr);
|
ret = libj1939_bind_socket(priv->sock_bcast_rx, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_set_broadcast(priv->sock_bcast_rx);
|
ret = libj1939_set_broadcast(priv->sock_bcast_rx);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -493,7 +493,7 @@ static int isobusfs_cli_sock_bcast_prepare(struct isobusfs_priv *priv)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_bcast_rx,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_bcast_rx,
|
||||||
EPOLLIN);
|
EPOLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -501,7 +501,7 @@ static int isobusfs_cli_sock_prepare(struct isobusfs_priv *priv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_create_epoll();
|
ret = libj1939_create_epoll();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -647,8 +647,8 @@ int main(int argc, char *argv[])
|
||||||
|
|
||||||
bzero(priv, sizeof(*priv));
|
bzero(priv, sizeof(*priv));
|
||||||
|
|
||||||
isobusfs_init_sockaddr_can(&priv->sockname, J1939_NO_PGN);
|
libj1939_init_sockaddr_can(&priv->sockname, J1939_NO_PGN);
|
||||||
isobusfs_init_sockaddr_can(&priv->peername, ISOBUSFS_PGN_CL_TO_FS);
|
libj1939_init_sockaddr_can(&priv->peername, ISOBUSFS_PGN_CL_TO_FS);
|
||||||
|
|
||||||
ret = isobusfs_cli_parse_args(priv, argc, argv);
|
ret = isobusfs_cli_parse_args(priv, argc, argv);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ struct isobusfs_priv {
|
||||||
struct isobusfs_buf_log tx_buf_log;
|
struct isobusfs_buf_log tx_buf_log;
|
||||||
enum isobusfs_cli_state state;
|
enum isobusfs_cli_state state;
|
||||||
|
|
||||||
struct isobusfs_cmn cmn;
|
struct libj1939_cmn cmn;
|
||||||
uint8_t handle;
|
uint8_t handle;
|
||||||
|
|
||||||
uint32_t read_offset;
|
uint32_t read_offset;
|
||||||
|
|
|
||||||
|
|
@ -125,29 +125,6 @@ void isobusfs_log_level_set(log_level_t level)
|
||||||
log_level = level;
|
log_level = level;
|
||||||
}
|
}
|
||||||
|
|
||||||
int isobusfs_get_timeout_ms(struct timespec *ts)
|
|
||||||
{
|
|
||||||
struct timespec curr_time;
|
|
||||||
int64_t time_diff;
|
|
||||||
int timeout_ms;
|
|
||||||
|
|
||||||
clock_gettime(CLOCK_MONOTONIC, &curr_time);
|
|
||||||
time_diff = timespec_diff_ms(ts, &curr_time);
|
|
||||||
if (time_diff < 0) {
|
|
||||||
/* Too late to send next message. Send it now */
|
|
||||||
timeout_ms = 0;
|
|
||||||
} else {
|
|
||||||
if (time_diff > INT_MAX) {
|
|
||||||
warn("timeout too long: %" PRId64 " ms", time_diff);
|
|
||||||
time_diff = INT_MAX;
|
|
||||||
}
|
|
||||||
|
|
||||||
timeout_ms = time_diff;
|
|
||||||
}
|
|
||||||
|
|
||||||
return timeout_ms;
|
|
||||||
}
|
|
||||||
|
|
||||||
const char *isobusfs_error_to_str(enum isobusfs_error err)
|
const char *isobusfs_error_to_str(enum isobusfs_error err)
|
||||||
{
|
{
|
||||||
switch (err) {
|
switch (err) {
|
||||||
|
|
@ -238,15 +215,6 @@ enum isobusfs_error linux_error_to_isobusfs_error(int linux_err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void isobusfs_init_sockaddr_can(struct sockaddr_can *sac, uint32_t pgn)
|
|
||||||
{
|
|
||||||
sac->can_family = AF_CAN;
|
|
||||||
sac->can_addr.j1939.addr = J1939_NO_ADDR;
|
|
||||||
sac->can_addr.j1939.name = J1939_NO_NAME;
|
|
||||||
sac->can_addr.j1939.pgn = pgn;
|
|
||||||
}
|
|
||||||
|
|
||||||
static void isobusfs_print_timestamp(struct isobusfs_err_msg *emsg,
|
static void isobusfs_print_timestamp(struct isobusfs_err_msg *emsg,
|
||||||
const char *name, struct timespec *cur)
|
const char *name, struct timespec *cur)
|
||||||
{
|
{
|
||||||
|
|
@ -520,28 +488,6 @@ int isobusfs_send(int sock, const void *data, size_t len,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* isobusfs_cmn_open_socket - Open a CAN J1939 socket
|
|
||||||
*
|
|
||||||
* This function opens a CAN J1939 socket and returns the file descriptor
|
|
||||||
* on success. In case of an error, the function returns the negative
|
|
||||||
* error code.
|
|
||||||
*/
|
|
||||||
int isobusfs_cmn_open_socket(void)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
/* Create a new CAN J1939 socket */
|
|
||||||
ret = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
|
|
||||||
if (ret < 0) {
|
|
||||||
/* Get the error code and print an error message */
|
|
||||||
ret = -errno;
|
|
||||||
pr_err("socket(j1939): %d (%s)", ret, strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* isobusfs_cmn_configure_socket_filter - Configure a J1939 socket filter
|
* isobusfs_cmn_configure_socket_filter - Configure a J1939 socket filter
|
||||||
* @sock: Socket file descriptor
|
* @sock: Socket file descriptor
|
||||||
|
|
@ -650,47 +596,6 @@ int isobusfs_cmn_configure_error_queue(int sock)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* isobusfs_cmn_bind_socket - Bind a J1939 socket to a given address
|
|
||||||
* @sock: socket file descriptor
|
|
||||||
* @addr: pointer to a sockaddr_can structure containing the address
|
|
||||||
* information to bind the socket to
|
|
||||||
*
|
|
||||||
* This function binds a J1939 socket to the specified address. It returns
|
|
||||||
* 0 on successful binding or a negative error code on failure.
|
|
||||||
*
|
|
||||||
* Return: 0 on success, or a negative error code on failure.
|
|
||||||
*/
|
|
||||||
int isobusfs_cmn_bind_socket(int sock, struct sockaddr_can *addr)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = bind(sock, (void *)addr, sizeof(*addr));
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
pr_err("failed to bind: %d (%s)", ret, strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int isobusfs_cmn_socket_prio(int sock, int prio)
|
|
||||||
{
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
|
||||||
&prio, sizeof(prio));
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
pr_warn("Failed to set priority %i. Error %i (%s)", prio, ret,
|
|
||||||
strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int isobusfs_cmn_connect_socket(int sock, struct sockaddr_can *addr)
|
int isobusfs_cmn_connect_socket(int sock, struct sockaddr_can *addr)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
@ -705,32 +610,6 @@ int isobusfs_cmn_connect_socket(int sock, struct sockaddr_can *addr)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* isobusfs_cmn_set_broadcast - Enable broadcast option for a socket
|
|
||||||
* @sock: socket file descriptor
|
|
||||||
*
|
|
||||||
* This function enables the SO_BROADCAST option for the given socket,
|
|
||||||
* allowing it to send and receive broadcast messages. It returns 0 on success
|
|
||||||
* or a negative error code on failure.
|
|
||||||
*
|
|
||||||
* Return: 0 on success, or a negative error code on failure.
|
|
||||||
*/
|
|
||||||
int isobusfs_cmn_set_broadcast(int sock)
|
|
||||||
{
|
|
||||||
int broadcast = true;
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast,
|
|
||||||
sizeof(broadcast));
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
pr_err("setsockopt(SO_BROADCAST): %d (%s)", ret, strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
/* FIXME: linger is currently not supported by the kernel J1939 stack
|
/* FIXME: linger is currently not supported by the kernel J1939 stack
|
||||||
* but it would be nice to have it. Especially if we wont to stop sending
|
* but it would be nice to have it. Especially if we wont to stop sending
|
||||||
* messages on a socket when the connection is lost.
|
* messages on a socket when the connection is lost.
|
||||||
|
|
@ -753,70 +632,6 @@ int isobusfs_cmn_set_linger(int sock)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
int isobusfs_cmn_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events)
|
|
||||||
{
|
|
||||||
struct epoll_event ev = {0};
|
|
||||||
int ret;
|
|
||||||
|
|
||||||
ev.events = events;
|
|
||||||
ev.data.fd = sock;
|
|
||||||
|
|
||||||
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock, &ev);
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = errno;
|
|
||||||
pr_err("epoll_ctl(EPOLL_CTL_ADD): %d (%s)", ret, strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
int isobusfs_cmn_create_epoll(void)
|
|
||||||
{
|
|
||||||
int ret, epoll_fd;
|
|
||||||
|
|
||||||
epoll_fd = epoll_create1(0);
|
|
||||||
if (epoll_fd < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
pr_err("epoll_create1: %d (%s)", ret, strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return epoll_fd;
|
|
||||||
}
|
|
||||||
|
|
||||||
int isobusfs_cmn_prepare_for_events(struct isobusfs_cmn *cmn, int *nfds,
|
|
||||||
bool dont_wait)
|
|
||||||
{
|
|
||||||
int ret, timeout_ms;
|
|
||||||
|
|
||||||
if (dont_wait)
|
|
||||||
timeout_ms = 0;
|
|
||||||
else
|
|
||||||
timeout_ms = isobusfs_get_timeout_ms(&cmn->next_send_time);
|
|
||||||
|
|
||||||
ret = epoll_wait(cmn->epoll_fd, cmn->epoll_events,
|
|
||||||
cmn->epoll_events_size, timeout_ms);
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
if (ret != -EINTR) {
|
|
||||||
*nfds = 0;
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
*nfds = ret;
|
|
||||||
|
|
||||||
ret = clock_gettime(CLOCK_MONOTONIC, &cmn->last_time);
|
|
||||||
if (ret < 0) {
|
|
||||||
ret = -errno;
|
|
||||||
pr_err("failed to get time: %i (%s)", ret, strerror(ret));
|
|
||||||
return ret;
|
|
||||||
}
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
void isobusfs_cmn_dump_last_x_bytes(const uint8_t *buffer, size_t buffer_size,
|
void isobusfs_cmn_dump_last_x_bytes(const uint8_t *buffer, size_t buffer_size,
|
||||||
size_t x)
|
size_t x)
|
||||||
{
|
{
|
||||||
|
|
|
||||||
|
|
@ -257,15 +257,6 @@ struct isobusfs_err_msg {
|
||||||
struct isobusfs_stats *stats;
|
struct isobusfs_stats *stats;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct isobusfs_cmn {
|
|
||||||
int epoll_fd;
|
|
||||||
struct epoll_event *epoll_events;
|
|
||||||
size_t epoll_events_size;
|
|
||||||
struct timespec next_send_time;
|
|
||||||
struct timespec last_time;
|
|
||||||
};
|
|
||||||
|
|
||||||
void isobusfs_init_sockaddr_can(struct sockaddr_can *sac, uint32_t pgn);
|
|
||||||
int isobusfs_recv_err(int sock, struct isobusfs_err_msg *emsg);
|
int isobusfs_recv_err(int sock, struct isobusfs_err_msg *emsg);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
@ -300,7 +291,6 @@ static inline uint8_t isobusfs_cg_function_to_buf(enum isobusfs_cg cg,
|
||||||
const char *isobusfs_error_to_str(enum isobusfs_error err);
|
const char *isobusfs_error_to_str(enum isobusfs_error err);
|
||||||
enum isobusfs_error linux_error_to_isobusfs_error(int linux_err);
|
enum isobusfs_error linux_error_to_isobusfs_error(int linux_err);
|
||||||
|
|
||||||
int isobusfs_get_timeout_ms(struct timespec *ts);
|
|
||||||
void isobusfs_send_nack(int sock, struct isobusfs_msg *msg);
|
void isobusfs_send_nack(int sock, struct isobusfs_msg *msg);
|
||||||
void isobufs_store_tx_data(struct isobusfs_buf_log *buffer, uint8_t *data);
|
void isobufs_store_tx_data(struct isobusfs_buf_log *buffer, uint8_t *data);
|
||||||
void isobusfs_dump_tx_data(const struct isobusfs_buf_log *buffer);
|
void isobusfs_dump_tx_data(const struct isobusfs_buf_log *buffer);
|
||||||
|
|
@ -313,20 +303,11 @@ int isobusfs_send(int sock, const void *data, size_t len,
|
||||||
void isobusfs_cmn_dump_last_x_bytes(const uint8_t *buffer, size_t buffer_size,
|
void isobusfs_cmn_dump_last_x_bytes(const uint8_t *buffer, size_t buffer_size,
|
||||||
size_t x);
|
size_t x);
|
||||||
|
|
||||||
int isobusfs_cmn_open_socket(void);
|
|
||||||
int isobusfs_cmn_configure_socket_filter(int sock, pgn_t pgn);
|
int isobusfs_cmn_configure_socket_filter(int sock, pgn_t pgn);
|
||||||
int isobusfs_cmn_configure_error_queue(int sock);
|
int isobusfs_cmn_configure_error_queue(int sock);
|
||||||
int isobusfs_cmn_bind_socket(int sock, struct sockaddr_can *addr);
|
|
||||||
int isobusfs_cmn_connect_socket(int sock, struct sockaddr_can *addr);
|
int isobusfs_cmn_connect_socket(int sock, struct sockaddr_can *addr);
|
||||||
int isobusfs_cmn_set_broadcast(int sock);
|
|
||||||
int isobusfs_cmn_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events);
|
|
||||||
int isobusfs_cmn_create_epoll(void);
|
|
||||||
int isobusfs_cmn_socket_prio(int sock, int prio);
|
|
||||||
int isobusfs_cmn_set_linger(int sock);
|
int isobusfs_cmn_set_linger(int sock);
|
||||||
|
|
||||||
int isobusfs_cmn_prepare_for_events(struct isobusfs_cmn *cmn, int *nfds,
|
|
||||||
bool dont_wait);
|
|
||||||
|
|
||||||
/* ============ directory handling ============ */
|
/* ============ directory handling ============ */
|
||||||
int isobusfs_cmn_dh_validate_dir_path(const char *path, bool writable);
|
int isobusfs_cmn_dh_validate_dir_path(const char *path, bool writable);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -250,7 +250,7 @@ static int isobusfs_srv_process_events_and_tasks(struct isobusfs_srv_priv *priv)
|
||||||
{
|
{
|
||||||
int ret, nfds;
|
int ret, nfds;
|
||||||
|
|
||||||
ret = isobusfs_cmn_prepare_for_events(&priv->cmn, &nfds, false);
|
ret = libj1939_prepare_for_events(&priv->cmn, &nfds, false);
|
||||||
if (ret)
|
if (ret)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -268,7 +268,7 @@ static int isobusfs_srv_sock_fss_prepare(struct isobusfs_srv_priv *priv)
|
||||||
struct sockaddr_can addr = priv->addr;
|
struct sockaddr_can addr = priv->addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -283,11 +283,11 @@ static int isobusfs_srv_sock_fss_prepare(struct isobusfs_srv_priv *priv)
|
||||||
* PGN?
|
* PGN?
|
||||||
*/
|
*/
|
||||||
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS;
|
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS;
|
||||||
ret = isobusfs_cmn_bind_socket(priv->sock_fss, &addr);
|
ret = libj1939_bind_socket(priv->sock_fss, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_set_broadcast(priv->sock_fss);
|
ret = libj1939_set_broadcast(priv->sock_fss);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -295,7 +295,7 @@ static int isobusfs_srv_sock_fss_prepare(struct isobusfs_srv_priv *priv)
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_socket_prio(priv->sock_fss, ISOBUSFS_PRIO_FSS);
|
ret = libj1939_socket_prio(priv->sock_fss, ISOBUSFS_PRIO_FSS);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -308,7 +308,7 @@ static int isobusfs_srv_sock_fss_prepare(struct isobusfs_srv_priv *priv)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* poll for errors to get confirmation if our packets are send */
|
/* poll for errors to get confirmation if our packets are send */
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_fss,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_fss,
|
||||||
EPOLLERR);
|
EPOLLERR);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -317,7 +317,7 @@ static int isobusfs_srv_sock_in_prepare(struct isobusfs_srv_priv *priv)
|
||||||
struct sockaddr_can addr = priv->addr;
|
struct sockaddr_can addr = priv->addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -325,11 +325,11 @@ static int isobusfs_srv_sock_in_prepare(struct isobusfs_srv_priv *priv)
|
||||||
|
|
||||||
/* keep address and name and overwrite PGN */
|
/* keep address and name and overwrite PGN */
|
||||||
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS;
|
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS;
|
||||||
ret = isobusfs_cmn_bind_socket(priv->sock_in, &addr);
|
ret = libj1939_bind_socket(priv->sock_in, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_in,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd, priv->sock_in,
|
||||||
EPOLLIN);
|
EPOLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -338,23 +338,23 @@ static int isobusfs_srv_sock_nack_prepare(struct isobusfs_srv_priv *priv)
|
||||||
struct sockaddr_can addr = priv->addr;
|
struct sockaddr_can addr = priv->addr;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
priv->sock_nack = ret;
|
priv->sock_nack = ret;
|
||||||
|
|
||||||
addr.can_addr.j1939.pgn = ISOBUS_PGN_ACK;
|
addr.can_addr.j1939.pgn = ISOBUS_PGN_ACK;
|
||||||
ret = isobusfs_cmn_bind_socket(priv->sock_nack, &addr);
|
ret = libj1939_bind_socket(priv->sock_nack, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_socket_prio(priv->sock_nack, ISOBUSFS_PRIO_ACK);
|
ret = libj1939_socket_prio(priv->sock_nack, ISOBUSFS_PRIO_ACK);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
/* poll for errors to get confirmation if our packets are send */
|
/* poll for errors to get confirmation if our packets are send */
|
||||||
return isobusfs_cmn_add_socket_to_epoll(priv->cmn.epoll_fd,
|
return libj1939_add_socket_to_epoll(priv->cmn.epoll_fd,
|
||||||
priv->sock_nack, EPOLLIN);
|
priv->sock_nack, EPOLLIN);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -370,7 +370,7 @@ static int isobusfs_srv_sock_prepare(struct isobusfs_srv_priv *priv)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
ret = isobusfs_cmn_create_epoll();
|
ret = libj1939_create_epoll();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -762,7 +762,7 @@ int main(int argc, char *argv[])
|
||||||
memset(priv, 0, sizeof(*priv));
|
memset(priv, 0, sizeof(*priv));
|
||||||
|
|
||||||
/* Initialize sockaddr_can with a non-configurable PGN */
|
/* Initialize sockaddr_can with a non-configurable PGN */
|
||||||
isobusfs_init_sockaddr_can(&priv->addr, J1939_NO_PGN);
|
libj1939_init_sockaddr_can(&priv->addr, J1939_NO_PGN);
|
||||||
|
|
||||||
priv->server_version = ISOBUSFS_SRV_VERSION;
|
priv->server_version = ISOBUSFS_SRV_VERSION;
|
||||||
/* Parse command line arguments */
|
/* Parse command line arguments */
|
||||||
|
|
|
||||||
|
|
@ -103,7 +103,7 @@ struct isobusfs_srv_priv {
|
||||||
int clients_count;
|
int clients_count;
|
||||||
struct isobusfs_buf_log tx_buf_log;
|
struct isobusfs_buf_log tx_buf_log;
|
||||||
|
|
||||||
struct isobusfs_cmn cmn;
|
struct libj1939_cmn cmn;
|
||||||
|
|
||||||
struct isobusfs_srv_volume volumes[ISOBUSFS_SRV_MAX_VOLUMES];
|
struct isobusfs_srv_volume volumes[ISOBUSFS_SRV_MAX_VOLUMES];
|
||||||
int volume_count;
|
int volume_count;
|
||||||
|
|
|
||||||
|
|
@ -213,14 +213,14 @@ static int isobusfs_srv_init_client(struct isobusfs_srv_priv *priv,
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = isobusfs_cmn_open_socket();
|
ret = libj1939_open_socket();
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
client->sock = ret;
|
client->sock = ret;
|
||||||
|
|
||||||
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS;
|
addr.can_addr.j1939.pgn = ISOBUSFS_PGN_CL_TO_FS;
|
||||||
ret = isobusfs_cmn_bind_socket(client->sock, &addr);
|
ret = libj1939_bind_socket(client->sock, &addr);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
@ -243,7 +243,7 @@ static int isobusfs_srv_init_client(struct isobusfs_srv_priv *priv,
|
||||||
goto close_socket;
|
goto close_socket;
|
||||||
}
|
}
|
||||||
|
|
||||||
ret = isobusfs_cmn_socket_prio(client->sock, ISOBUSFS_PRIO_DEFAULT);
|
ret = libj1939_socket_prio(client->sock, ISOBUSFS_PRIO_DEFAULT);
|
||||||
if (ret < 0)
|
if (ret < 0)
|
||||||
return ret;
|
return ret;
|
||||||
|
|
||||||
|
|
|
||||||
13
j1939cat.c
13
j1939cat.c
|
|
@ -97,15 +97,6 @@ static const char help_msg[] =
|
||||||
|
|
||||||
static const char optstring[] = "?hi:vs:rp:P:R:B";
|
static const char optstring[] = "?hi:vs:rp:P:R:B";
|
||||||
|
|
||||||
|
|
||||||
static void j1939cat_init_sockaddr_can(struct sockaddr_can *sac)
|
|
||||||
{
|
|
||||||
sac->can_family = AF_CAN;
|
|
||||||
sac->can_addr.j1939.addr = J1939_NO_ADDR;
|
|
||||||
sac->can_addr.j1939.name = J1939_NO_NAME;
|
|
||||||
sac->can_addr.j1939.pgn = J1939_NO_PGN;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
static ssize_t j1939cat_send_one(struct j1939cat_priv *priv, int out_fd,
|
||||||
const void *buf, size_t buf_size)
|
const void *buf, size_t buf_size)
|
||||||
{
|
{
|
||||||
|
|
@ -766,8 +757,8 @@ int main(int argc, char *argv[])
|
||||||
priv->polltimeout = 100000;
|
priv->polltimeout = 100000;
|
||||||
priv->repeat = 1;
|
priv->repeat = 1;
|
||||||
|
|
||||||
j1939cat_init_sockaddr_can(&priv->sockname);
|
libj1939_init_sockaddr_can(&priv->sockname, J1939_NO_PGN);
|
||||||
j1939cat_init_sockaddr_can(&priv->peername);
|
libj1939_init_sockaddr_can(&priv->peername, J1939_NO_PGN);
|
||||||
|
|
||||||
ret = j1939cat_parse_args(priv, argc, argv);
|
ret = j1939cat_parse_args(priv, argc, argv);
|
||||||
if (ret)
|
if (ret)
|
||||||
|
|
|
||||||
244
libj1939.c
244
libj1939.c
|
|
@ -11,19 +11,24 @@
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#include <err.h>
|
#include <err.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <fcntl.h>
|
||||||
#include <inttypes.h>
|
#include <inttypes.h>
|
||||||
|
#include <limits.h>
|
||||||
|
#include <linux/kernel.h>
|
||||||
|
#include <net/if.h>
|
||||||
|
#include <net/if.h>
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <sys/epoll.h>
|
||||||
#include <fcntl.h>
|
|
||||||
#include <net/if.h>
|
|
||||||
#include <sys/ioctl.h>
|
#include <sys/ioctl.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#include <net/if.h>
|
|
||||||
|
|
||||||
#include "libj1939.h"
|
#include "libj1939.h"
|
||||||
|
#include "lib.h"
|
||||||
|
|
||||||
/* static data */
|
/* static data */
|
||||||
static struct if_nameindex *saved;
|
static struct if_nameindex *saved;
|
||||||
|
|
@ -195,3 +200,232 @@ const char *libj1939_addr2str(const struct sockaddr_can *can)
|
||||||
return buf;
|
return buf;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void libj1939_init_sockaddr_can(struct sockaddr_can *sac, uint32_t pgn)
|
||||||
|
{
|
||||||
|
sac->can_family = AF_CAN;
|
||||||
|
sac->can_addr.j1939.addr = J1939_NO_ADDR;
|
||||||
|
sac->can_addr.j1939.name = J1939_NO_NAME;
|
||||||
|
sac->can_addr.j1939.pgn = pgn;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_open_socket - Open a new J1939 socket
|
||||||
|
*
|
||||||
|
* This function opens a new J1939 socket.
|
||||||
|
*
|
||||||
|
* Return: The file descriptor of the new socket, or a negative error code.
|
||||||
|
*/
|
||||||
|
int libj1939_open_socket(void)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
/* Create a new CAN J1939 socket */
|
||||||
|
ret = socket(PF_CAN, SOCK_DGRAM, CAN_J1939);
|
||||||
|
if (ret < 0) {
|
||||||
|
/* Get the error code and print an error message */
|
||||||
|
ret = -errno;
|
||||||
|
pr_err("socket(j1939): %d (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_bind_socket - Bind a J1939 socket to a specific address
|
||||||
|
* @sock: The file descriptor of the socket
|
||||||
|
* @addr: The address to bind to
|
||||||
|
*
|
||||||
|
* This function binds a J1939 socket to a specific address.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code.
|
||||||
|
*/
|
||||||
|
int libj1939_bind_socket(int sock, struct sockaddr_can *addr)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = bind(sock, (void *)addr, sizeof(*addr));
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_err("failed to bind: %d (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_socket_prio - Set the priority of a J1939 socket
|
||||||
|
* @sock: The file descriptor of the socket
|
||||||
|
* @prio: The priority to set
|
||||||
|
*
|
||||||
|
* This function sets the priority of a J1939 socket.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code.
|
||||||
|
*/
|
||||||
|
int libj1939_socket_prio(int sock, int prio)
|
||||||
|
{
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = setsockopt(sock, SOL_CAN_J1939, SO_J1939_SEND_PRIO,
|
||||||
|
&prio, sizeof(prio));
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_warn("Failed to set priority %i. Error %i (%s)", prio, ret,
|
||||||
|
strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_set_broadcast - Enable broadcast on a J1939 socket
|
||||||
|
* @sock: The file descriptor of the socket
|
||||||
|
*
|
||||||
|
* This function enables broadcast on a J1939 socket.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code.
|
||||||
|
*/
|
||||||
|
int libj1939_set_broadcast(int sock)
|
||||||
|
{
|
||||||
|
int broadcast = true;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ret = setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &broadcast,
|
||||||
|
sizeof(broadcast));
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_err("setsockopt(SO_BROADCAST): %d (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_add_socket_to_epoll - Add a socket to an epoll instance
|
||||||
|
* @epoll_fd: The file descriptor of the epoll instance
|
||||||
|
* @sock: The file descriptor of the socket
|
||||||
|
* @events: The events to monitor
|
||||||
|
*
|
||||||
|
* This function adds a socket to an epoll instance.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code.
|
||||||
|
*/
|
||||||
|
int libj1939_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events)
|
||||||
|
{
|
||||||
|
struct epoll_event ev = {0};
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
ev.events = events;
|
||||||
|
ev.data.fd = sock;
|
||||||
|
|
||||||
|
ret = epoll_ctl(epoll_fd, EPOLL_CTL_ADD, sock, &ev);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = errno;
|
||||||
|
pr_err("epoll_ctl(EPOLL_CTL_ADD): %d (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_create_epoll - Create a new epoll instance
|
||||||
|
*
|
||||||
|
* This function creates a new epoll instance.
|
||||||
|
*
|
||||||
|
* Return: The file descriptor of the new epoll instance, or a negative error
|
||||||
|
* code.
|
||||||
|
*/
|
||||||
|
int libj1939_create_epoll(void)
|
||||||
|
{
|
||||||
|
int ret, epoll_fd;
|
||||||
|
|
||||||
|
epoll_fd = epoll_create1(0);
|
||||||
|
if (epoll_fd < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_err("epoll_create1: %d (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return epoll_fd;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_get_timeout_ms - Get the timeout in milliseconds until a specific
|
||||||
|
* time
|
||||||
|
* @ts: The time to wait for
|
||||||
|
* @return: The timeout in milliseconds until the specified time
|
||||||
|
*
|
||||||
|
* This function calculates the timeout in milliseconds until a specific time.
|
||||||
|
*
|
||||||
|
* Return: The timeout in milliseconds until the specified time.
|
||||||
|
*/
|
||||||
|
static int libj1939_get_timeout_ms(struct timespec *ts)
|
||||||
|
{
|
||||||
|
struct timespec curr_time;
|
||||||
|
int64_t time_diff;
|
||||||
|
int timeout_ms;
|
||||||
|
|
||||||
|
clock_gettime(CLOCK_MONOTONIC, &curr_time);
|
||||||
|
time_diff = timespec_diff_ms(ts, &curr_time);
|
||||||
|
if (time_diff < 0) {
|
||||||
|
/* Too late to send next message. Send it now */
|
||||||
|
timeout_ms = 0;
|
||||||
|
} else {
|
||||||
|
if (time_diff > INT_MAX) {
|
||||||
|
pr_warn("timeout too long: %" PRId64 " ms", time_diff);
|
||||||
|
time_diff = INT_MAX;
|
||||||
|
}
|
||||||
|
|
||||||
|
timeout_ms = time_diff;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timeout_ms;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* libj1939_prepare_for_events - Prepare and wait for events on an epoll
|
||||||
|
* @cmn: The common J1939 instance data
|
||||||
|
* @nfds: The number of file descriptors that are ready
|
||||||
|
* @dont_wait: Don't wait for events, just check if there are any
|
||||||
|
*
|
||||||
|
* This function calculates the timeout until the next message should be sent
|
||||||
|
* or any other event should be handled, prepares the epoll instance for events
|
||||||
|
* by waiting for the specified timeout or until an event occurs, and waits for
|
||||||
|
* events on the epoll instance.
|
||||||
|
*
|
||||||
|
* Return: 0 on success, or a negative error code.
|
||||||
|
*/
|
||||||
|
int libj1939_prepare_for_events(struct libj1939_cmn *cmn, int *nfds,
|
||||||
|
bool dont_wait)
|
||||||
|
{
|
||||||
|
int ret, timeout_ms;
|
||||||
|
|
||||||
|
if (dont_wait)
|
||||||
|
timeout_ms = 0;
|
||||||
|
else
|
||||||
|
timeout_ms = libj1939_get_timeout_ms(&cmn->next_send_time);
|
||||||
|
|
||||||
|
ret = epoll_wait(cmn->epoll_fd, cmn->epoll_events,
|
||||||
|
cmn->epoll_events_size, timeout_ms);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
if (ret != -EINTR) {
|
||||||
|
*nfds = 0;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
*nfds = ret;
|
||||||
|
|
||||||
|
ret = clock_gettime(CLOCK_MONOTONIC, &cmn->last_time);
|
||||||
|
if (ret < 0) {
|
||||||
|
ret = -errno;
|
||||||
|
pr_err("failed to get time: %i (%s)", ret, strerror(ret));
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
|
||||||
24
libj1939.h
24
libj1939.h
|
|
@ -13,9 +13,11 @@
|
||||||
/* needed on some 64 bit platforms to get consistent 64-bit types */
|
/* needed on some 64 bit platforms to get consistent 64-bit types */
|
||||||
#define __SANE_USERSPACE_TYPES__
|
#define __SANE_USERSPACE_TYPES__
|
||||||
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <linux/can.h>
|
#include <linux/can.h>
|
||||||
#include <linux/can/j1939.h>
|
#include <linux/can/j1939.h>
|
||||||
|
#include <stdbool.h>
|
||||||
|
#include <stdint.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
#ifndef J1939_LIB_H
|
#ifndef J1939_LIB_H
|
||||||
#define J1939_LIB_H
|
#define J1939_LIB_H
|
||||||
|
|
@ -24,10 +26,30 @@
|
||||||
extern "C" {
|
extern "C" {
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
struct libj1939_cmn {
|
||||||
|
int epoll_fd;
|
||||||
|
struct epoll_event *epoll_events;
|
||||||
|
size_t epoll_events_size;
|
||||||
|
struct timespec next_send_time;
|
||||||
|
struct timespec last_time;
|
||||||
|
};
|
||||||
|
|
||||||
void libj1939_parse_canaddr(char *spec, struct sockaddr_can *paddr);
|
void libj1939_parse_canaddr(char *spec, struct sockaddr_can *paddr);
|
||||||
extern int libj1939_str2addr(const char *str, char **endp, struct sockaddr_can *can);
|
extern int libj1939_str2addr(const char *str, char **endp, struct sockaddr_can *can);
|
||||||
extern const char *libj1939_addr2str(const struct sockaddr_can *can);
|
extern const char *libj1939_addr2str(const struct sockaddr_can *can);
|
||||||
|
|
||||||
|
void libj1939_init_sockaddr_can(struct sockaddr_can *sac, uint32_t pgn);
|
||||||
|
|
||||||
|
int libj1939_open_socket(void);
|
||||||
|
int libj1939_bind_socket(int sock, struct sockaddr_can *addr);
|
||||||
|
int libj1939_socket_prio(int sock, int prio);
|
||||||
|
int libj1939_set_broadcast(int sock);
|
||||||
|
int libj1939_add_socket_to_epoll(int epoll_fd, int sock, uint32_t events);
|
||||||
|
int libj1939_create_epoll(void);
|
||||||
|
|
||||||
|
int libj1939_prepare_for_events(struct libj1939_cmn *cmn, int *nfds,
|
||||||
|
bool dont_wait);
|
||||||
|
|
||||||
#ifdef __cplusplus
|
#ifdef __cplusplus
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue