1
0
mirror of https://github.com/RIOT-OS/RIOT.git synced 2024-12-29 04:50:03 +01:00
RIOT/sys/can/pkt.c

167 lines
3.2 KiB
C

/*
* 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 sys_can_dll
* @{
* @file
* @brief CAN memory allocation module
*
* @author Vincent Dupont <vincent@otakeys.com>
* @author Toon Stegen <toon.stegen@altran.com>
* @}
*/
#include <string.h>
#include <limits.h>
#include <errno.h>
#include "net/gnrc/pktbuf.h"
#include "can/pkt.h"
#include "mutex.h"
#define ENABLE_DEBUG (0)
#include "debug.h"
#define HANDLE_UNUSED 0
static int handle;
static mutex_t _mutex = MUTEX_INIT;
void can_pkt_init(void)
{
mutex_lock(&_mutex);
handle = 1;
mutex_unlock(&_mutex);
}
static can_pkt_t *_pkt_alloc(int ifnum, const struct can_frame *frame)
{
can_pkt_t *pkt;
gnrc_pktsnip_t *snip = gnrc_pktbuf_add(NULL, NULL, sizeof(*pkt), GNRC_NETTYPE_UNDEF);
if (!snip) {
DEBUG("can_pkt_alloc: out of memory\n");
return NULL;
}
pkt = snip->data;
pkt->entry.ifnum = ifnum;
pkt->frame = *frame;
pkt->snip = snip;
DEBUG("can_pkt_alloc: pkt allocated\n");
return pkt;
}
static void _init_pkt(can_pkt_t *pkt, int tx)
{
if (tx) {
mutex_lock(&_mutex);
pkt->handle = handle++;
if (handle == INT_MAX) {
handle = 1;
}
pkt->entry.next = NULL;
mutex_unlock(&_mutex);
}
else {
pkt->handle = 0;
atomic_store(&pkt->ref_count, 0);
}
}
can_pkt_t *can_pkt_alloc_tx(int ifnum, const struct can_frame *frame, kernel_pid_t tx_pid)
{
can_pkt_t *pkt = _pkt_alloc(ifnum, frame);
if (!pkt) {
return NULL;
}
_init_pkt(pkt, 1);
pkt->entry.target.pid = tx_pid;
#ifdef MODULE_CAN_MBOX
pkt->entry.type = CAN_TYPE_DEFAULT;
#endif
return pkt;
}
can_pkt_t *can_pkt_alloc_rx(int ifnum, const struct can_frame *frame)
{
can_pkt_t *pkt = _pkt_alloc(ifnum, frame);
if (!pkt) {
return NULL;
}
_init_pkt(pkt, 0);
return pkt;
}
#ifdef MODULE_CAN_MBOX
can_pkt_t *can_pkt_alloc_mbox_tx(int ifnum, const struct can_frame *frame, mbox_t *tx_mbox)
{
can_pkt_t *pkt = _pkt_alloc(ifnum, frame);
if (!pkt) {
return NULL;
}
_init_pkt(pkt, 1);
pkt->entry.target.mbox = tx_mbox;
pkt->entry.type = CAN_TYPE_MBOX;
return pkt;
}
#endif
void can_pkt_free(can_pkt_t *pkt)
{
if (!pkt) {
return;
}
DEBUG("can_pkt_free: free pkt=%p\n", (void*)pkt);
gnrc_pktbuf_release(pkt->snip);
}
can_rx_data_t *can_pkt_alloc_rx_data(void *data, size_t len, void *arg)
{
can_rx_data_t *rx;
gnrc_pktsnip_t *snip = gnrc_pktbuf_add(NULL, NULL, sizeof(*rx), GNRC_NETTYPE_UNDEF);
if (!snip) {
DEBUG("can_pkt_alloc_rx_data: out of memory\n");
return NULL;
}
rx = snip->data;
DEBUG("can_pkt_alloc_rx_data: rx=%p\n", (void *)rx);
rx->data.iov_base = data;
rx->data.iov_len = len;
rx->arg = arg;
rx->snip = snip;
return rx;
}
void can_pkt_free_rx_data(can_rx_data_t *data)
{
if (!data) {
return;
}
gnrc_pktbuf_release(data->snip);
}