dect
/
libnl
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.
libnl/lib/dect/transceiver_obj.c

336 lines
8.5 KiB
C

/*
* lib/dect/transceiver_obj.c DECT Transceiver objects
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation version 2.1
* of the License.
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#include <netlink-private/netlink.h>
#include <netlink/netlink.h>
#include <netlink/cache.h>
#include <netlink/utils.h>
#include <netlink/data.h>
#include <netlink/dect/dect.h>
#include <netlink/dect/cell.h>
#include <netlink/dect/transceiver.h>
/** @cond SKIP */
#define TRANSCEIVER_ATTR_NAME 0x0001
#define TRANSCEIVER_ATTR_TYPE 0x0002
#define TRANSCEIVER_ATTR_FEATURES 0x0004
#define TRANSCEIVER_ATTR_INDEX 0x0008
#define TRANSCEIVER_ATTR_LINK 0x0010
#define TRANSCEIVER_ATTR_BAND 0x0020
/** @endtsond */
static void transceiver_free_data(struct nl_object *obj)
{
struct nl_dect_transceiver *trx = nl_object_priv(obj);
if (trx == NULL)
return;
free(trx->trx_name);
free(trx->trx_type);
}
static void slot_dump(struct nl_dect_transceiver_slot *dts, unsigned int n,
struct nl_dump_params *p)
{
int64_t offset;
char buf[64];
nl_dect_slot_state2str(dts->dts_state, buf, sizeof(buf));
nl_dump(p, "\tslot %u: <%s", n, buf);
if (dts->dts_flags) {
nl_dect_slot_flags2str(dts->dts_flags, buf, sizeof(buf));
nl_dump(p, ",%s", buf);
}
nl_dump(p, "> ");
if (dts->dts_state != DECT_SLOT_IDLE) {
nl_dump(p, "packet: %s ",
nl_dect_slot_packet2str(dts->dts_packet, buf,
sizeof(buf)));
nl_dump(p, "carrier: %u (%u.%03u MHz", dts->dts_carrier,
dts->dts_frequency / 1000, dts->dts_frequency % 1000);
if (dts->dts_state == DECT_SLOT_RX) {
offset = (int64_t)dts->dts_frequency *
dts->dts_phaseoff /
DECT_PHASE_OFFSET_SCALE;
nl_dump(p, " %+" PRId64 ".%03" PRIu64 " kHz",
offset / 1000000,
llabs(offset) % 1000000 / 1000);
}
nl_dump(p, ")");
}
if (dts->dts_state == DECT_SLOT_RX)
nl_dump(p, " signal level: %.2fdBm",
nl_dect_rssi_to_dbm(dts->dts_rssi));
nl_dump(p, "\n");
nl_dump(p, "\t RX: bytes %u packets %u a-crc-errors %u "
"x-crc-errors %u z-crc-errors %u\n",
dts->dts_rx_bytes, dts->dts_rx_packets,
dts->dts_rx_a_crc_errors,
dts->dts_rx_x_crc_errors,
dts->dts_rx_z_crc_errors);
nl_dump(p, "\t TX: bytes %u packets %u\n",
dts->dts_tx_bytes, dts->dts_tx_packets);
}
static void transceiver_dump(struct nl_object *obj, struct nl_dump_params *p)
{
struct nl_dect_transceiver *trx = nl_object_priv(obj);
struct nl_dect_transceiver_stats *stats = &trx->trx_stats;
struct nl_dect_transceiver_slot *dts;
struct nl_cache *cell_cache;
char buf[64];
unsigned int n;
nl_dump(p, "DECT Transceiver ");
if (trx->trx_name != NULL)
nl_dump_line(p, "%s", trx->trx_name);
if (trx->trx_link) {
cell_cache = nl_cache_mngt_require("nl_dect/cell");
if (cell_cache != NULL) {
nl_dump(p, "@%s",
nl_dect_cell_i2name(cell_cache, trx->trx_link,
buf, sizeof(buf)));
} else
nl_dump(p, "@%d", trx->trx_link);
}
nl_dump(p, ":\n");
if (trx->trx_type != NULL)
nl_dump_line(p, "\tType: %s\n", trx->trx_type);
if (trx->trx_features != 0)
nl_dump_line(p, "\tFeatures: %s\n",
nl_dect_transceiver_features2str(trx->trx_features,
buf, sizeof(buf)));
nl_dump(p, "\tRF-band: %.5u\n", trx->trx_band);
nl_dump(p, "\tEvents: busy: %u late: %u\n",
stats->trx_event_busy, stats->trx_event_late);
nl_dump(p, "\n");
for (n = 0; n < 24; n++) {
dts = &trx->trx_slots[n];
if (!dts->dts_valid)
continue;
slot_dump(dts, n, p);
}
}
static int nl_dect_transceiver_compare(struct nl_object *_a, struct nl_object *_b,
uint32_t attrs, int flags)
{
struct nl_dect_transceiver *a = (struct nl_dect_transceiver *)_a;
struct nl_dect_transceiver *b = (struct nl_dect_transceiver *)_b;
int diff = 0;
#define TRX_DIFF(ATTR, EXPR) ATTR_DIFF(attrs, TRANSCEIVER_ATTR_##ATTR, a, b, EXPR)
diff |= TRX_DIFF(NAME, strcmp(a->trx_name, b->trx_name));
diff |= TRX_DIFF(LINK, a->trx_link != b->trx_link);
#undef TRX_DIFF
return diff;
}
/**
* @name Allocation/Freeing
* @{
*/
struct nl_dect_transceiver *nl_dect_transceiver_alloc(void)
{
return (struct nl_dect_transceiver *)nl_object_alloc(&nl_dect_transceiver_obj_ops);
}
void nl_dect_transceiver_get(struct nl_dect_transceiver *trx)
{
nl_object_get((struct nl_object *)trx);
}
void nl_dect_transceiver_put(struct nl_dect_transceiver *trx)
{
nl_object_put((struct nl_object *)trx);
}
/** @} */
/**
* @name Attributes
* @{
*/
void nl_dect_transceiver_set_name(struct nl_dect_transceiver *trx, const char *name)
{
trx->trx_name = strdup(name);
trx->ce_mask |= TRANSCEIVER_ATTR_NAME;
}
bool nl_dect_transceiver_test_name(const struct nl_dect_transceiver *trx)
{
return !!(trx->ce_mask & TRANSCEIVER_ATTR_NAME);
}
const char *nl_dect_transceiver_get_name(const struct nl_dect_transceiver *trx)
{
return trx->trx_name;
}
void nl_dect_transceiver_set_type(struct nl_dect_transceiver *trx, const char *type)
{
trx->trx_type = strdup(type);
trx->ce_mask |= TRANSCEIVER_ATTR_TYPE;
}
bool nl_dect_transceiver_test_type(const struct nl_dect_transceiver *trx)
{
return !!(trx->ce_mask & TRANSCEIVER_ATTR_TYPE);
}
const char *nl_dect_transceiver_get_type(const struct nl_dect_transceiver *trx)
{
return trx->trx_type;
}
void nl_dect_transceiver_set_features(struct nl_dect_transceiver *trx, uint32_t features)
{
trx->trx_features = features;
trx->ce_mask |= TRANSCEIVER_ATTR_FEATURES;
}
void nl_dect_transceiver_set_index(struct nl_dect_transceiver *trx, int index)
{
trx->trx_index = index;
trx->ce_mask |= TRANSCEIVER_ATTR_INDEX;
}
void nl_dect_transceiver_set_link(struct nl_dect_transceiver *trx, uint8_t link)
{
trx->trx_link = link;
trx->ce_mask |= TRANSCEIVER_ATTR_LINK;
}
void nl_dect_transceiver_set_band(struct nl_dect_transceiver *trx, uint8_t band)
{
trx->trx_band = band;
trx->ce_mask |= TRANSCEIVER_ATTR_BAND;
}
bool nl_dect_transceiver_test_band(const struct nl_dect_transceiver *trx)
{
return !!(trx->ce_mask & TRANSCEIVER_ATTR_BAND);
}
uint8_t nl_dect_transceiver_get_band(const struct nl_dect_transceiver *trx)
{
return trx->trx_band;
}
static struct trans_tbl trx_features[] = {
__ADD(DECT_TRANSCEIVER_SLOW_HOPPING, slow-hopping)
__ADD(DECT_TRANSCEIVER_PACKET_P64, p64)
};
const char *nl_dect_transceiver_features2str(uint32_t features, char *buf, size_t len)
{
return __flags2str(features, buf, len, trx_features,
ARRAY_SIZE(trx_features));
}
static struct trans_tbl slot_states[] = {
__ADD(DECT_SLOT_IDLE, idle)
__ADD(DECT_SLOT_SCANNING, scanning)
__ADD(DECT_SLOT_RX, rx)
__ADD(DECT_SLOT_TX, tx)
};
const char *nl_dect_slot_state2str(uint8_t state, char *buf, size_t len)
{
return __type2str(state, buf, len, slot_states,
ARRAY_SIZE(slot_states));
}
uint8_t nl_dect_slot_str2state(const char *str)
{
return __str2type(str, slot_states, ARRAY_SIZE(slot_states));
}
static struct trans_tbl slot_flags[] = {
__ADD(DECT_SLOT_SYNC, sync)
__ADD(DECT_SLOT_CIPHER, cipher)
};
const char *nl_dect_slot_flags2str(uint32_t state, char *buf, size_t len)
{
return __flags2str(state, buf, len, slot_flags, ARRAY_SIZE(slot_flags));
}
uint32_t nl_dect_slot_str2flags(const char *str)
{
return __str2flags(str, slot_flags, ARRAY_SIZE(slot_flags));
}
static struct trans_tbl packet_types[] = {
__ADD(DECT_PACKET_P00, P00)
__ADD(DECT_PACKET_P08, P08)
__ADD(DECT_PACKET_P32, P32)
__ADD(DECT_PACKET_P80, P80)
__ADD(DECT_PACKET_P640j, P640j)
__ADD(DECT_PACKET_P640j, P672j)
};
const char *nl_dect_slot_packet2str(uint8_t pkt, char *buf, size_t len)
{
return __type2str(pkt, buf, len, packet_types, ARRAY_SIZE(packet_types));
}
uint8_t nl_dect_slot_str2packet(const char *str)
{
return __str2type(str, packet_types, ARRAY_SIZE(packet_types));
}
int nl_dect_transceiver_build_msg(struct nl_msg *msg, struct nl_dect_transceiver *trx)
{
struct dectmsg dm = {
.dm_index = trx->trx_index,
};
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
goto nla_put_failure;
if (trx->ce_mask & TRANSCEIVER_ATTR_NAME)
NLA_PUT_STRING(msg, DECTA_TRANSCEIVER_NAME, trx->trx_name);
if (trx->ce_mask & TRANSCEIVER_ATTR_LINK)
NLA_PUT_U8(msg, DECTA_TRANSCEIVER_LINK, trx->trx_link);
return 0;
nla_put_failure:
return -NLE_MSGSIZE;
}
/** @cond SKIP */
struct nl_object_ops nl_dect_transceiver_obj_ops = {
.oo_name = "nl_dect/transceiver",
.oo_size = sizeof(struct nl_dect_transceiver),
.oo_free_data = transceiver_free_data,
.oo_dump = {
[NL_DUMP_LINE] = transceiver_dump,
},
.oo_compare = nl_dect_transceiver_compare,
.oo_id_attrs = TRANSCEIVER_ATTR_NAME,
};
/** @endcond */
/** @} */