dect
/
libdect
Archived
13
0
Fork 0
This repository has been archived on 2022-02-17. You can view files and clone it, but cannot push or open issues or pull requests.
libdect/src/ie.c

199 lines
4.1 KiB
C

/*
* DECT Information Elements
*
* Copyright (c) 2009-2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/**
* @defgroup ie Information Elements
* @{
*/
#include <stdint.h>
#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include <asm/byteorder.h>
#include <dect/ie.h>
#include <libdect.h>
#if 0
#define refcnt_debug(fmt, ...) dect_debug(DECT_DEBUG_UNKNOWN, fmt, ## __VA_ARGS__)
#else
#define refcnt_debug(fmt, ...)
#endif
/*
* Information Elements
*/
struct dect_ie_common *dect_ie_alloc(const struct dect_handle *dh, size_t size)
{
struct dect_ie_common *ie;
ie = dect_zalloc(dh, size);
if (ie == NULL)
return NULL;
ie->refcnt = 1;
return ie;
}
EXPORT_SYMBOL(dect_ie_alloc);
void dect_ie_destroy(const struct dect_handle *dh, struct dect_ie_common *ie)
{
dect_free(dh, ie);
}
EXPORT_SYMBOL(dect_ie_destroy);
struct dect_ie_common *__dect_ie_clone(const struct dect_handle *dh,
const struct dect_ie_common *ie,
size_t size)
{
struct dect_ie_common *clone;
clone = dect_ie_alloc(dh, size);
if (clone == NULL)
return NULL;
memcpy(clone + 1, ie + 1, size - sizeof(*ie));
return clone;
}
EXPORT_SYMBOL(__dect_ie_clone);
struct dect_ie_common *__dect_ie_hold(struct dect_ie_common *ie)
{
if (ie == NULL)
return NULL;
refcnt_debug("IE %p: hold refcnt=%u\n", ie, ie->refcnt);
dect_assert(ie->refcnt != 0);
ie->refcnt++;
return ie;
}
EXPORT_SYMBOL(__dect_ie_hold);
void __dect_ie_put(const struct dect_handle *dh, struct dect_ie_common *ie)
{
if (ie == NULL)
return;
refcnt_debug("IE %p: release refcnt=%u\n", ie, ie->refcnt);
dect_assert(ie->refcnt != 0);
if (--ie->refcnt == 0)
dect_ie_destroy(dh, ie);
}
EXPORT_SYMBOL(__dect_ie_put);
/*
* Information Element lists
*/
static struct dect_ie_common ie_list_marker;
void dect_ie_list_init(struct dect_ie_list *ie)
{
ie->common.next = &ie_list_marker;
ie->list = NULL;
}
EXPORT_SYMBOL(dect_ie_list_init);
void __dect_ie_list_add(struct dect_ie_common *ie, struct dect_ie_list *iel)
{
struct dect_ie_common **pprev;
pprev = &iel->list;
while (*pprev != NULL)
pprev = &(*pprev)->next;
ie->next = NULL;
*pprev = ie;
}
EXPORT_SYMBOL(__dect_ie_list_add);
struct dect_ie_list *dect_ie_list_hold(struct dect_ie_list *iel)
{
struct dect_ie_common *ie;
refcnt_debug("IEL %p: hold\n", iel);
dect_foreach_ie(ie, iel)
__dect_ie_hold(ie);
return iel;
}
EXPORT_SYMBOL(dect_ie_list_hold);
void dect_ie_list_put(const struct dect_handle *dh, struct dect_ie_list *iel)
{
struct dect_ie_common *ie;
refcnt_debug("IEL %p: release\n", iel);
dect_foreach_ie(ie, iel)
__dect_ie_put(dh, ie);
}
EXPORT_SYMBOL(dect_ie_list_put);
/*
* Information Element collections
*/
void *dect_ie_collection_alloc(const struct dect_handle *dh, unsigned int size)
{
struct dect_ie_collection *iec;
iec = dect_zalloc(dh, size);
if (iec == NULL)
return NULL;
iec->refcnt = 1;
iec->size = size;
return iec;
}
EXPORT_SYMBOL(dect_ie_collection_alloc);
static void dect_ie_collection_free(const struct dect_handle *dh,
struct dect_ie_collection *iec)
{
struct dect_ie_common *ie;
unsigned int size;
void **ptr;
size = iec->size - sizeof(*iec);
ptr = (void **)&iec->ie;
while (size > 0) {
if (*ptr == &ie_list_marker) {
dect_ie_list_put(dh, *ptr);
size -= sizeof(struct dect_ie_list);
ptr = ((void *)ptr) + sizeof(struct dect_ie_list);
} else {
ie = *ptr;
if (ie != NULL)
__dect_ie_put(dh, ie);
size -= sizeof(struct dect_ie_common *);
ptr++;
}
}
dect_free(dh, iec);
}
EXPORT_SYMBOL(dect_ie_collection_free);
void __dect_ie_collection_put(const struct dect_handle *dh, struct dect_ie_collection *iec)
{
dect_assert(iec->refcnt != 0);
if (--iec->refcnt > 0)
return;
dect_ie_collection_free(dh, iec);
}
EXPORT_SYMBOL(__dect_ie_collection_put);
struct dect_ie_collection *__dect_ie_collection_hold(struct dect_ie_collection *iec)
{
dect_assert(iec->refcnt != 0);
iec->refcnt++;
return iec;
}
EXPORT_SYMBOL(__dect_ie_collection_hold);
/** @} */