can: add conn_can top layer interface
This module provide support for raw can and isotp socket-like user interface.
This commit is contained in:
parent
63ca443b05
commit
ab5f8548f2
@ -583,6 +583,12 @@ ifneq (,$(filter can_isotp,$(USEMODULE)))
|
|||||||
USEMODULE += xtimer
|
USEMODULE += xtimer
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter conn_can,$(USEMODULE)))
|
||||||
|
USEMODULE += can
|
||||||
|
USEMODULE += can_mbox
|
||||||
|
USEMODULE += xtimer
|
||||||
|
endif
|
||||||
|
|
||||||
ifneq (,$(filter random,$(USEMODULE)))
|
ifneq (,$(filter random,$(USEMODULE)))
|
||||||
# select default prng
|
# select default prng
|
||||||
ifeq (,$(filter prng_%,$(USEMODULE)))
|
ifeq (,$(filter prng_%,$(USEMODULE)))
|
||||||
|
|||||||
@ -2,6 +2,7 @@ PSEUDOMODULES += auto_init_gnrc_rpl
|
|||||||
PSEUDOMODULES += can_mbox
|
PSEUDOMODULES += can_mbox
|
||||||
PSEUDOMODULES += can_pm
|
PSEUDOMODULES += can_pm
|
||||||
PSEUDOMODULES += can_raw
|
PSEUDOMODULES += can_raw
|
||||||
|
PSEUDOMODULES += conn_can_isotp_multi
|
||||||
PSEUDOMODULES += core_%
|
PSEUDOMODULES += core_%
|
||||||
PSEUDOMODULES += emb6_router
|
PSEUDOMODULES += emb6_router
|
||||||
PSEUDOMODULES += gnrc_ipv6_default
|
PSEUDOMODULES += gnrc_ipv6_default
|
||||||
|
|||||||
@ -3,4 +3,8 @@ ifneq (,$(filter can_isotp,$(USEMODULE)))
|
|||||||
DIRS += isotp
|
DIRS += isotp
|
||||||
endif
|
endif
|
||||||
|
|
||||||
|
ifneq (,$(filter conn_can,$(USEMODULE)))
|
||||||
|
DIRS += conn
|
||||||
|
endif
|
||||||
|
|
||||||
include $(RIOTBASE)/Makefile.base
|
include $(RIOTBASE)/Makefile.base
|
||||||
|
|||||||
3
sys/can/conn/Makefile
Normal file
3
sys/can/conn/Makefile
Normal file
@ -0,0 +1,3 @@
|
|||||||
|
MODULE = conn_can
|
||||||
|
|
||||||
|
include $(RIOTBASE)/Makefile.base
|
||||||
419
sys/can/conn/isotp.c
Normal file
419
sys/can/conn/isotp.c
Normal file
@ -0,0 +1,419 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 OTA keys S.A.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Implementation of isotp CAN connection
|
||||||
|
*
|
||||||
|
* @author Vincent Dupont <vincent@otakeys.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef MODULE_CAN_ISOTP
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "can/conn/isotp.h"
|
||||||
|
#include "can/isotp.h"
|
||||||
|
#include "can/device.h"
|
||||||
|
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
#include "utlist.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "xtimer.h"
|
||||||
|
|
||||||
|
#define _TIMEOUT_TX_MSG_TYPE (0x8000)
|
||||||
|
#define _TIMEOUT_RX_MSG_TYPE (0x8001)
|
||||||
|
#define _CLOSE_CONN_MSG_TYPE (0x8002)
|
||||||
|
#define _TIMEOUT_MSG_VALUE (0xABCDEFAB)
|
||||||
|
|
||||||
|
#ifndef CONN_CAN_ISOTP_TIMEOUT_TX_CONF
|
||||||
|
#define CONN_CAN_ISOTP_TIMEOUT_TX_CONF (10 * US_PER_SEC)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
static inline void put_msg(conn_can_isotp_t *conn, msg_t *msg)
|
||||||
|
{
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
mbox_put(&conn->master->mbox, msg);
|
||||||
|
#else
|
||||||
|
mbox_put(&conn->mbox, msg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void get_msg(conn_can_isotp_t *conn, msg_t *msg)
|
||||||
|
{
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
mbox_get(&conn->master->mbox, msg);
|
||||||
|
#else
|
||||||
|
mbox_get(&conn->mbox, msg);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_isotp_create(conn_can_isotp_t *conn, struct isotp_options *options, int ifnum)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(options != NULL);
|
||||||
|
assert(ifnum < CAN_DLL_NUMOF);
|
||||||
|
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
DEBUG("conn_can_isotp_create: conn=%p, conn->master=%p, ifnum=%d\n",
|
||||||
|
(void *)conn, (void *)conn->master, ifnum);
|
||||||
|
|
||||||
|
if (conn->master == conn || conn->master == NULL) {
|
||||||
|
conn->master = conn;
|
||||||
|
conn->master->next = NULL;
|
||||||
|
mutex_init(&conn->master->lock);
|
||||||
|
mutex_lock(&conn->master->lock);
|
||||||
|
DEBUG("conn_can_isotp_create: init master conn\n");
|
||||||
|
mbox_init(&conn->master->mbox, conn->master->mbox_queue, CONN_CAN_ISOTP_MBOX_SIZE);
|
||||||
|
mutex_unlock(&conn->master->lock);
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
mbox_init(&conn->mbox, conn->mbox_queue, CONN_CAN_ISOTP_MBOX_SIZE);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
conn->ifnum = ifnum;
|
||||||
|
|
||||||
|
memset(&conn->isotp, 0, sizeof(struct isotp));
|
||||||
|
conn->isotp.opt = *options;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_isotp_bind(conn_can_isotp_t *conn)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(conn->isotp.opt.tx_id != 0 || conn->isotp.opt.rx_id != 0);
|
||||||
|
|
||||||
|
DEBUG("conn_can_isotp_bind: conn=%p, ifnum=%d\n",
|
||||||
|
(void *)conn, conn->ifnum);
|
||||||
|
|
||||||
|
if (conn->bound) {
|
||||||
|
return -EALREADY;
|
||||||
|
}
|
||||||
|
msg_t msg;
|
||||||
|
int ret;
|
||||||
|
can_reg_entry_t entry;
|
||||||
|
entry.ifnum = conn->ifnum;
|
||||||
|
entry.type = CAN_TYPE_MBOX;
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
assert(conn->master != NULL);
|
||||||
|
|
||||||
|
entry.target.mbox = &(conn->master->mbox);
|
||||||
|
if (conn != conn->master) {
|
||||||
|
mutex_lock(&conn->master->lock);
|
||||||
|
LL_APPEND(conn->master->next, (conn_can_isotp_slave_t *)conn);
|
||||||
|
mutex_unlock(&conn->master->lock);
|
||||||
|
}
|
||||||
|
ret = mbox_try_get(&conn->master->mbox, &msg);
|
||||||
|
#else
|
||||||
|
entry.target.mbox = &conn->mbox;
|
||||||
|
ret = mbox_try_get(&conn->mbox, &msg);
|
||||||
|
#endif
|
||||||
|
if ((ret == 1) && (msg.type != _CLOSE_CONN_MSG_TYPE)) {
|
||||||
|
DEBUG("conn_can_isotp_bind: msg in queue type=%x\n", msg.type);
|
||||||
|
put_msg(conn, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
ret = isotp_bind(&conn->isotp, &entry, conn);
|
||||||
|
if (!ret) {
|
||||||
|
conn->bound = 1;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tx_conf_timeout(void *arg)
|
||||||
|
{
|
||||||
|
conn_can_isotp_t *conn = arg;
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
msg.type = _TIMEOUT_TX_MSG_TYPE;
|
||||||
|
msg.content.value = _TIMEOUT_MSG_VALUE;
|
||||||
|
|
||||||
|
put_msg(conn, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_isotp_send(conn_can_isotp_t *conn, const void *buf, size_t size, int flags)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(buf != NULL || size == 0);
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
|
||||||
|
if (!conn->bound) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & CAN_ISOTP_TX_DONT_WAIT) {
|
||||||
|
return isotp_send(&conn->isotp, buf, size, flags);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xtimer_t timer;
|
||||||
|
timer.callback = _tx_conf_timeout;
|
||||||
|
timer.arg = conn;
|
||||||
|
xtimer_set(&timer, CONN_CAN_ISOTP_TIMEOUT_TX_CONF);
|
||||||
|
|
||||||
|
ret = isotp_send(&conn->isotp, buf, size, flags);
|
||||||
|
|
||||||
|
msg_t msg;
|
||||||
|
while (1) {
|
||||||
|
get_msg(conn, &msg);
|
||||||
|
switch (msg.type) {
|
||||||
|
case CAN_MSG_TX_ERROR:
|
||||||
|
if (msg.content.ptr == conn) {
|
||||||
|
ret = -EIO;
|
||||||
|
}
|
||||||
|
/* No break */
|
||||||
|
case CAN_MSG_TX_CONFIRMATION:
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
if (msg.content.ptr != conn) {
|
||||||
|
mbox_put(&conn->master->mbox, &msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
return ret;
|
||||||
|
case _TIMEOUT_TX_MSG_TYPE:
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
default:
|
||||||
|
DEBUG("conn_can_isotp_send: unexpected msg %x, requeing\n", msg.type);
|
||||||
|
put_msg(conn, &msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _rx_timeout(void *arg)
|
||||||
|
{
|
||||||
|
conn_can_isotp_t *conn = arg;
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
msg.type = _TIMEOUT_RX_MSG_TYPE;
|
||||||
|
msg.content.value = _TIMEOUT_MSG_VALUE;
|
||||||
|
|
||||||
|
put_msg(conn, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_isotp_recv(conn_can_isotp_t *conn, void *buf, size_t size, uint32_t timeout)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(buf != NULL);
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
gnrc_pktsnip_t *snip;
|
||||||
|
|
||||||
|
if (!conn->bound) {
|
||||||
|
return -ENOTCONN;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
if (conn->rx) {
|
||||||
|
snip = conn->rx->data.iov_base;
|
||||||
|
if (snip->size <= size) {
|
||||||
|
memcpy(buf, snip->data, snip->size);
|
||||||
|
ret = snip->size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -EOVERFLOW;
|
||||||
|
}
|
||||||
|
isotp_free_rx(conn->rx);
|
||||||
|
conn->rx = NULL;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
xtimer_t timer;
|
||||||
|
if (timeout != 0) {
|
||||||
|
timer.callback = _rx_timeout;
|
||||||
|
timer.arg = conn;
|
||||||
|
xtimer_set(&timer, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_t msg;
|
||||||
|
can_rx_data_t *rx;
|
||||||
|
|
||||||
|
while (1) {
|
||||||
|
get_msg(conn, &msg);
|
||||||
|
switch (msg.type) {
|
||||||
|
case CAN_MSG_RX_INDICATION:
|
||||||
|
DEBUG("conn_can_isotp_recv: CAN_MSG_RX_INDICATION\n");
|
||||||
|
rx = msg.content.ptr;
|
||||||
|
snip = rx->data.iov_base;
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
if (rx->arg != conn) {
|
||||||
|
mbox_put(&conn->master->mbox, &msg);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
if (timeout != 0) {
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
}
|
||||||
|
if (snip->size <= size) {
|
||||||
|
memcpy(buf, snip->data, snip->size);
|
||||||
|
ret = snip->size;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -EOVERFLOW;
|
||||||
|
}
|
||||||
|
isotp_free_rx(rx);
|
||||||
|
return ret;
|
||||||
|
case _TIMEOUT_RX_MSG_TYPE:
|
||||||
|
DEBUG("conn_can_isotp_recv: _TIMEOUT_RX_MSG_TYPE\n");
|
||||||
|
if (msg.content.value == _TIMEOUT_MSG_VALUE) {
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -EINTR;
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
case _CLOSE_CONN_MSG_TYPE:
|
||||||
|
DEBUG("conn_can_isotp_recv: _CLOSE_CONN_MSG_TYPE\n");
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
if ((msg.content.ptr == conn) || (msg.content.ptr == conn->master)) {
|
||||||
|
#endif
|
||||||
|
if (timeout != 0) {
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
}
|
||||||
|
return -ECONNABORTED;
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG("conn_can_isotp_recv: unexpected msg %x\n", msg.type);
|
||||||
|
if (timeout != 0) {
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
}
|
||||||
|
ret = -EINTR;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_isotp_close(conn_can_isotp_t *conn)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
DEBUG("conn_can_isotp_close: conn=%p, ifnum=%d\n",
|
||||||
|
(void *)conn, conn->ifnum);
|
||||||
|
|
||||||
|
if (!conn->bound) {
|
||||||
|
return -EALREADY;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
assert(conn->master != NULL);
|
||||||
|
|
||||||
|
if (conn->master != conn) {
|
||||||
|
mutex_lock(&conn->master->lock);
|
||||||
|
LL_DELETE(conn->master->next, (conn_can_isotp_slave_t *)conn);
|
||||||
|
mutex_unlock(&conn->master->lock);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
if (conn->master->next) {
|
||||||
|
return -EBUSY;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
isotp_release(&conn->isotp);
|
||||||
|
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
if (conn->rx) {
|
||||||
|
isotp_free_rx(conn->rx);
|
||||||
|
}
|
||||||
|
if (conn->master == conn) {
|
||||||
|
while (mbox_try_get(&conn->master->mbox, &msg)) {
|
||||||
|
if (msg.type == CAN_MSG_RX_INDICATION) {
|
||||||
|
DEBUG("conn_can_isotp_close: freeing %p\n", msg.content.ptr);
|
||||||
|
isotp_free_rx(msg.content.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
while (mbox_try_get(&conn->mbox, &msg)) {
|
||||||
|
if (msg.type == CAN_MSG_RX_INDICATION) {
|
||||||
|
DEBUG("conn_can_isotp_close: freeing %p\n", msg.content.ptr);
|
||||||
|
isotp_free_rx(msg.content.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
msg.type = _CLOSE_CONN_MSG_TYPE;
|
||||||
|
msg.content.ptr = conn;
|
||||||
|
put_msg(conn, &msg);
|
||||||
|
|
||||||
|
conn->bound = 0;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef MODULE_CONN_CAN_ISOTP_MULTI
|
||||||
|
int conn_can_isotp_select(conn_can_isotp_slave_t **conn, conn_can_isotp_t *master, uint32_t timeout)
|
||||||
|
{
|
||||||
|
assert(master != NULL);
|
||||||
|
assert(conn != NULL);
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
xtimer_t timer;
|
||||||
|
if (timeout != 0) {
|
||||||
|
timer.callback = _rx_timeout;
|
||||||
|
timer.arg = master;
|
||||||
|
xtimer_set(&timer, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_t msg;
|
||||||
|
can_rx_data_t *rx;
|
||||||
|
|
||||||
|
mbox_get(&master->mbox, &msg);
|
||||||
|
|
||||||
|
if (timeout != 0) {
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
}
|
||||||
|
switch (msg.type) {
|
||||||
|
case CAN_MSG_RX_INDICATION:
|
||||||
|
DEBUG("conn_can_isotp_select: CAN_MSG_RX_INDICATION\n");
|
||||||
|
rx = msg.content.ptr;
|
||||||
|
*conn = rx->arg;
|
||||||
|
(*conn)->rx = rx;
|
||||||
|
ret = 0;
|
||||||
|
break;
|
||||||
|
case _TIMEOUT_RX_MSG_TYPE:
|
||||||
|
DEBUG("conn_can_isotp_select: _TIMEOUT_MSG_VALUE\n");
|
||||||
|
if (msg.content.value == _TIMEOUT_MSG_VALUE) {
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -EINTR;
|
||||||
|
}
|
||||||
|
*conn = NULL;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG("conn_can_isotp_select: %d\n", msg.type);
|
||||||
|
*conn = NULL;
|
||||||
|
ret = -EINTR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
#endif /* MODULE_CONN_CAN_ISOTP_MULTI */
|
||||||
|
|
||||||
|
#else
|
||||||
|
typedef int dont_be_pedantic;
|
||||||
|
#endif /* MODULE_CAN_ISOTP */
|
||||||
279
sys/can/conn/raw.c
Normal file
279
sys/can/conn/raw.c
Normal file
@ -0,0 +1,279 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 OTA keys S.A.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @file
|
||||||
|
* @brief Implementation of raw CAN connection
|
||||||
|
*
|
||||||
|
* @author Vincent Dupont <vincent@otakeys.com>
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <errno.h>
|
||||||
|
#include <string.h>
|
||||||
|
|
||||||
|
#include "can/conn/raw.h"
|
||||||
|
#include "can/can.h"
|
||||||
|
#include "can/raw.h"
|
||||||
|
#include "timex.h"
|
||||||
|
|
||||||
|
#define ENABLE_DEBUG (0)
|
||||||
|
#include "debug.h"
|
||||||
|
|
||||||
|
#include "xtimer.h"
|
||||||
|
|
||||||
|
#define _TIMEOUT_TX_MSG_TYPE (0x8000)
|
||||||
|
#define _TIMEOUT_RX_MSG_TYPE (0x8001)
|
||||||
|
#define _CLOSE_CONN_MSG_TYPE (0x8002)
|
||||||
|
#define _TIMEOUT_MSG_VALUE (0xABCDEFAB)
|
||||||
|
|
||||||
|
#ifndef CONN_CAN_RAW_TIMEOUT_TX_CONF
|
||||||
|
#define CONN_CAN_RAW_TIMEOUT_TX_CONF (1 * US_PER_SEC)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
int conn_can_raw_create(conn_can_raw_t *conn, struct can_filter *filter, size_t count,
|
||||||
|
int ifnum, int flags)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(ifnum < CAN_DLL_NUMOF);
|
||||||
|
|
||||||
|
DEBUG("conn_can_raw_create: create conn=%p, ifnum=%d flags=%d\n", (void *)conn, ifnum, flags);
|
||||||
|
|
||||||
|
mbox_init(&conn->mbox, conn->mbox_queue, CONN_CAN_RAW_MBOX_SIZE);
|
||||||
|
conn->flags = flags;
|
||||||
|
conn->count = 0;
|
||||||
|
conn->ifnum = ifnum;
|
||||||
|
|
||||||
|
if (flags & CONN_CAN_RECVONLY) {
|
||||||
|
can_opt_t opt;
|
||||||
|
opt.opt = CANOPT_STATE;
|
||||||
|
canopt_state_t state = CANOPT_STATE_LISTEN_ONLY;
|
||||||
|
opt.data = &state;
|
||||||
|
opt.data_len = sizeof(state);
|
||||||
|
int ret = raw_can_set_can_opt(ifnum, &opt);
|
||||||
|
if (ret < 0) {
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return conn_can_raw_set_filter(conn, filter, count);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int conn_can_raw_set_filter(conn_can_raw_t *conn, struct can_filter *filter, size_t count)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(filter != NULL || count == 0);
|
||||||
|
|
||||||
|
DEBUG("conn_can_raw_set_filter: conn=%p, filter=%p, count=%d\n",
|
||||||
|
(void *)conn, (void *)filter, count);
|
||||||
|
DEBUG("conn_can_raw_set_filter: conn->filter=%p, conn->count=%d\n",
|
||||||
|
(void *)conn->filter, conn->count);
|
||||||
|
|
||||||
|
/* unset previous filters */
|
||||||
|
if (conn->count) {
|
||||||
|
for (size_t i = 0; i < conn->count; i++) {
|
||||||
|
DEBUG("conn_can_raw_set_filter: unsetting filter=0x%" PRIx32 ", mask=0x%" PRIx32 "\n",
|
||||||
|
conn->filter[i].can_id, conn->filter[i].can_mask);
|
||||||
|
raw_can_unsubscribe_rx_mbox(conn->ifnum, &conn->filter[i], &conn->mbox, conn);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (size_t i = 0; i < count; i++) {
|
||||||
|
DEBUG("conn_can_raw_set_filter: setting filter=0x%" PRIx32 ", mask=0x%" PRIx32 "\n",
|
||||||
|
filter[i].can_id, filter[i].can_mask);
|
||||||
|
int ret = raw_can_subscribe_rx_mbox(conn->ifnum, &filter[i], &conn->mbox, conn);
|
||||||
|
if (ret < 0) {
|
||||||
|
DEBUG("conn_can_raw_set_filter: error setting filters %d\n", ret);
|
||||||
|
for (size_t j = 0; j < i; j++) {
|
||||||
|
DEBUG("conn_can_raw_set_filter: unsetting filter=0x%" PRIx32 ", mask=0x%" PRIx32 "\n",
|
||||||
|
filter[j].can_id, filter[j].can_mask);
|
||||||
|
raw_can_unsubscribe_rx_mbox(conn->ifnum, &filter[j], &conn->mbox, conn);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
conn->filter = filter;
|
||||||
|
conn->count = count;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _tx_conf_timeout(void *arg)
|
||||||
|
{
|
||||||
|
conn_can_raw_t *conn = arg;
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
msg.type = _TIMEOUT_TX_MSG_TYPE;
|
||||||
|
msg.content.value = _TIMEOUT_MSG_VALUE;
|
||||||
|
|
||||||
|
mbox_put(&conn->mbox, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_raw_send(conn_can_raw_t *conn, const struct can_frame *frame, int flags)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(conn->ifnum < CAN_DLL_NUMOF);
|
||||||
|
assert((conn->flags & CONN_CAN_RECVONLY) == 0);
|
||||||
|
assert(frame != NULL);
|
||||||
|
|
||||||
|
int ret = 0;
|
||||||
|
int handle;
|
||||||
|
|
||||||
|
DEBUG("conn_can_raw_send: conn=%p, frame=%p, flags=%d\n",
|
||||||
|
(void *)conn, (void *)frame, flags);
|
||||||
|
|
||||||
|
if (flags & CONN_CAN_DONTWAIT) {
|
||||||
|
handle = ret = raw_can_send(conn->ifnum, frame, 0);
|
||||||
|
if (ret >= 0) {
|
||||||
|
ret = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
xtimer_t timer;
|
||||||
|
timer.callback = _tx_conf_timeout;
|
||||||
|
timer.arg = conn;
|
||||||
|
xtimer_set(&timer, CONN_CAN_RAW_TIMEOUT_TX_CONF);
|
||||||
|
|
||||||
|
handle = raw_can_send_mbox(conn->ifnum, frame, &conn->mbox);
|
||||||
|
if (handle < 0) {
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
return handle;
|
||||||
|
}
|
||||||
|
|
||||||
|
msg_t msg;
|
||||||
|
int timeout = 5;
|
||||||
|
while (1) {
|
||||||
|
mbox_get(&conn->mbox, &msg);
|
||||||
|
switch (msg.type) {
|
||||||
|
case CAN_MSG_TX_ERROR:
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
return -EIO;
|
||||||
|
case CAN_MSG_TX_CONFIRMATION:
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
if ((int)msg.content.value == handle) {
|
||||||
|
DEBUG("conn_can_raw_send: frame sent correctly\n");
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
raw_can_abort(conn->ifnum, handle);
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case _TIMEOUT_TX_MSG_TYPE:
|
||||||
|
DEBUG("conn_can_raw_send: timeout\n");
|
||||||
|
return -ETIMEDOUT;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
DEBUG("conn_can_raw_send: unexpected msg=%x, requeing\n", msg.type);
|
||||||
|
mbox_put(&conn->mbox, &msg);
|
||||||
|
if (!timeout--) {
|
||||||
|
return -EINTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void _rx_timeout(void *arg)
|
||||||
|
{
|
||||||
|
conn_can_raw_t *conn = arg;
|
||||||
|
msg_t msg;
|
||||||
|
|
||||||
|
msg.type = _TIMEOUT_RX_MSG_TYPE;
|
||||||
|
msg.content.value = _TIMEOUT_MSG_VALUE;
|
||||||
|
|
||||||
|
mbox_put(&conn->mbox, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_raw_recv(conn_can_raw_t *conn, struct can_frame *frame, uint32_t timeout)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(conn->ifnum < CAN_DLL_NUMOF);
|
||||||
|
assert(frame != NULL);
|
||||||
|
|
||||||
|
xtimer_t timer;
|
||||||
|
|
||||||
|
if (timeout != 0) {
|
||||||
|
timer.callback = _rx_timeout;
|
||||||
|
timer.arg = conn;
|
||||||
|
xtimer_set(&timer, timeout);
|
||||||
|
}
|
||||||
|
|
||||||
|
int ret;
|
||||||
|
msg_t msg;
|
||||||
|
can_rx_data_t *rx;
|
||||||
|
|
||||||
|
mbox_get(&conn->mbox, &msg);
|
||||||
|
if (timeout != 0) {
|
||||||
|
xtimer_remove(&timer);
|
||||||
|
}
|
||||||
|
switch (msg.type) {
|
||||||
|
case CAN_MSG_RX_INDICATION:
|
||||||
|
DEBUG("conn_can_raw_recv: CAN_MSG_RX_INDICATION\n");
|
||||||
|
rx = msg.content.ptr;
|
||||||
|
memcpy(frame, rx->data.iov_base, rx->data.iov_len);
|
||||||
|
ret = rx->data.iov_len;
|
||||||
|
raw_can_free_frame(rx);
|
||||||
|
break;
|
||||||
|
case _TIMEOUT_RX_MSG_TYPE:
|
||||||
|
if (msg.content.value == _TIMEOUT_MSG_VALUE) {
|
||||||
|
ret = -ETIMEDOUT;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -EINTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case _CLOSE_CONN_MSG_TYPE:
|
||||||
|
if (msg.content.ptr == conn) {
|
||||||
|
ret = -ECONNABORTED;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
ret = -EINTR;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
mbox_put(&conn->mbox, &msg);
|
||||||
|
ret = -EINTR;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
int conn_can_raw_close(conn_can_raw_t *conn)
|
||||||
|
{
|
||||||
|
assert(conn != NULL);
|
||||||
|
assert(conn->ifnum < CAN_DLL_NUMOF);
|
||||||
|
|
||||||
|
DEBUG("conn_can_raw_close: conn=%p\n", (void *)conn);
|
||||||
|
|
||||||
|
if (conn->count) {
|
||||||
|
for (size_t i = 0; i < conn->count; i++) {
|
||||||
|
DEBUG("conn_can_raw_close: unsetting filter=0x%" PRIx32 ", mask=0x%" PRIx32 "\n",
|
||||||
|
conn->filter[i].can_id, conn->filter[i].can_mask);
|
||||||
|
raw_can_unsubscribe_rx_mbox(conn->ifnum, &conn->filter[i], &conn->mbox, conn);
|
||||||
|
}
|
||||||
|
conn->count = 0;
|
||||||
|
msg_t msg;
|
||||||
|
while (mbox_try_get(&conn->mbox, &msg)) {
|
||||||
|
if (msg.type == CAN_MSG_RX_INDICATION) {
|
||||||
|
DEBUG("conn_can_raw_close: incoming msg pending, freeing\n");
|
||||||
|
raw_can_free_frame(msg.content.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
msg.type = _CLOSE_CONN_MSG_TYPE;
|
||||||
|
msg.content.ptr = conn;
|
||||||
|
mbox_try_put(&conn->mbox, &msg);
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
202
sys/include/can/conn/isotp.h
Normal file
202
sys/include/can/conn/isotp.h
Normal file
@ -0,0 +1,202 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 OTA keys S.A.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup conn_can
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Definitions of generic CAN interface
|
||||||
|
*
|
||||||
|
* @author Vincent Dupont <vincent@otakeys.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAN_CONN_ISOTP_H
|
||||||
|
#define CAN_CONN_ISOTP_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "can/can.h"
|
||||||
|
#include "can/isotp.h"
|
||||||
|
#include "mbox.h"
|
||||||
|
|
||||||
|
#if defined(MODULE_CONN_CAN_ISOTP_MULTI) || defined(DOXYGEN)
|
||||||
|
#include "mutex.h"
|
||||||
|
|
||||||
|
#ifndef CONN_CAN_ISOTP_MBOX_SIZE
|
||||||
|
/**
|
||||||
|
* @brief Mailbox size of a conn_can_isotp_t
|
||||||
|
*/
|
||||||
|
#define CONN_CAN_ISOTP_MBOX_SIZE (16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ISO-TP connection
|
||||||
|
*
|
||||||
|
* When conn_can_isotp_multi module is used, this is a 'master' connection
|
||||||
|
* which can be used to send and receive with multiple connections within
|
||||||
|
* a single thread.
|
||||||
|
*
|
||||||
|
* If conn_can_isotp_multi is not used, this is a simple ISO-TP connection
|
||||||
|
*/
|
||||||
|
typedef struct conn_can_isotp_master conn_can_isotp_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ISO-TP salve connection
|
||||||
|
*
|
||||||
|
* This is a slave connection which exists only when conn_can_isotp_multi
|
||||||
|
* module is used.
|
||||||
|
*/
|
||||||
|
typedef struct conn_can_isotp_slave {
|
||||||
|
struct conn_can_isotp_slave *next; /**< Next slave in the list */
|
||||||
|
struct conn_can_isotp_master *master; /**< Master connection holding the mailbox */
|
||||||
|
struct isotp isotp; /**< ISO-TP parameters and status */
|
||||||
|
int ifnum; /**< interface number */
|
||||||
|
int bound; /**< 1 if connection is bound */
|
||||||
|
can_rx_data_t *rx; /**< Buffered rx data */
|
||||||
|
} conn_can_isotp_slave_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ISO-TP master connection
|
||||||
|
*/
|
||||||
|
struct conn_can_isotp_master {
|
||||||
|
/* slave fields */
|
||||||
|
struct conn_can_isotp_slave *next; /**< First slave in the list */
|
||||||
|
struct conn_can_isotp_master *master; /**< Master connection */
|
||||||
|
struct isotp isotp; /**< ISO-TP parameters and status */
|
||||||
|
int ifnum; /**< interface number */
|
||||||
|
int bound; /**< 1 if connection is bound */
|
||||||
|
can_rx_data_t *rx; /**< Buffered rx data */
|
||||||
|
/* slave fields end */
|
||||||
|
mutex_t lock; /**< Master lock */
|
||||||
|
mbox_t mbox; /**< mailbox for the connection list */
|
||||||
|
/** Connection list message queue */
|
||||||
|
msg_t mbox_queue[CONN_CAN_ISOTP_MBOX_SIZE];
|
||||||
|
};
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Initialize a slave connection
|
||||||
|
*
|
||||||
|
* This initializes a slave connection.
|
||||||
|
*
|
||||||
|
* This must be called on slave connections when conn_can_isotp_multi is used.
|
||||||
|
* Does not exist otherwise.
|
||||||
|
*
|
||||||
|
* @param[in] master the master connection
|
||||||
|
* @param[inout] slave the slave connection to initialize
|
||||||
|
*/
|
||||||
|
static inline void conn_can_isotp_init_slave(conn_can_isotp_t *master, conn_can_isotp_slave_t *slave)
|
||||||
|
{
|
||||||
|
slave->next = NULL;
|
||||||
|
slave->master = master;
|
||||||
|
slave->rx = NULL;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
|
||||||
|
#ifndef CONN_CAN_ISOTP_MBOX_SIZE
|
||||||
|
/**
|
||||||
|
* @brief Mailbox size of a conn_can_isotp_t
|
||||||
|
*/
|
||||||
|
#define CONN_CAN_ISOTP_MBOX_SIZE (16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief ISOTP connection
|
||||||
|
*/
|
||||||
|
typedef struct conn_can_isotp {
|
||||||
|
struct isotp isotp; /**< ISO-TP connection */
|
||||||
|
int ifnum; /**< interface number */
|
||||||
|
int bound; /**< 1 if connection is bound */
|
||||||
|
mbox_t mbox; /**< mbox */
|
||||||
|
/** message queue */
|
||||||
|
msg_t mbox_queue[CONN_CAN_ISOTP_MBOX_SIZE];
|
||||||
|
} conn_can_isotp_t;
|
||||||
|
#endif /* MODULE_CONN_CAN_ISOTP_MULTI */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create can isotp connection socket
|
||||||
|
*
|
||||||
|
* @param[inout] conn ISO-TP connection
|
||||||
|
* @param[in] options ISO-TP options
|
||||||
|
* @param[in] ifnum can device Interface
|
||||||
|
*
|
||||||
|
* @return 0 if socket was successfully connected
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_isotp_create(conn_can_isotp_t *conn, struct isotp_options *options, int ifnum);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Bind a can isotp connection
|
||||||
|
*
|
||||||
|
* @param[inout] conn ISO-TP connection
|
||||||
|
*
|
||||||
|
* @return 0 on success
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_isotp_bind(conn_can_isotp_t *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Close can isotp connection socket
|
||||||
|
*
|
||||||
|
* @param[in] conn ISO-TP connection
|
||||||
|
*
|
||||||
|
* @return 0 if conn is closed correctly
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_isotp_close(conn_can_isotp_t *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Receive isotp data
|
||||||
|
*
|
||||||
|
* @param[in] conn ISO-TP connection
|
||||||
|
* @param[out] buf buf to fill in with received data
|
||||||
|
* @param[in] size size of the buffer in bytes
|
||||||
|
* @param[in] timeout timeout in us, 0 for infinite
|
||||||
|
*
|
||||||
|
* @return the number of bytes received
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_isotp_recv(conn_can_isotp_t *conn, void *buf, size_t size, uint32_t timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generic can send
|
||||||
|
*
|
||||||
|
* @param[in] conn ISO-TP connection
|
||||||
|
* @param[in] buf data to send
|
||||||
|
* @param[in] size size of the buffer in bytes
|
||||||
|
* @param[in] flags make function blocked or not
|
||||||
|
* (CAN_ISOTP_TX_DONT_WAIT to ignore tx confirmation)
|
||||||
|
*
|
||||||
|
* @return the number of bytes sent
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_isotp_send(conn_can_isotp_t *conn, const void *buf, size_t size, int flags);
|
||||||
|
|
||||||
|
#if defined(MODULE_CONN_CAN_ISOTP_MULTI) || defined(DOXYGEN)
|
||||||
|
/**
|
||||||
|
* @brief Wait for reception from multiple connections
|
||||||
|
*
|
||||||
|
* @param[out] conn ISO-TP connection which received data
|
||||||
|
* @param[in] master the master connection
|
||||||
|
* @param[in] timeout timeout in us, 0 for infinite wait
|
||||||
|
*
|
||||||
|
* @return 0 if OK, < 0 if error
|
||||||
|
*/
|
||||||
|
int conn_can_isotp_select(conn_can_isotp_slave_t **conn, conn_can_isotp_t *master, uint32_t timeout);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CAN_CONN_ISOTP_H */
|
||||||
|
/** @} */
|
||||||
138
sys/include/can/conn/raw.h
Normal file
138
sys/include/can/conn/raw.h
Normal file
@ -0,0 +1,138 @@
|
|||||||
|
/*
|
||||||
|
* Copyright (C) 2016 OTA keys S.A.
|
||||||
|
*
|
||||||
|
* This file is subject to the terms and conditions of the GNU Lesser
|
||||||
|
* General Public License v2.1. See the file LICENSE in the top level
|
||||||
|
* directory for more details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @ingroup can
|
||||||
|
* @defgroup conn_can Connection
|
||||||
|
* @brief conn interface for CAN stack
|
||||||
|
*
|
||||||
|
* This is the user interface to send and receive raw CAN frames or ISO-TP datagrams
|
||||||
|
*
|
||||||
|
* @{
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @file
|
||||||
|
* @brief Definitions of generic CAN interface
|
||||||
|
*
|
||||||
|
* @author Vincent Dupont <vincent@otakeys.com>
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef CAN_CONN_RAW_H
|
||||||
|
#define CAN_CONN_RAW_H
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
extern "C" {
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#include "can/can.h"
|
||||||
|
#include "can/raw.h"
|
||||||
|
#include "mbox.h"
|
||||||
|
|
||||||
|
#ifndef CONN_CAN_RAW_MBOX_SIZE
|
||||||
|
/**
|
||||||
|
* @brief Mailbox size of a conn_can_raw_t
|
||||||
|
*/
|
||||||
|
#define CONN_CAN_RAW_MBOX_SIZE (16)
|
||||||
|
#endif
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @name flags values
|
||||||
|
* @{
|
||||||
|
*/
|
||||||
|
#define CONN_CAN_DONTWAIT (1) /**< Do not wait for Tx confirmation when sending */
|
||||||
|
#define CONN_CAN_RECVONLY (2) /**< Do not send anything on the bus */
|
||||||
|
/** @} */
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief RAW CAN connection
|
||||||
|
*/
|
||||||
|
typedef struct conn_can_raw {
|
||||||
|
int ifnum; /**< Interface number of the can device */
|
||||||
|
int flags; /**< Config flags for that conn object */
|
||||||
|
size_t count; /**< number of filters set */
|
||||||
|
struct can_filter *filter; /**< list of filter */
|
||||||
|
mbox_t mbox; /**< mbox */
|
||||||
|
/**
|
||||||
|
* message queue
|
||||||
|
*/
|
||||||
|
msg_t mbox_queue[CONN_CAN_RAW_MBOX_SIZE];
|
||||||
|
} conn_can_raw_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Create can connection socket
|
||||||
|
*
|
||||||
|
* @param[inout] conn CAN connection
|
||||||
|
* @param[in] filter list of filters to set
|
||||||
|
* @param[in] count number of filters in @p filter
|
||||||
|
* @param[in] ifnum can device Interface
|
||||||
|
* @param[in] flags conn flags to set (CONN_CAN_RECVONLY)
|
||||||
|
*
|
||||||
|
* @return 0 if socket was successfully connected
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_raw_create(conn_can_raw_t *conn, struct can_filter *filter, size_t count,
|
||||||
|
int ifnum, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Close can connection socket
|
||||||
|
*
|
||||||
|
* @param[in] conn CAN connection
|
||||||
|
*
|
||||||
|
* @return 0 if conn is closed correctly
|
||||||
|
* @return any other negative number in case of an error.
|
||||||
|
*/
|
||||||
|
int conn_can_raw_close(conn_can_raw_t *conn);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generic can receive
|
||||||
|
*
|
||||||
|
* @param[in] conn CAN connection
|
||||||
|
* @param[out] frame CAN frame to receive
|
||||||
|
* @param[in] timeout timeout in us, 0 for infinite
|
||||||
|
*
|
||||||
|
* @return the number of bytes received
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_raw_recv(conn_can_raw_t *conn, struct can_frame *frame, uint32_t timeout);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Generic can send
|
||||||
|
*
|
||||||
|
* @param[in] conn CAN connection
|
||||||
|
* @param[in] frame frame to send
|
||||||
|
* @param[in] flags make function blocked or not
|
||||||
|
* (CONN_CAN_DONTWAIT to ignore tx confirmation)
|
||||||
|
*
|
||||||
|
* @return the number of bytes sent
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_raw_send(conn_can_raw_t *conn, const struct can_frame *frame, int flags);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @brief Set raw CAN filters
|
||||||
|
*
|
||||||
|
* If filters were already set for this connection, it first unsets the previous filters
|
||||||
|
* and sets the new ones.
|
||||||
|
*
|
||||||
|
* @param[in] conn CAN connection
|
||||||
|
* @param[in] filter list of filters to set
|
||||||
|
* @param[in] count number of filters in @p filter
|
||||||
|
*
|
||||||
|
* @return 0 if can filters were successfully set
|
||||||
|
* @return any other negative number in case of an error
|
||||||
|
*/
|
||||||
|
int conn_can_raw_set_filter(conn_can_raw_t *conn, struct can_filter *filter, size_t count);
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef __cplusplus
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif /* CAN_CONN_RAW_H */
|
||||||
|
/** @} */
|
||||||
Loading…
x
Reference in New Issue
Block a user