libnl: import DECT support
Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
parent
b24d4fa5db
commit
be93d3d46c
|
@ -31,6 +31,7 @@ install:
|
|||
mkdir -p $(DESTDIR)$(includedir)/netlink/genl/
|
||||
mkdir -p $(DESTDIR)$(includedir)/netlink/fib_lookup/
|
||||
mkdir -p $(DESTDIR)$(includedir)/netlink/netfilter
|
||||
mkdir -p $(DESTDIR)$(includedir)/netlink/dect
|
||||
install -m 0644 netlink/*.h $(DESTDIR)$(includedir)/netlink/
|
||||
install -m 0644 netlink/route/*.h $(DESTDIR)$(includedir)/netlink/route/
|
||||
install -m 0644 netlink/route/sch/*.h $(DESTDIR)$(includedir)/netlink/route/sch/
|
||||
|
@ -39,4 +40,4 @@ install:
|
|||
install -m 0644 netlink/genl/*.h $(DESTDIR)$(includedir)/netlink/genl/
|
||||
install -m 0644 netlink/fib_lookup/*.h $(DESTDIR)$(includedir)/netlink/fib_lookup/
|
||||
install -m 0644 netlink/netfilter/*.h $(DESTDIR)$(includedir)/netlink/netfilter/
|
||||
|
||||
install -m 0644 netlink/dect/*.h $(DESTDIR)$(includedir)/netlink/dect
|
||||
|
|
|
@ -0,0 +1,255 @@
|
|||
#ifndef _LINUX_DECT_NETLINK_H
|
||||
#define _LINUX_DECT_NETLINK_H
|
||||
|
||||
struct dectmsg {
|
||||
int dm_index;
|
||||
};
|
||||
|
||||
enum dect_nlgroups {
|
||||
DECTNLGRP_NONE,
|
||||
DECTNLGRP_TRANSCEIVER,
|
||||
DECTNLGRP_CELL,
|
||||
DECTNLGRP_CLUSTER,
|
||||
DECTNLGRP_LLME,
|
||||
__DECTNLGRP_MAX
|
||||
};
|
||||
#define DECTNLGRP_MAX (__DECTNLGRP_MAX - 1)
|
||||
|
||||
enum dect_netlink_msg_types {
|
||||
DECT_MSG_BASE = 0x10,
|
||||
DECT_NEW_TRANSCEIVER,
|
||||
DECT_DEL_TRANSCEIVER,
|
||||
DECT_GET_TRANSCEIVER,
|
||||
DECT_NEW_CELL,
|
||||
DECT_DEL_CELL,
|
||||
DECT_GET_CELL,
|
||||
DECT_NEW_CLUSTER,
|
||||
DECT_DEL_CLUSTER,
|
||||
DECT_GET_CLUSTER,
|
||||
DECT_LLME_MSG,
|
||||
__DECT_MSG_MAX
|
||||
};
|
||||
#define DECT_MSG_MAX (__DECT_MSG_MAX - 1)
|
||||
|
||||
#define DECT_NR_MSGTYPES (DECT_MSG_MAX + 1 - DECT_MSG_BASE)
|
||||
|
||||
enum dect_list_attrs {
|
||||
DECTA_LIST_UNSPEC,
|
||||
DECTA_LIST_ELEM,
|
||||
__DECTA_LIST_MAX
|
||||
};
|
||||
#define DECTA_LIST_MAX (__DECTA_LIST_MAX - 1)
|
||||
|
||||
enum dect_slot_states {
|
||||
DECT_SLOT_IDLE,
|
||||
DECT_SLOT_SCANNING,
|
||||
DECT_SLOT_RX,
|
||||
DECT_SLOT_TX,
|
||||
};
|
||||
|
||||
enum dect_slot_attrs {
|
||||
DECTA_SLOT_UNSPEC,
|
||||
DECTA_SLOT_NUM,
|
||||
DECTA_SLOT_STATE,
|
||||
DECTA_SLOT_CARRIER,
|
||||
DECTA_SLOT_FREQUENCY,
|
||||
DECTA_SLOT_RSSI,
|
||||
DECTA_SLOT_RX_PACKETS,
|
||||
DECTA_SLOT_RX_BYTES,
|
||||
DECTA_SLOT_TX_PACKETS,
|
||||
DECTA_SLOT_TX_BYTES,
|
||||
__DECTA_SLOT_MAX
|
||||
};
|
||||
#define DECTA_SLOT_MAX (__DECTA_SLOT_MAX - 1)
|
||||
|
||||
enum dect_transceiver_stats_attrs {
|
||||
DECTA_TRANSCEIVER_STATS_UNSPEC,
|
||||
DECTA_TRANSCEIVER_STATS_EVENT_BUSY,
|
||||
DECTA_TRANSCEIVER_STATS_EVENT_LATE,
|
||||
__DECTA_TRANSCEIVER_STATS_MAX
|
||||
};
|
||||
#define DECTA_TRANSCEIVER_STATS_MAX (__DECTA_TRANSCEIVER_STATS_MAX - 1)
|
||||
|
||||
enum dect_transceiver_attrs {
|
||||
DECTA_TRANSCEIVER_UNSPEC,
|
||||
DECTA_TRANSCEIVER_NAME,
|
||||
DECTA_TRANSCEIVER_TYPE,
|
||||
DECTA_TRANSCEIVER_LINK,
|
||||
DECTA_TRANSCEIVER_STATS,
|
||||
DECTA_TRANSCEIVER_BAND,
|
||||
DECTA_TRANSCEIVER_SLOTS,
|
||||
__DECTA_TRANSCEIVER_MAX
|
||||
};
|
||||
#define DECTA_TRANSCEIVER_MAX (__DECTA_TRANSCEIVER_MAX - 1)
|
||||
|
||||
enum dect_cell_flags {
|
||||
DECT_CELL_CCP = (1 << 0),
|
||||
};
|
||||
|
||||
enum dect_cell_attrs {
|
||||
DECTA_CELL_UNSPEC,
|
||||
DECTA_CELL_NAME,
|
||||
DECTA_CELL_FLAGS,
|
||||
DECTA_CELL_TRANSCEIVERS,
|
||||
DECTA_CELL_CLUSTER,
|
||||
__DECTA_CELL_MAX
|
||||
};
|
||||
#define DECTA_CELL_MAX (__DECTA_CELL_MAX - 1)
|
||||
|
||||
enum dect_cluster_attrs {
|
||||
DECTA_CLUSTER_UNSPEC,
|
||||
DECTA_CLUSTER_NAME,
|
||||
DECTA_CLUSTER_MODE,
|
||||
DECTA_CLUSTER_PARI,
|
||||
DECTA_CLUSTER_CELLS,
|
||||
__DECTA_CLUSTER_MAX
|
||||
};
|
||||
#define DECTA_CLUSTER_MAX (__DECTA_CLUSTER_MAX - 1)
|
||||
|
||||
enum dect_cluster_modes {
|
||||
DECT_MODE_FP,
|
||||
DECT_MODE_PP,
|
||||
DECT_MODE_MONITOR,
|
||||
};
|
||||
|
||||
/**
|
||||
* DECT ARI classes
|
||||
*
|
||||
* @DECT_ARC_A: Residential and private (PBX) single- and small multiple cell systems
|
||||
* @DECT_ARC_B: Private (PABXs) multiple cell
|
||||
* @DECT_ARC_C: Public single and multiple cell systems
|
||||
* @DECT_ARC_D: Public DECT access to a GSM network
|
||||
* @DECT_ARC_E: PP to PP direct communication (private)
|
||||
*/
|
||||
enum dect_ari_classes {
|
||||
DECT_ARC_A,
|
||||
DECT_ARC_B,
|
||||
DECT_ARC_C,
|
||||
DECT_ARC_D,
|
||||
DECT_ARC_E,
|
||||
};
|
||||
|
||||
enum dect_ari_attrs {
|
||||
DECTA_ARI_UNSPEC,
|
||||
DECTA_ARI_CLASS,
|
||||
DECTA_ARI_FPN,
|
||||
DECTA_ARI_FPS,
|
||||
DECTA_ARI_EMC,
|
||||
DECTA_ARI_EIC,
|
||||
DECTA_ARI_POC,
|
||||
DECTA_ARI_GOP,
|
||||
DECTA_ARI_FIL,
|
||||
__DECTA_ARI_MAX
|
||||
};
|
||||
#define DECTA_ARI_MAX (__DECTA_ARI_MAX - 1)
|
||||
|
||||
enum decta_sari_attrs {
|
||||
DECTA_SARI_UNSPEC,
|
||||
DECTA_SARI_ARI,
|
||||
DECTA_SARI_BLACK,
|
||||
DECTA_SARI_TARI,
|
||||
__DECTA_SARI_MAX
|
||||
};
|
||||
#define DECTA_SARI_MAX (__DECTA_SARI_MAX - 1)
|
||||
|
||||
enum dect_fixed_part_capabilities {
|
||||
DECT_FPC_EXTENDED_FP_INFO = 0x80000,
|
||||
DECT_FPC_DOUBLE_DUPLEX_BEARER_CONNECTION= 0x40000,
|
||||
DECT_FPC_RESERVED = 0x20000,
|
||||
DECT_FPC_DOUBLE_SLOT = 0x10000,
|
||||
DECT_FPC_HALF_SLOT = 0x8000,
|
||||
DECT_FPC_FULL_SLOT = 0x4000,
|
||||
DECT_FPC_FREQ_CONTROL = 0x2000,
|
||||
DECT_FPC_PAGE_REPETITION = 0x1000,
|
||||
DECT_FPC_CO_SETUP_ON_DUMMY = 0x800,
|
||||
DECT_FPC_CL_UPLINK = 0x400,
|
||||
DECT_FPC_CL_DOWNLINK = 0x200,
|
||||
DECT_FPC_BASIC_A_FIELD_SETUP = 0x100,
|
||||
DECT_FPC_ADV_A_FIELD_SETUP = 0x80,
|
||||
DECT_FPC_B_FIELD_SETUP = 0x40,
|
||||
DECT_FPC_CF_MESSAGES = 0x20,
|
||||
DECT_FPC_IN_MIN_DELAY = 0x10,
|
||||
DECT_FPC_IN_NORM_DELAY = 0x8,
|
||||
DECT_FPC_IP_ERROR_DETECTION = 0x4,
|
||||
DECT_FPC_IP_ERROR_CORRECTION = 0x2,
|
||||
DECT_FPC_MULTIBEARER_CONNECTIONS = 0x1,
|
||||
};
|
||||
|
||||
enum dect_higher_layer_capabilities {
|
||||
DECT_HLC_ADPCM_G721_VOICE = 0x8000,
|
||||
DECT_HLC_GAP_PAP_BASIC_SPEECH = 0x4000,
|
||||
DECT_HLC_NON_VOICE_CIRCUIT_SWITCHED = 0x2000,
|
||||
DECT_HLC_NON_VOICE_PACKET_SWITCHED = 0x1000,
|
||||
DECT_HLC_STANDARD_AUTHENTICATION = 0x800,
|
||||
DECT_HLC_STANDARD_CIPHERING = 0x400,
|
||||
DECT_HLC_LOCATION_REGISTRATION = 0x200,
|
||||
DECT_HLC_SIM_SERVICES = 0x100,
|
||||
DECT_HLC_NON_STATIC_FIXED_PART = 0x80,
|
||||
DECT_HLC_CISS_SERVICE = 0x40,
|
||||
DECT_HLC_CLMS_SERVICE = 0x20,
|
||||
DECT_HLC_COMS_SERVICE = 0x10,
|
||||
DECT_HLC_ACCESS_RIGHT_REQUESTS = 0x8,
|
||||
DECT_HLC_EXTERNAL_HANDOVER = 0x4,
|
||||
DECT_HLC_CONNECTION_HANDOVER = 0x2,
|
||||
DECT_HLC_RESERVED = 0x1,
|
||||
};
|
||||
|
||||
enum dect_extended_higher_layer_capabilities {
|
||||
DECT_EHLC_ISDN_DATA_SERVICE = 0x1,
|
||||
DECT_EHLC_DATA_SERVICE_PROFILE_A_B = 0x2,
|
||||
DECT_EHLC_DATA_SERVICE_PROFILE_C = 0x4,
|
||||
DECT_EHLC_DATA_SERVICE_PROFILE_D = 0x8,
|
||||
DECT_EHLC_DATA_SERVICE_PROFILE_E = 0x10,
|
||||
DECT_EHLC_DATA_SERVICE_PROFILE_F = 0x20,
|
||||
DECT_EHLC_ASYMETRIC_BEARERS = 0x40,
|
||||
DECT_EHLC_TPUI_LOCATION_REGISTRATION = 0x100,
|
||||
};
|
||||
|
||||
enum dect_efpc_attrs {
|
||||
DECTA_EFPC_UNSPEC,
|
||||
DECTA_EFPC_CRFP_HOPS,
|
||||
DECTA_EFPC_CRFP_ENCRYPTION,
|
||||
DECTA_EFPC_REP_HOPS,
|
||||
DECTA_EFPC_REP_INTERLACING,
|
||||
DECTA_EFPC_EHLC,
|
||||
__DECTA_EFPC_MAX
|
||||
};
|
||||
#define DECTA_EFPC_MAX (__DECTA_EFPC_MAX - 1)
|
||||
|
||||
enum dect_mac_info_attrs {
|
||||
DECTA_MAC_INFO_UNSPEC,
|
||||
DECTA_MAC_INFO_PARI,
|
||||
DECTA_MAC_INFO_RPN,
|
||||
DECTA_MAC_INFO_RSSI,
|
||||
DECTA_MAC_INFO_SARI_LIST,
|
||||
DECTA_MAC_INFO_FPC,
|
||||
DECTA_MAC_INFO_HLC,
|
||||
DECTA_MAC_INFO_EFPC,
|
||||
__DECTA_MAC_INFO_MAX
|
||||
};
|
||||
#define DECTA_MAC_INFO_MAX (__DECTA_MAC_INFO_MAX - 1)
|
||||
|
||||
enum dect_llme_ops {
|
||||
DECT_LLME_REQUEST,
|
||||
DECT_LLME_INDICATE,
|
||||
DECT_LLME_RESPONSE,
|
||||
DECT_LLME_CONFIRM,
|
||||
};
|
||||
|
||||
enum dect_llme_msg_types {
|
||||
DECT_LLME_SCAN,
|
||||
DECT_LLME_MAC_INFO,
|
||||
__DECT_LLME_MAX
|
||||
};
|
||||
#define DECT_LLME_MAX (__DECT_LLME_MAX - 1)
|
||||
|
||||
enum dect_llme_msg_attrs {
|
||||
DECTA_LLME_UNSPEC,
|
||||
DECTA_LLME_OP,
|
||||
DECTA_LLME_TYPE,
|
||||
DECTA_LLME_DATA,
|
||||
__DECTA_LLME_MAX
|
||||
};
|
||||
#define DECTA_LLME_MAX (__DECTA_LLME_MAX - 1)
|
||||
|
||||
#endif /* _LINUX_DECT_NETLINK_H */
|
|
@ -24,6 +24,7 @@
|
|||
/* leave room for NETLINK_DM (DM Events) */
|
||||
#define NETLINK_SCSITRANSPORT 18 /* SCSI Transports */
|
||||
#define NETLINK_ECRYPTFS 19
|
||||
#define NETLINK_DECT 20 /* DECT */
|
||||
|
||||
#define MAX_LINKS 32
|
||||
|
||||
|
|
|
@ -799,4 +799,102 @@ struct nfnl_queue_msg {
|
|||
uint32_t queue_msg_verdict;
|
||||
};
|
||||
|
||||
struct nl_dect_transceiver_slot {
|
||||
uint8_t dts_valid;
|
||||
uint8_t dts_state;
|
||||
uint8_t dts_carrier;
|
||||
uint8_t dts_rssi;
|
||||
uint32_t dts_frequency;
|
||||
uint32_t dts_rx_bytes;
|
||||
uint32_t dts_rx_packets;
|
||||
uint32_t dts_tx_bytes;
|
||||
uint32_t dts_tx_packets;
|
||||
};
|
||||
|
||||
struct nl_dect_transceiver_stats {
|
||||
uint32_t trx_event_busy;
|
||||
uint32_t trx_event_late;
|
||||
};
|
||||
|
||||
struct nl_dect_transceiver {
|
||||
NLHDR_COMMON
|
||||
|
||||
char *trx_name;
|
||||
char *trx_type;
|
||||
uint8_t trx_index;
|
||||
uint8_t trx_link;
|
||||
uint8_t trx_band;
|
||||
struct nl_dect_transceiver_stats trx_stats;
|
||||
struct nl_dect_transceiver_slot trx_slots[24];
|
||||
};
|
||||
|
||||
struct nl_dect_ari {
|
||||
uint32_t ari_flags;
|
||||
|
||||
uint8_t ari_class;
|
||||
uint32_t ari_fpn;
|
||||
uint32_t ari_fps;
|
||||
union {
|
||||
uint16_t emc;
|
||||
uint16_t eic;
|
||||
uint16_t poc;
|
||||
uint32_t gop;
|
||||
uint16_t fil;
|
||||
} ari_u;
|
||||
};
|
||||
|
||||
struct nl_dect_cluster {
|
||||
NLHDR_COMMON
|
||||
|
||||
int cl_index;
|
||||
char *cl_name;
|
||||
uint8_t cl_mode;
|
||||
struct nl_dect_ari cl_pari;
|
||||
uint8_t cells[8];
|
||||
};
|
||||
|
||||
struct nl_dect_cell {
|
||||
NLHDR_COMMON
|
||||
|
||||
int c_index;
|
||||
char * c_name;
|
||||
uint32_t c_flags;
|
||||
char *c_transceiver[16];
|
||||
int c_link;
|
||||
};
|
||||
|
||||
struct nl_dect_llme_mac_info {
|
||||
NLHDR_COMMON
|
||||
|
||||
struct nl_dect_ari mi_pari;
|
||||
uint8_t mi_rpn;
|
||||
uint8_t mi_rssi;
|
||||
uint32_t mi_fpc;
|
||||
uint16_t mi_hlc;
|
||||
uint16_t mi_ehlc;
|
||||
};
|
||||
|
||||
struct nl_dect_llme_mac_con {
|
||||
NLHDR_COMMON
|
||||
|
||||
uint32_t mc_mcei;
|
||||
struct nl_dect_ari mc_ari;
|
||||
uint32_t mc_pmid;
|
||||
uint8_t mc_type;
|
||||
uint8_t mc_ecn;
|
||||
uint8_t mc_service;
|
||||
};
|
||||
|
||||
struct nl_dect_llme_msg {
|
||||
NLHDR_COMMON
|
||||
|
||||
int lm_index;
|
||||
uint8_t lm_type;
|
||||
uint8_t lm_op;
|
||||
union {
|
||||
struct nl_dect_llme_mac_info lm_mi;
|
||||
struct nl_dect_llme_mac_con lm_mc;
|
||||
};
|
||||
};
|
||||
|
||||
#endif
|
||||
|
|
|
@ -0,0 +1,35 @@
|
|||
#ifndef NETLINK_DECT_ARI_H
|
||||
#define NETLINK_DECT_ARI_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern int nl_dect_parse_ari(struct nl_dect_ari *,
|
||||
struct nlattr *);
|
||||
extern int nl_dect_fill_ari(struct nl_msg *,
|
||||
const struct nl_dect_ari *,
|
||||
int);
|
||||
extern void nl_dect_dump_ari(const struct nl_dect_ari *,
|
||||
struct nl_dump_params *);
|
||||
|
||||
extern void nl_dect_ari_set_class(struct nl_dect_ari *,
|
||||
enum dect_ari_classes);
|
||||
extern enum dect_ari_classes nl_dect_ari_get_class(const struct nl_dect_ari *);
|
||||
|
||||
extern void nl_dect_ari_set_fpn(struct nl_dect_ari *, uint32_t);
|
||||
extern uint32_t nl_dect_ari_get_fpn(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_fps(struct nl_dect_ari *, uint32_t);
|
||||
extern uint32_t nl_dect_ari_get_fps(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_emc(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_emc(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_eic(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_eic(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_poc(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_poc(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_gop(struct nl_dect_ari *, uint32_t);
|
||||
extern uint32_t nl_dect_ari_get_gop(const struct nl_dect_ari *);
|
||||
extern void nl_dect_ari_set_fil(struct nl_dect_ari *, uint16_t);
|
||||
extern uint16_t nl_dect_ari_get_fil(const struct nl_dect_ari *);
|
||||
|
||||
#endif /* NETLINK_DECT_ARI_H */
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef NETLINK_DECT_CELL_H
|
||||
#define NETLINK_DECT_CELL_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_cell;
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern struct nl_object_ops nl_dect_cell_obj_ops;
|
||||
|
||||
extern struct nl_dect_cell * nl_dect_cell_alloc(void);
|
||||
extern void nl_dect_cell_get(struct nl_dect_cell *);
|
||||
extern void nl_dect_cell_put(struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_index(struct nl_dect_cell *, int);
|
||||
extern bool nl_dect_cell_test_index(const struct nl_dect_cell *);
|
||||
extern int nl_dect_cell_get_index(const struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_name(struct nl_dect_cell *, const char *);
|
||||
extern bool nl_dect_cell_test_name(const struct nl_dect_cell *);
|
||||
extern const char * nl_dect_cell_get_name(const struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_flags(struct nl_dect_cell *, uint32_t);
|
||||
extern bool nl_dect_cell_test_flags(const struct nl_dect_cell *);
|
||||
extern uint32_t nl_dect_cell_get_flags(const struct nl_dect_cell *);
|
||||
|
||||
extern void nl_dect_cell_set_transceiver(struct nl_dect_cell *,
|
||||
unsigned int,
|
||||
const char *);
|
||||
extern bool nl_dect_cell_test_transceiver(const struct nl_dect_cell *);
|
||||
extern const char * nl_dect_cell_get_transceiver(const struct nl_dect_cell *,
|
||||
unsigned int);
|
||||
|
||||
extern void nl_dect_cell_set_link(struct nl_dect_cell *, int);
|
||||
extern bool nl_dect_cell_test_link(const struct nl_dect_cell *);
|
||||
extern int nl_dect_cell_get_link(const struct nl_dect_cell *);
|
||||
|
||||
extern int nl_dect_cell_alloc_cache(struct nl_sock *,
|
||||
struct nl_cache **);
|
||||
|
||||
extern int nl_dect_cell_build_msg(struct nl_msg *,
|
||||
struct nl_dect_cell *);
|
||||
|
||||
extern int nl_dect_cell_build_add_request(struct nl_dect_cell *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cell_add(struct nl_sock *,
|
||||
struct nl_dect_cell *, int);
|
||||
|
||||
extern int nl_dect_cell_build_del_request(struct nl_dect_cell *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cell_delete(struct nl_sock *,
|
||||
struct nl_dect_cell *, int);
|
||||
|
||||
extern char * nl_dect_cell_i2name(struct nl_cache *, int, char *,
|
||||
size_t);
|
||||
extern int nl_dect_cell_name2i(struct nl_cache *, const char *);
|
||||
|
||||
extern char * nl_dect_cell_flags2str(uint32_t, char *, size_t);
|
||||
extern uint32_t nl_dect_cell_str2flags(const char *);
|
||||
|
||||
#endif /* NETLINK_DECT_CELL_H */
|
|
@ -0,0 +1,61 @@
|
|||
#ifndef NETLINK_DECT_CLUSTER_H
|
||||
#define NETLINK_DECT_CLUSTER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_cluster;
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern struct nl_object_ops nl_dect_cluster_obj_ops;
|
||||
|
||||
extern struct nl_dect_cluster * nl_dect_cluster_alloc(void);
|
||||
extern void nl_dect_cluster_get(struct nl_dect_cluster *);
|
||||
extern void nl_dect_cluster_put(struct nl_dect_cluster *);
|
||||
|
||||
extern unsigned int nl_dect_cluster_get_index(const struct nl_dect_cluster *);
|
||||
|
||||
extern void nl_dect_cluster_set_name(struct nl_dect_cluster *,
|
||||
const char *);
|
||||
extern bool nl_dect_cluster_test_name(const struct nl_dect_cluster *);
|
||||
extern const char * nl_dect_cluster_get_name(const struct nl_dect_cluster *);
|
||||
|
||||
extern void nl_dect_cluster_set_mode(struct nl_dect_cluster *,
|
||||
uint8_t mode);
|
||||
extern bool nl_dect_cluster_test_mode(const struct nl_dect_cluster *);
|
||||
extern uint8_t nl_dect_cluster_get_mode(const struct nl_dect_cluster *);
|
||||
|
||||
extern void nl_dect_cluster_set_pari(struct nl_dect_cluster *,
|
||||
const struct nl_dect_ari *);
|
||||
extern bool nl_dect_cluster_test_pari(const struct nl_dect_cluster *);
|
||||
extern const struct nl_dect_ari *nl_dect_cluster_get_pari(const struct nl_dect_cluster *);
|
||||
|
||||
extern char * nl_dect_cluster_mode2str(enum dect_cluster_modes,
|
||||
char *, size_t);
|
||||
extern enum dect_cluster_modes nl_dect_cluster_str2mode(const char *);
|
||||
|
||||
extern int nl_dect_cluster_alloc_cache(struct nl_sock *,
|
||||
struct nl_cache **);
|
||||
|
||||
extern int nl_dect_cluster_build_msg(struct nl_msg *,
|
||||
struct nl_dect_cluster *);
|
||||
|
||||
extern int nl_dect_cluster_build_add_request(struct nl_dect_cluster *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cluster_add(struct nl_sock *,
|
||||
struct nl_dect_cluster *, int);
|
||||
|
||||
extern int nl_dect_cluster_build_del_request(struct nl_dect_cluster *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cluster_delete(struct nl_sock *,
|
||||
struct nl_dect_cluster *, int);
|
||||
|
||||
extern int nl_dect_cluster_build_query_request(struct nl_dect_cluster *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_cluster_query(struct nl_sock *,
|
||||
struct nl_dect_cluster *, int);
|
||||
|
||||
extern char * nl_dect_cluster_i2name(struct nl_cache *, int, char *,
|
||||
size_t);
|
||||
extern int nl_dect_cluster_name2i(struct nl_cache *, const char *);
|
||||
|
||||
#endif /* NETLINK_DECT_CLUSTER_H */
|
|
@ -0,0 +1,6 @@
|
|||
#ifndef _NETLINK_DECT_H
|
||||
#define _NETLINK_DECT_H
|
||||
|
||||
extern double nl_dect_rssi_to_dbm(uint8_t);
|
||||
|
||||
#endif /* _NETLINK_DECT_H */
|
|
@ -0,0 +1,106 @@
|
|||
#ifndef NETLINK_DECT_LLME_H
|
||||
#define NETLINK_DECT_LLME_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_llme_msg;
|
||||
struct nl_dect_ari;
|
||||
|
||||
extern struct nl_dect_llme_msg *nl_dect_llme_msg_alloc(void);
|
||||
extern void nl_dect_llme_msg_get(struct nl_dect_llme_msg *);
|
||||
extern void nl_dect_llme_msg_put(struct nl_dect_llme_msg *);
|
||||
|
||||
extern int nl_dect_llme_build_request(struct nl_dect_llme_msg *,
|
||||
struct nl_msg **);
|
||||
extern int nl_dect_llme_request(struct nl_sock *,
|
||||
struct nl_dect_llme_msg *);
|
||||
|
||||
extern int nl_dect_llme_build_response(struct nl_dect_llme_msg *,
|
||||
struct nl_msg **);
|
||||
extern int nl_dect_llme_respond(struct nl_sock *, struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_msg_set_index(struct nl_dect_llme_msg *, int);
|
||||
extern void nl_dect_llme_msg_set_type(struct nl_dect_llme_msg *,
|
||||
enum dect_llme_msg_types);
|
||||
extern enum dect_llme_msg_types nl_dect_llme_msg_get_type(const struct nl_dect_llme_msg *);
|
||||
extern void nl_dect_llme_msg_set_op(struct nl_dect_llme_msg *,
|
||||
enum dect_llme_ops);
|
||||
extern enum dect_llme_ops nl_dect_llme_msg_get_op(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern char * nl_dect_llme_msgtype2str(enum dect_llme_msg_types,
|
||||
char *, size_t);
|
||||
extern enum dect_llme_msg_types nl_dect_llme_str2msgtype(const char *);
|
||||
|
||||
extern char * nl_dect_llme_op2str(enum dect_llme_ops,
|
||||
char *, size_t);
|
||||
extern enum dect_llme_ops nl_dect_llme_str2op(const char *);
|
||||
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_pari(struct nl_dect_llme_msg *lmsg,
|
||||
const struct nl_dect_ari *);
|
||||
extern const struct nl_dect_ari *nl_dect_llme_mac_info_get_pari(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_rpn(struct nl_dect_llme_msg *,
|
||||
uint8_t);
|
||||
extern uint8_t nl_dect_llme_mac_info_get_rpn(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_rssi(struct nl_dect_llme_msg *,
|
||||
uint8_t);
|
||||
extern uint8_t nl_dect_llme_mac_info_get_rssi(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_fpc(struct nl_dect_llme_msg *,
|
||||
uint32_t);
|
||||
extern uint32_t nl_dect_llme_mac_info_get_fpc(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_hlc(struct nl_dect_llme_msg *,
|
||||
uint16_t);
|
||||
extern uint16_t nl_dect_llme_mac_info_get_hlc(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_info_set_ehlc(struct nl_dect_llme_msg *,
|
||||
uint16_t);
|
||||
extern uint16_t nl_dect_llme_mac_info_get_ehlc(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern char * nl_dect_llme_fpc2str(uint32_t, char *, size_t);
|
||||
extern uint32_t nl_dect_llme_str2fpc(const char *);
|
||||
|
||||
extern char * nl_dect_llme_hlc2str(uint16_t, char *, size_t);
|
||||
extern uint16_t nl_dect_llme_str2hlc(const char *);
|
||||
|
||||
extern char * nl_dect_llme_ehlc2str(uint16_t, char *, size_t);
|
||||
extern uint16_t nl_dect_llme_str2ehlc(const char *);
|
||||
|
||||
#if 0
|
||||
extern void nl_dect_llme_mac_con_set_mcei(struct nl_dect_llme_msg *,
|
||||
uint32_t);
|
||||
extern uint32_t nl_dect_llme_mac_con_get_mcei(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_con_set_ari(struct nl_dect_llme_msg *,
|
||||
const struct nl_dect_ari *);
|
||||
extern const struct nl_dect_ari * nl_dect_llme_mac_con_get_ari(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_con_set_pmid(struct nl_dect_llme_msg *,
|
||||
uint32_t);
|
||||
extern uint32_t nl_dect_llme_mac_con_get_pmid(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_con_set_type(struct nl_dect_llme_msg *,
|
||||
enum nl_dect_mac_con_types);
|
||||
extern enum nl_dect_mac_con_types nl_dect_llme_mac_con_get_type(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_con_set_ecn(struct nl_dect_llme_msg *,
|
||||
uint8_t);
|
||||
extern uint8_t nl_dect_llme_mac_con_get_ecn(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern void nl_dect_llme_mac_con_set_service(struct nl_dect_llme_msg *,
|
||||
enum nl_dect_mac_con_service_types);
|
||||
extern enum nl_dect_mac_con_service_types nl_dect_llme_mac_con_get_service(const struct nl_dect_llme_msg *);
|
||||
|
||||
extern char * nl_dect_llme_contype2str(enum nl_dect_mac_con_types,
|
||||
char *, size_t);
|
||||
extern enum nl_dect_mac_con_types nl_dect_llme_str2contype(const char *);
|
||||
|
||||
extern char * nl_dect_llme_service2str(enum nl_dect_mac_con_service_types,
|
||||
char *, size_t);
|
||||
extern enum nl_dect_mac_con_service_types nl_dect_llme_str2service(const char *);
|
||||
#endif
|
||||
|
||||
#endif /* NETLINK_DECT_LLME_H */
|
|
@ -0,0 +1,47 @@
|
|||
#ifndef NETLINK_DECT_TRANSCEIVER_H
|
||||
#define NETLINK_DECT_TRANSCEIVER_H
|
||||
|
||||
#include <stdbool.h>
|
||||
|
||||
struct nl_dect_transceiver;
|
||||
|
||||
extern struct nl_object_ops nl_dect_transceiver_obj_ops;
|
||||
|
||||
extern struct nl_dect_transceiver *nl_dect_transceiver_alloc(void);
|
||||
extern void nl_dect_transceiver_get(struct nl_dect_transceiver *);
|
||||
extern void nl_dect_transceiver_put(struct nl_dect_transceiver *);
|
||||
|
||||
extern void nl_dect_transceiver_set_name(struct nl_dect_transceiver *,
|
||||
const char *);
|
||||
extern bool nl_dect_transceiver_test_name(const struct nl_dect_transceiver *);
|
||||
extern const char * nl_dect_transceiver_get_name(const struct nl_dect_transceiver *);
|
||||
|
||||
extern void nl_dect_transceiver_set_type(struct nl_dect_transceiver *,
|
||||
const char *);
|
||||
extern bool nl_dect_transceiver_test_type(const struct nl_dect_transceiver *);
|
||||
extern const char * nl_dect_transceiver_get_type(const struct nl_dect_transceiver *);
|
||||
|
||||
extern void nl_dect_transceiver_set_index(struct nl_dect_transceiver *,
|
||||
int);
|
||||
extern void nl_dect_transceiver_set_link(struct nl_dect_transceiver *,
|
||||
uint8_t);
|
||||
|
||||
extern void nl_dect_transceiver_set_band(struct nl_dect_transceiver *,
|
||||
uint8_t);
|
||||
extern bool nl_dect_transceiver_test_band(const struct nl_dect_transceiver *);
|
||||
extern uint8_t nl_dect_transceiver_get_band(const struct nl_dect_transceiver *);
|
||||
|
||||
extern int nl_dect_transceiver_build_msg(struct nl_msg *,
|
||||
struct nl_dect_transceiver *);
|
||||
extern int nl_dect_transceiver_build_change_request(struct nl_dect_transceiver *,
|
||||
int, struct nl_msg **);
|
||||
extern int nl_dect_transceiver_change(struct nl_sock *,
|
||||
struct nl_dect_transceiver *, int flags);
|
||||
|
||||
extern char * nl_dect_slot_state2str(uint8_t, char *, size_t);
|
||||
extern uint8_t nl_dect_slot_str2state(const char *);
|
||||
|
||||
extern int nl_dect_transceiver_alloc_cache(struct nl_sock *,
|
||||
struct nl_cache **);
|
||||
|
||||
#endif /* NETLINK_DECT_TRANSCEIVER_H */
|
|
@ -26,6 +26,7 @@
|
|||
#include <linux/rtnetlink.h>
|
||||
#include <linux/genetlink.h>
|
||||
#include <linux/netfilter/nfnetlink.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
#include <netlink/version.h>
|
||||
#include <netlink/errno.h>
|
||||
#include <netlink/types.h>
|
||||
|
|
17
lib/Makefile
17
lib/Makefile
|
@ -29,7 +29,10 @@ GENL_OBJ := $(GENL_C:%.c=%.o)
|
|||
NF_C := $(wildcard netfilter/*.c)
|
||||
NF_OBJ := $(NF_C:%.c=%.o)
|
||||
|
||||
ALL_C := $(CORE_C) $(ROUTE_C) $(GENL_C) $(NF_C)
|
||||
DECT_C := $(wildcard dect/*.c)
|
||||
DECT_OBJ := $(DECT_C:%.c=%.o)
|
||||
|
||||
ALL_C := $(CORE_C) $(ROUTE_C) $(GENL_C) $(NF_C) $(DECT_C)
|
||||
ALL_OBJ := $(ALL_C:%.c=%.o)
|
||||
DEPS := $(ALL_C:%.c=%.d)
|
||||
|
||||
|
@ -39,7 +42,8 @@ CORE_LIB := $(PACKAGE_NAME).so
|
|||
ROUTE_LIB := $(PACKAGE_NAME)-route.so
|
||||
GENL_LIB := $(PACKAGE_NAME)-genl.so
|
||||
NF_LIB := $(PACKAGE_NAME)-nf.so
|
||||
LIBS := $(CORE_LIB) $(ROUTE_LIB) $(GENL_LIB) $(NF_LIB)
|
||||
DECT_LIB := $(PACKAGE_NAME)-dect.so
|
||||
LIBS := $(CORE_LIB) $(ROUTE_LIB) $(GENL_LIB) $(NF_LIB) $(DECT_LIB)
|
||||
LIBS_V := $(LIBS:%.so=%.so.$(PACKAGE_VERSION))
|
||||
|
||||
export
|
||||
|
@ -82,6 +86,14 @@ $(NF_LIB): $(NF_LIB).$(PACKAGE_VERSION)
|
|||
@echo " LN $@ -> $<"; \
|
||||
$(RM) -f $@; $(LN) $< -s $@
|
||||
|
||||
$(DECT_LIB).$(PACKAGE_VERSION): $(DECT_OBJ)
|
||||
@echo " LD $@"; \
|
||||
$(CC) -shared -Wl,-soname=$@ -o $@ $^ $(LIBNL_LIB) -lnl
|
||||
|
||||
$(DECT_LIB): $(DECT_LIB).$(PACKAGE_VERSION)
|
||||
@echo " LN $@ -> $<"; \
|
||||
$(RM) -f $@; $(LN) $< -s $@
|
||||
|
||||
clean:
|
||||
@echo " CLEAN lib"; \
|
||||
$(RM) -f $(ALL_OBJ) $(LIBS) $(DEPS) *.so.*
|
||||
|
@ -97,6 +109,7 @@ install:
|
|||
$(LN) -sf $(ROUTE_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(ROUTE_LIB)
|
||||
$(LN) -sf $(GENL_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(GENL_LIB)
|
||||
$(LN) -sf $(NF_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(NF_LIB)
|
||||
$(LN) -sf $(DECT_LIB:%.so=%.so.$(PACKAGE_VERSION)) $(DESTDIR)$(libdir)/$(DECT_LIB)
|
||||
|
||||
$(DEPS): ../Makefile.opts
|
||||
|
||||
|
|
|
@ -0,0 +1,227 @@
|
|||
#include <netlink-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
#define ARI_ATTR_CLASS 0x01
|
||||
#define ARI_ATTR_FPN 0x02
|
||||
#define ARI_ATTR_FPS 0x03
|
||||
#define ARI_ATTR_EMC 0x04
|
||||
#define ARI_ATTR_EIC 0x05
|
||||
#define ARI_ATTR_POC 0x06
|
||||
#define ARI_ATTR_GOP 0x07
|
||||
#define ARI_ATTR_FIL 0x08
|
||||
|
||||
static struct nla_policy nl_dect_ari_policy[DECTA_ARI_MAX + 1] = {
|
||||
[DECTA_ARI_CLASS] = { .type = NLA_U8 },
|
||||
[DECTA_ARI_FPN] = { .type = NLA_U32 },
|
||||
[DECTA_ARI_FPS] = { .type = NLA_U32 },
|
||||
[DECTA_ARI_EMC] = { .type = NLA_U16 },
|
||||
[DECTA_ARI_EIC] = { .type = NLA_U16 },
|
||||
[DECTA_ARI_POC] = { .type = NLA_U16 },
|
||||
[DECTA_ARI_GOP] = { .type = NLA_U32 },
|
||||
[DECTA_ARI_FIL] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
int nl_dect_parse_ari(struct nl_dect_ari *ari, struct nlattr *nla)
|
||||
{
|
||||
struct nlattr *tb[DECTA_ARI_MAX + 1];
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_ARI_MAX, nla, nl_dect_ari_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_ARI_CLASS] == NULL)
|
||||
return -NLE_INVAL;
|
||||
|
||||
memset(ari, 0, sizeof(ari));
|
||||
ari->ari_class = nla_get_u8(tb[DECTA_ARI_CLASS]);
|
||||
if (tb[DECTA_ARI_FPN] != NULL)
|
||||
ari->ari_fpn = nla_get_u32(tb[DECTA_ARI_FPN]);
|
||||
|
||||
switch (ari->ari_class) {
|
||||
case DECT_ARC_A:
|
||||
if (tb[DECTA_ARI_EMC] != NULL)
|
||||
ari->ari_u.emc = nla_get_u16(tb[DECTA_ARI_EMC]);
|
||||
break;
|
||||
case DECT_ARC_B:
|
||||
if (tb[DECTA_ARI_EIC] != NULL)
|
||||
ari->ari_u.eic = nla_get_u16(tb[DECTA_ARI_EIC]);
|
||||
if (tb[DECTA_ARI_FPS] != NULL)
|
||||
ari->ari_fps = nla_get_u32(tb[DECTA_ARI_FPS]);
|
||||
break;
|
||||
case DECT_ARC_C:
|
||||
if (tb[DECTA_ARI_POC] != NULL)
|
||||
ari->ari_u.poc = nla_get_u16(tb[DECTA_ARI_POC]);
|
||||
if (tb[DECTA_ARI_FPS] != NULL)
|
||||
ari->ari_fps = nla_get_u32(tb[DECTA_ARI_FPS]);
|
||||
break;
|
||||
case DECT_ARC_D:
|
||||
if (tb[DECTA_ARI_GOP] != NULL)
|
||||
ari->ari_u.gop = nla_get_u32(tb[DECTA_ARI_GOP]);
|
||||
break;
|
||||
case DECT_ARC_E:
|
||||
if (tb[DECTA_ARI_FIL] != NULL)
|
||||
ari->ari_u.fil = nla_get_u16(tb[DECTA_ARI_FIL]);
|
||||
break;
|
||||
default:
|
||||
return -NLE_INVAL;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_fill_ari(struct nl_msg *msg, const struct nl_dect_ari *ari, int attr)
|
||||
{
|
||||
struct nlattr *nla;
|
||||
|
||||
nla = nla_nest_start(msg, attr);
|
||||
if (nla == NULL)
|
||||
goto nla_put_failure;
|
||||
|
||||
NLA_PUT_U8(msg, DECTA_ARI_CLASS, ari->ari_class);
|
||||
NLA_PUT_U32(msg, DECTA_ARI_FPN, ari->ari_fpn);
|
||||
|
||||
switch (ari->ari_class) {
|
||||
case DECT_ARC_A:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_EMC, ari->ari_u.emc);
|
||||
break;
|
||||
case DECT_ARC_B:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_EIC, ari->ari_u.eic);
|
||||
NLA_PUT_U32(msg, DECTA_ARI_FPS, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_C:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_POC, ari->ari_u.poc);
|
||||
NLA_PUT_U32(msg, DECTA_ARI_FPS, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_D:
|
||||
NLA_PUT_U32(msg, DECTA_ARI_GOP, ari->ari_u.gop);
|
||||
break;
|
||||
case DECT_ARC_E:
|
||||
NLA_PUT_U16(msg, DECTA_ARI_FIL, ari->ari_u.fil);
|
||||
break;
|
||||
}
|
||||
nla_nest_end(msg, nla);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
void nl_dect_dump_ari(const struct nl_dect_ari *ari, struct nl_dump_params *p)
|
||||
{
|
||||
nl_dump(p, "class %c ", 'A' + ari->ari_class);
|
||||
|
||||
switch (ari->ari_class) {
|
||||
case DECT_ARC_A:
|
||||
nl_dump(p, "(residential) EMC: %.4x FPN: %.5x",
|
||||
ari->ari_u.emc, ari->ari_fpn);
|
||||
break;
|
||||
case DECT_ARC_B:
|
||||
nl_dump(p, "(private multiple cell) EIC: %.4x FPN: %.2x FPS: %x",
|
||||
ari->ari_u.eic, ari->ari_fpn, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_C:
|
||||
nl_dump(p, "(public) POC: %.4x FPN: %.2x FPS: %x",
|
||||
ari->ari_u.poc, ari->ari_fpn, ari->ari_fps);
|
||||
break;
|
||||
case DECT_ARC_D:
|
||||
nl_dump(p, "(public GSM) GOP: %.5x FPN: %.2x",
|
||||
ari->ari_u.gop, ari->ari_fpn);
|
||||
break;
|
||||
case DECT_ARC_E:
|
||||
nl_dump(p, "(PP to PP) FIL: %.4x FPN: %.3x",
|
||||
ari->ari_u.fil, ari->ari_fpn);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_class(struct nl_dect_ari *ari, enum dect_ari_classes class)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_CLASS;
|
||||
ari->ari_class = class;
|
||||
}
|
||||
|
||||
enum dect_ari_classes nl_dect_ari_get_class(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_class;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_fpn(struct nl_dect_ari *ari, uint32_t fpn)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_FPN;
|
||||
ari->ari_fpn = fpn;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_ari_get_fpn(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_fpn;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_fps(struct nl_dect_ari *ari, uint32_t fps)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_FPS;
|
||||
ari->ari_fps = fps;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_ari_get_fps(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_fps;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_emc(struct nl_dect_ari *ari, uint16_t emc)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_EMC;
|
||||
ari->ari_u.emc = emc;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_emc(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.emc;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_eic(struct nl_dect_ari *ari, uint16_t eic)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_EIC;
|
||||
ari->ari_u.eic = eic;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_eic(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.eic;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_poc(struct nl_dect_ari *ari, uint16_t poc)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_POC;
|
||||
ari->ari_u.poc = poc;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_poc(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.poc;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_gop(struct nl_dect_ari *ari, uint32_t gop)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_GOP;
|
||||
ari->ari_u.gop = gop;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_ari_get_gop(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.gop;
|
||||
}
|
||||
|
||||
void nl_dect_ari_set_fil(struct nl_dect_ari *ari, uint16_t fil)
|
||||
{
|
||||
ari->ari_flags |= ARI_ATTR_FIL;
|
||||
ari->ari_u.fil = fil;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_ari_get_fil(const struct nl_dect_ari *ari)
|
||||
{
|
||||
return ari->ari_u.fil;
|
||||
}
|
|
@ -0,0 +1,267 @@
|
|||
/*
|
||||
* lib/nl_dect/cell.c DECT Cell 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>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nl_dect
|
||||
* @defgroup nl_dect Transceivers
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/cell.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_cache_ops nl_dect_cell_ops;
|
||||
/** @endcond */
|
||||
|
||||
static struct nla_policy cell_policy[DECTA_CELL_MAX + 1] = {
|
||||
[DECTA_CELL_NAME] = { .type = NLA_STRING, .maxlen = 16 },
|
||||
[DECTA_CELL_FLAGS] = { .type = NLA_U32 },
|
||||
[DECTA_CELL_TRANSCEIVERS] = { .type = NLA_NESTED },
|
||||
[DECTA_CELL_CLUSTER] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int cell_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, struct nl_parser_param *pp)
|
||||
{
|
||||
struct dectmsg *dm = nlmsg_data(n);
|
||||
struct nl_dect_cell *cell;
|
||||
struct nlattr *tb[DECTA_CELL_MAX + 1], *nla;
|
||||
int rem, err;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_CELL_MAX, cell_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
cell = nl_dect_cell_alloc();
|
||||
if (cell == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
cell->ce_msgtype = n->nlmsg_type;
|
||||
cell->c_index = dm->dm_index;
|
||||
|
||||
if (tb[DECTA_CELL_NAME] != NULL)
|
||||
nl_dect_cell_set_name(cell, nla_data(tb[DECTA_CELL_NAME]));
|
||||
if (tb[DECTA_CELL_FLAGS] != NULL)
|
||||
nl_dect_cell_set_flags(cell, nla_get_u32(tb[DECTA_CELL_FLAGS]));
|
||||
if (tb[DECTA_CELL_TRANSCEIVERS] != NULL) {
|
||||
unsigned int i = 0;
|
||||
nla_for_each_nested(nla, tb[DECTA_CELL_TRANSCEIVERS], rem) {
|
||||
char *id = nla_strdup(nla);
|
||||
if (id == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
nl_dect_cell_set_transceiver(cell, i++, id);
|
||||
}
|
||||
}
|
||||
if (tb[DECTA_CELL_CLUSTER] != NULL)
|
||||
nl_dect_cell_set_link(cell, nla_get_u8(tb[DECTA_CELL_CLUSTER]));
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)cell, pp);
|
||||
errout:
|
||||
nl_dect_cell_put(cell);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cell_request_update(struct nl_cache *c, struct nl_sock *h)
|
||||
{
|
||||
struct dectmsg dm;
|
||||
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
return nl_send_simple(h, DECT_GET_CELL, NLM_F_DUMP, &dm, sizeof(dm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Cache Management
|
||||
* @{
|
||||
*/
|
||||
int nl_dect_cell_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
{
|
||||
struct nl_cache *cache;
|
||||
int err;
|
||||
|
||||
cache = nl_cache_alloc(&nl_dect_cell_ops);
|
||||
if (cache == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
|
||||
free(cache);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nl_dect_cell *nl_dect_cell_get_by_name(struct nl_cache *cache, const char *name)
|
||||
{
|
||||
struct nl_dect_cell *cell;
|
||||
|
||||
nl_list_for_each_entry(cell, &cache->c_items, ce_list) {
|
||||
if (!strcmp(cell->c_name, name)) {
|
||||
nl_object_get((struct nl_object *)cell);
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nl_dect_cell *nl_dect_cell_get_by_index(struct nl_cache *cache, int index)
|
||||
{
|
||||
struct nl_dect_cell *cell;
|
||||
|
||||
nl_list_for_each_entry(cell, &cache->c_items, ce_list) {
|
||||
if (cell->c_index == index) {
|
||||
nl_object_get((struct nl_object *)cell);
|
||||
return cell;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Device creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int build_cell_msg(struct nl_dect_cell *tmpl, int cmd, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
msg = nlmsg_alloc_simple(cmd, flags);
|
||||
if (msg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
err = nl_dect_cell_build_msg(msg, tmpl);
|
||||
if (err < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_cell_build_add_request(struct nl_dect_cell *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cell_msg(tmpl, DECT_NEW_CELL, NLM_F_CREATE | flags,
|
||||
result);
|
||||
}
|
||||
|
||||
int nl_dect_cell_add(struct nl_sock *sk, struct nl_dect_cell *cell, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cell_build_add_request(cell, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_cell_build_del_request(struct nl_dect_cell *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cell_msg(tmpl, DECT_DEL_CELL, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_cell_delete(struct nl_sock *sk, struct nl_dect_cell *tmpl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cell_build_del_request(tmpl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Name <-> Index Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
char *nl_dect_cell_i2name(struct nl_cache *cache, int index, char *buf, size_t len)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_dect_cell_get_by_index(cache, index);
|
||||
|
||||
if (cell != NULL) {
|
||||
strncpy(buf, cell->c_name, len - 1);
|
||||
buf[len - 1] = 0;
|
||||
return buf;
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nl_dect_cell_name2i(struct nl_cache *cache, const char *name)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_dect_cell_get_by_name(cache, name);
|
||||
|
||||
if (cell != NULL)
|
||||
return cell->c_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static struct nl_cache_ops nl_dect_cell_ops = {
|
||||
.co_name = "nl_dect/cell",
|
||||
.co_hdrsize = 0,
|
||||
.co_msgtypes = {
|
||||
{ DECT_NEW_CELL, NL_ACT_NEW, "new" },
|
||||
{ DECT_DEL_CELL, NL_ACT_NEW, "del" },
|
||||
{ DECT_GET_CELL, NL_ACT_GET, "get" },
|
||||
END_OF_MSGTYPES_LIST
|
||||
},
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_request_update = cell_request_update,
|
||||
.co_msg_parser = cell_msg_parser,
|
||||
.co_obj_ops = &nl_dect_cell_obj_ops,
|
||||
};
|
||||
|
||||
static void __init cell_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_cell_ops);
|
||||
}
|
||||
|
||||
static void __exit cell_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_cell_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,232 @@
|
|||
/*
|
||||
* lib/dect/cell.c DECT Cell 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-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/data.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/cell.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
#define CELL_ATTR_INDEX 0x0001
|
||||
#define CELL_ATTR_NAME 0x0002
|
||||
#define CELL_ATTR_FLAGS 0x0004
|
||||
#define CELL_ATTR_TRANSCEIVER 0x0008
|
||||
#define CELL_ATTR_LINK 0x0010
|
||||
/** @endcond */
|
||||
|
||||
static void cell_free_data(struct nl_object *obj)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_object_priv(obj);
|
||||
unsigned int i;
|
||||
|
||||
if (cell == NULL)
|
||||
return;
|
||||
for (i = 0; i < 16; i++)
|
||||
free(cell->c_transceiver[i]);
|
||||
}
|
||||
|
||||
static void cell_dump(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_dect_cell *cell = nl_object_priv(obj);
|
||||
struct nl_cache *cluster_cache;
|
||||
unsigned int i;
|
||||
char buf[64];
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_NAME)
|
||||
nl_dump(p, "%u: DECT Cell %s", cell->c_index, cell->c_name);
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_LINK) {
|
||||
cluster_cache = nl_cache_mngt_require("nl_dect/cluster");
|
||||
if (cluster_cache != NULL) {
|
||||
nl_dect_cluster_i2name(cluster_cache, cell->c_link, buf,
|
||||
sizeof(buf));
|
||||
nl_dump(p, "@%s", buf);
|
||||
} else
|
||||
nl_dump(p, "@%u", cell->c_link);
|
||||
}
|
||||
nl_dump(p, ":");
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_FLAGS) {
|
||||
nl_dect_cell_flags2str(cell->c_flags, buf, sizeof(buf));
|
||||
nl_dump(p, " <%s>", buf);
|
||||
}
|
||||
nl_dump(p, "\n");
|
||||
|
||||
if (cell->ce_mask & CELL_ATTR_TRANSCEIVER) {
|
||||
for (i = 0; i < 16 && cell->c_transceiver[i] != NULL; i++)
|
||||
nl_dump(p, "\tTransceiver: %s\n",
|
||||
cell->c_transceiver[i]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct nl_dect_cell *nl_dect_cell_alloc(void)
|
||||
{
|
||||
return (struct nl_dect_cell *)nl_object_alloc(&nl_dect_cell_obj_ops);
|
||||
}
|
||||
|
||||
void nl_dect_cell_get(struct nl_dect_cell *cell)
|
||||
{
|
||||
nl_object_get((struct nl_object *)cell);
|
||||
}
|
||||
|
||||
void nl_dect_cell_put(struct nl_dect_cell *cell)
|
||||
{
|
||||
nl_object_put((struct nl_object *)cell);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
void nl_dect_cell_set_index(struct nl_dect_cell *cell, int index)
|
||||
{
|
||||
cell->c_index = index;
|
||||
cell->ce_mask |= CELL_ATTR_INDEX;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_index(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_INDEX);
|
||||
}
|
||||
|
||||
int nl_dect_cell_get_index(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_index;
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_name(struct nl_dect_cell *cell, const char *name)
|
||||
{
|
||||
cell->c_name = strdup(name);
|
||||
cell->ce_mask |= CELL_ATTR_NAME;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_name(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_NAME);
|
||||
}
|
||||
|
||||
const char *nl_dect_cell_get_name(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_name;
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_flags(struct nl_dect_cell *cell, uint32_t flags)
|
||||
{
|
||||
cell->c_flags = flags;
|
||||
cell->ce_mask |= CELL_ATTR_FLAGS;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_flags(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_FLAGS);
|
||||
}
|
||||
|
||||
uint32_t nl_dect_cell_get_flags(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_flags;
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_transceiver(struct nl_dect_cell *cell, unsigned int i,
|
||||
const char *id)
|
||||
{
|
||||
cell->c_transceiver[i] = strdup(id);
|
||||
cell->ce_mask |= CELL_ATTR_TRANSCEIVER;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_transceiver(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_TRANSCEIVER);
|
||||
}
|
||||
|
||||
const char *nl_dect_cell_get_transceiver(const struct nl_dect_cell *cell,
|
||||
unsigned int i)
|
||||
{
|
||||
return cell->c_transceiver[i];
|
||||
}
|
||||
|
||||
void nl_dect_cell_set_link(struct nl_dect_cell *cell, int link)
|
||||
{
|
||||
cell->c_link = link;
|
||||
cell->ce_mask |= CELL_ATTR_LINK;
|
||||
}
|
||||
|
||||
bool nl_dect_cell_test_link(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return !!(cell->ce_mask & CELL_ATTR_LINK);
|
||||
}
|
||||
|
||||
int nl_dect_cell_get_link(const struct nl_dect_cell *cell)
|
||||
{
|
||||
return cell->c_link;
|
||||
}
|
||||
|
||||
int nl_dect_cell_build_msg(struct nl_msg *msg, struct nl_dect_cell *cell)
|
||||
{
|
||||
struct dectmsg dm = {
|
||||
.dm_index = cell->c_index,
|
||||
};
|
||||
|
||||
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
if (cell->ce_mask & CELL_ATTR_NAME)
|
||||
NLA_PUT_STRING(msg, DECTA_CELL_NAME, cell->c_name);
|
||||
if (cell->ce_mask & CELL_ATTR_FLAGS)
|
||||
NLA_PUT_U32(msg, DECTA_CELL_FLAGS, cell->c_flags);
|
||||
if (cell->ce_mask & CELL_ATTR_LINK)
|
||||
NLA_PUT_U8(msg, DECTA_CELL_CLUSTER, cell->c_link);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static struct trans_tbl cell_flags[] = {
|
||||
__ADD(DECT_CELL_CCP, ccp)
|
||||
};
|
||||
|
||||
char *nl_dect_cell_flags2str(uint32_t flags, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(flags, buf, len, cell_flags, ARRAY_SIZE(cell_flags));
|
||||
}
|
||||
|
||||
uint32_t nl_dect_cell_str2flags(const char *str)
|
||||
{
|
||||
return __str2flags(str, cell_flags, ARRAY_SIZE(cell_flags));
|
||||
}
|
||||
|
||||
/** @cond SKIP */
|
||||
struct nl_object_ops nl_dect_cell_obj_ops = {
|
||||
.oo_name = "nl_dect/cell",
|
||||
.oo_size = sizeof(struct nl_dect_cell),
|
||||
.oo_free_data = cell_free_data,
|
||||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = cell_dump,
|
||||
},
|
||||
.oo_id_attrs = CELL_ATTR_NAME,
|
||||
};
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,297 @@
|
|||
/*
|
||||
* lib/dect/cluster.c DECT Cluster 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>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup nl_dect
|
||||
* @defgroup nl_dect Transceivers
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_cache_ops nl_dect_cluster_ops;
|
||||
/** @endcond */
|
||||
|
||||
static struct nla_policy cluster_policy[DECTA_CLUSTER_MAX + 1] = {
|
||||
[DECTA_CLUSTER_NAME] = { .type = NLA_STRING, .maxlen = 16 },
|
||||
[DECTA_CLUSTER_MODE] = { .type = NLA_U8 },
|
||||
[DECTA_CLUSTER_PARI] = { .type = NLA_NESTED },
|
||||
[DECTA_CLUSTER_CELLS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static int cluster_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, struct nl_parser_param *pp)
|
||||
{
|
||||
struct dectmsg *dm = nlmsg_data(n);
|
||||
struct nl_dect_cluster *cl;
|
||||
struct nlattr *tb[DECTA_CLUSTER_MAX + 1];
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_CLUSTER_MAX, cluster_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
cl = nl_dect_cluster_alloc();
|
||||
if (cl == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
cl->ce_msgtype = n->nlmsg_type;
|
||||
cl->cl_index = dm->dm_index;
|
||||
|
||||
if (tb[DECTA_CLUSTER_NAME] != NULL) {
|
||||
char *name = nla_strdup(tb[DECTA_CLUSTER_NAME]);
|
||||
if (name == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
nl_dect_cluster_set_name(cl, name);
|
||||
free(name);
|
||||
}
|
||||
|
||||
if (tb[DECTA_CLUSTER_MODE] != NULL)
|
||||
nl_dect_cluster_set_mode(cl, nla_get_u8(tb[DECTA_CLUSTER_MODE]));
|
||||
|
||||
if (tb[DECTA_CLUSTER_PARI] != NULL) {
|
||||
struct nl_dect_ari pari;
|
||||
|
||||
err = nl_dect_parse_ari(&pari, tb[DECTA_CLUSTER_PARI]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
nl_dect_cluster_set_pari(cl, &pari);
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)cl, pp);
|
||||
errout:
|
||||
nl_dect_cluster_put(cl);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int cluster_request_update(struct nl_cache *c, struct nl_sock *h)
|
||||
{
|
||||
struct dectmsg dm;
|
||||
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
return nl_send_simple(h, DECT_GET_CLUSTER, NLM_F_DUMP, &dm, sizeof(dm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Cache Management
|
||||
* @{
|
||||
*/
|
||||
int nl_dect_cluster_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
{
|
||||
struct nl_cache *cache;
|
||||
int err;
|
||||
|
||||
cache = nl_cache_alloc(&nl_dect_cluster_ops);
|
||||
if (cache == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
|
||||
free(cache);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct nl_dect_cluster *nl_dect_cluster_get_by_name(struct nl_cache *cache,
|
||||
const char *name)
|
||||
{
|
||||
struct nl_dect_cluster *cl;
|
||||
|
||||
nl_list_for_each_entry(cl, &cache->c_items, ce_list) {
|
||||
if (!strcmp(cl->cl_name, name)) {
|
||||
nl_object_get((struct nl_object *)cl);
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
struct nl_dect_cluster *nl_dect_cluster_get_by_index(struct nl_cache *cache, int index)
|
||||
{
|
||||
struct nl_dect_cluster *cl;
|
||||
|
||||
nl_list_for_each_entry(cl, &cache->c_items, ce_list) {
|
||||
if (cl->cl_index == index) {
|
||||
nl_object_get((struct nl_object *)cl);
|
||||
return cl;
|
||||
}
|
||||
}
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Device creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int build_cluster_msg(struct nl_dect_cluster *tmpl, int cmd, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
msg = nlmsg_alloc_simple(cmd, flags);
|
||||
if (msg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
err = nl_dect_cluster_build_msg(msg, tmpl);
|
||||
if (err < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_add_request(struct nl_dect_cluster *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cluster_msg(tmpl, DECT_NEW_CLUSTER, NLM_F_CREATE | flags,
|
||||
result);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_add(struct nl_sock *sk, struct nl_dect_cluster *cl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cluster_build_add_request(cl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_del_request(struct nl_dect_cluster *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cluster_msg(tmpl, DECT_DEL_CLUSTER, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_delete(struct nl_sock *sk, struct nl_dect_cluster *tmpl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cluster_build_del_request(tmpl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_query_request(struct nl_dect_cluster *tmpl, int flags,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_cluster_msg(tmpl, DECT_GET_CLUSTER, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_cluster_query(struct nl_sock *sk, struct nl_dect_cluster *cl, int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_cluster_build_query_request(cl, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Name <-> Index Translations
|
||||
* @{
|
||||
*/
|
||||
|
||||
char *nl_dect_cluster_i2name(struct nl_cache *cache, int index,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_dect_cluster_get_by_index(cache, index);
|
||||
|
||||
if (cl != NULL) {
|
||||
strncpy(buf, cl->cl_name, len - 1);
|
||||
buf[len - 1] = 0;
|
||||
return buf;
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
int nl_dect_cluster_name2i(struct nl_cache *cache, const char *name)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_dect_cluster_get_by_name(cache, name);
|
||||
|
||||
if (cl != NULL)
|
||||
return cl->cl_index;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static struct nl_cache_ops nl_dect_cluster_ops = {
|
||||
.co_name = "nl_dect/cluster",
|
||||
.co_hdrsize = 0,
|
||||
.co_msgtypes = {
|
||||
{ DECT_NEW_CLUSTER, NL_ACT_NEW, "new" },
|
||||
{ DECT_DEL_CLUSTER, NL_ACT_NEW, "del" },
|
||||
{ DECT_GET_CLUSTER, NL_ACT_GET, "get" },
|
||||
END_OF_MSGTYPES_LIST
|
||||
},
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_request_update = cluster_request_update,
|
||||
.co_msg_parser = cluster_msg_parser,
|
||||
.co_obj_ops = &nl_dect_cluster_obj_ops,
|
||||
};
|
||||
|
||||
static void __init cluster_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_cluster_ops);
|
||||
}
|
||||
|
||||
static void __exit cluster_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_cluster_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,189 @@
|
|||
/*
|
||||
* lib/dect/cluster.c DECT Cluster 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-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/cache.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/data.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
#define CL_ATTR_NAME 0x0001
|
||||
#define CL_ATTR_MODE 0x0002
|
||||
#define CL_ATTR_PARI 0x0004
|
||||
/** @endcond */
|
||||
|
||||
static void cluster_free_data(struct nl_object *obj)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_object_priv(obj);
|
||||
|
||||
if (cl == NULL)
|
||||
return;
|
||||
free(cl->cl_name);
|
||||
}
|
||||
|
||||
static void cluster_dump(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_dect_cluster *cl = nl_object_priv(obj);
|
||||
char buf[64];
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_NAME)
|
||||
nl_dump_line(p, "%d: DECT Cluster %s:\n",
|
||||
cl->cl_index, cl->cl_name);
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_MODE)
|
||||
nl_dump_line(p, "\tMode: %s\n",
|
||||
nl_dect_cluster_mode2str(cl->cl_mode,
|
||||
buf, sizeof(buf)));
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_PARI) {
|
||||
nl_dump(p, "\tPARI: ");
|
||||
nl_dect_dump_ari(&cl->cl_pari, p);
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct nl_dect_cluster *nl_dect_cluster_alloc(void)
|
||||
{
|
||||
return (struct nl_dect_cluster *)nl_object_alloc(&nl_dect_cluster_obj_ops);
|
||||
}
|
||||
|
||||
void nl_dect_cluster_get(struct nl_dect_cluster *cl)
|
||||
{
|
||||
nl_object_get((struct nl_object *)cl);
|
||||
}
|
||||
|
||||
void nl_dect_cluster_put(struct nl_dect_cluster *cl)
|
||||
{
|
||||
nl_object_put((struct nl_object *)cl);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Attributes
|
||||
* @{
|
||||
*/
|
||||
|
||||
unsigned int nl_dect_cluster_get_index(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return cl->cl_index;
|
||||
}
|
||||
|
||||
void nl_dect_cluster_set_name(struct nl_dect_cluster *cl, const char *name)
|
||||
{
|
||||
cl->cl_name = strdup(name);
|
||||
cl->ce_mask |= CL_ATTR_NAME;
|
||||
}
|
||||
|
||||
bool nl_dect_cluster_test_name(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return !!(cl->ce_mask & CL_ATTR_NAME);
|
||||
}
|
||||
|
||||
const char *nl_dect_cluster_get_name(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return cl->cl_name;
|
||||
}
|
||||
|
||||
void nl_dect_cluster_set_mode(struct nl_dect_cluster *cl, uint8_t mode)
|
||||
{
|
||||
cl->cl_mode = mode;
|
||||
cl->ce_mask |= CL_ATTR_MODE;
|
||||
}
|
||||
|
||||
bool nl_dect_cluster_test_mode(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return !!(cl->ce_mask & CL_ATTR_MODE);
|
||||
}
|
||||
|
||||
uint8_t nl_dect_cluster_get_mode(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return cl->cl_mode;
|
||||
}
|
||||
|
||||
void nl_dect_cluster_set_pari(struct nl_dect_cluster *cl, const struct nl_dect_ari *pari)
|
||||
{
|
||||
memcpy(&cl->cl_pari, pari, sizeof(cl->cl_pari));
|
||||
cl->ce_mask |= CL_ATTR_PARI;
|
||||
}
|
||||
|
||||
bool nl_dect_cluster_test_pari(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return !!(cl->ce_mask & CL_ATTR_PARI);
|
||||
}
|
||||
|
||||
const struct nl_dect_ari *nl_dect_cluster_get_pari(const struct nl_dect_cluster *cl)
|
||||
{
|
||||
return &cl->cl_pari;
|
||||
}
|
||||
|
||||
int nl_dect_cluster_build_msg(struct nl_msg *msg, struct nl_dect_cluster *cl)
|
||||
{
|
||||
struct dectmsg dm = {
|
||||
.dm_index = cl->cl_index,
|
||||
};
|
||||
|
||||
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
|
||||
if (cl->ce_mask & CL_ATTR_NAME)
|
||||
NLA_PUT_STRING(msg, DECTA_CLUSTER_NAME, cl->cl_name);
|
||||
if (nl_dect_fill_ari(msg, &cl->cl_pari, DECTA_CLUSTER_PARI) < 0)
|
||||
goto nla_put_failure;
|
||||
if (cl->ce_mask & CL_ATTR_MODE)
|
||||
NLA_PUT_U8(msg, DECTA_CLUSTER_MODE, cl->cl_mode);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static struct trans_tbl cluster_modes[] = {
|
||||
__ADD(DECT_MODE_FP, FP)
|
||||
__ADD(DECT_MODE_PP, PP)
|
||||
__ADD(DECT_MODE_MONITOR, monitor)
|
||||
};
|
||||
|
||||
char *nl_dect_cluster_mode2str(enum dect_cluster_modes mode, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(mode, buf, len, cluster_modes,
|
||||
ARRAY_SIZE(cluster_modes));
|
||||
}
|
||||
|
||||
enum dect_cluster_modes nl_dect_cluster_str2mode(const char *str)
|
||||
{
|
||||
return __str2type(str, cluster_modes, ARRAY_SIZE(cluster_modes));
|
||||
}
|
||||
|
||||
|
||||
/** @cond SKIP */
|
||||
struct nl_object_ops nl_dect_cluster_obj_ops = {
|
||||
.oo_name = "nl_dect/cluster",
|
||||
.oo_size = sizeof(struct nl_dect_cluster),
|
||||
.oo_free_data = cluster_free_data,
|
||||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = cluster_dump,
|
||||
},
|
||||
.oo_id_attrs = CL_ATTR_NAME,
|
||||
};
|
||||
|
||||
/** @endcond */
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,22 @@
|
|||
/*
|
||||
* lib/dect/dect.c DECT
|
||||
*
|
||||
* 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-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/dect.h>
|
||||
|
||||
double nl_dect_rssi_to_dbm(uint8_t rssi)
|
||||
{
|
||||
if (rssi == 0)
|
||||
return 0;
|
||||
return -93 + (rssi * 60.0 / 255);
|
||||
}
|
|
@ -0,0 +1,843 @@
|
|||
/*
|
||||
* lib/dect/llme.c DECT Lower Layer Management Entity 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>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup dect
|
||||
* @defgroup dect LLME
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/dect.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
#include <netlink/dect/llme.h>
|
||||
#include <linux/dect_netlink.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_object_ops llme_msg_obj_ops;
|
||||
/** @endcond */
|
||||
|
||||
#define MAC_INFO_ATTR_PARI 0x010000
|
||||
#define MAC_INFO_ATTR_RPN 0x020000
|
||||
#define MAC_INFO_ATTR_RSSI 0x040000
|
||||
#define MAC_INFO_ATTR_FPC 0x080000
|
||||
#define MAC_INFO_ATTR_HLC 0x100000
|
||||
#define MAC_INFO_ATTR_EHLC 0x200000
|
||||
|
||||
static inline struct nl_dect_llme_mac_info *mac_info(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return (void *)&lmsg->lm_mi;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_pari(struct nl_dect_llme_msg *lmsg,
|
||||
const struct nl_dect_ari *pari)
|
||||
{
|
||||
struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
|
||||
|
||||
memcpy(&mi->mi_pari, pari, sizeof(mi->mi_pari));
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_PARI;
|
||||
}
|
||||
|
||||
const struct nl_dect_ari *nl_dect_llme_mac_info_get_pari(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return &mac_info(lmsg)->mi_pari;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_rpn(struct nl_dect_llme_msg *lmsg, uint8_t rpn)
|
||||
{
|
||||
mac_info(lmsg)->mi_rpn = rpn;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_RPN;
|
||||
}
|
||||
|
||||
uint8_t nl_dect_llme_mac_info_get_rpn(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_rpn;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_rssi(struct nl_dect_llme_msg *lmsg, uint8_t rssi)
|
||||
{
|
||||
mac_info(lmsg)->mi_rssi = rssi;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_RSSI;
|
||||
}
|
||||
|
||||
uint8_t nl_dect_llme_mac_info_get_rssi(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_rssi;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_fpc(struct nl_dect_llme_msg *lmsg, uint32_t fpc)
|
||||
{
|
||||
mac_info(lmsg)->mi_fpc = fpc;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_FPC;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_mac_info_get_fpc(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_fpc;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_hlc(struct nl_dect_llme_msg *lmsg, uint16_t hlc)
|
||||
{
|
||||
mac_info(lmsg)->mi_hlc = hlc;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_HLC;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_mac_info_get_hlc(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_hlc;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_info_set_ehlc(struct nl_dect_llme_msg *lmsg, uint16_t ehlc)
|
||||
{
|
||||
mac_info(lmsg)->mi_ehlc = ehlc;
|
||||
lmsg->ce_mask |= MAC_INFO_ATTR_EHLC;
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_mac_info_get_ehlc(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_info(lmsg)->mi_ehlc;
|
||||
}
|
||||
|
||||
static struct trans_tbl fixed_part_capabilities[] = {
|
||||
__ADD(DECT_FPC_EXTENDED_FP_INFO, extended_fp_info)
|
||||
__ADD(DECT_FPC_DOUBLE_DUPLEX_BEARER_CONNECTION, double_duplex_bearer_connection)
|
||||
__ADD(DECT_FPC_RESERVED, reserved)
|
||||
__ADD(DECT_FPC_DOUBLE_SLOT, double_slot)
|
||||
__ADD(DECT_FPC_HALF_SLOT, half_slot)
|
||||
__ADD(DECT_FPC_FULL_SLOT, full_slot)
|
||||
__ADD(DECT_FPC_FREQ_CONTROL, frequency_control)
|
||||
__ADD(DECT_FPC_PAGE_REPETITION, page_repetition)
|
||||
__ADD(DECT_FPC_CO_SETUP_ON_DUMMY, co_setup_on_dummy)
|
||||
__ADD(DECT_FPC_CL_UPLINK, cl_uplink)
|
||||
__ADD(DECT_FPC_CL_DOWNLINK, cl_downlink)
|
||||
__ADD(DECT_FPC_BASIC_A_FIELD_SETUP, basic_a_field_setup)
|
||||
__ADD(DECT_FPC_ADV_A_FIELD_SETUP, advanced_a_field_setup)
|
||||
__ADD(DECT_FPC_B_FIELD_SETUP, b_field_setup)
|
||||
__ADD(DECT_FPC_CF_MESSAGES, cf_messages)
|
||||
__ADD(DECT_FPC_IN_MIN_DELAY, in_min_delay)
|
||||
__ADD(DECT_FPC_IN_NORM_DELAY, in_normal_delay)
|
||||
__ADD(DECT_FPC_IP_ERROR_DETECTION, ip_error_detection)
|
||||
__ADD(DECT_FPC_IP_ERROR_CORRECTION, ip_error_correction)
|
||||
__ADD(DECT_FPC_MULTIBEARER_CONNECTIONS, multibearer_connections)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_fpc2str(uint32_t fpc, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(fpc, buf, len, fixed_part_capabilities,
|
||||
ARRAY_SIZE(fixed_part_capabilities));
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_str2fpc(const char *str)
|
||||
{
|
||||
return __str2flags(str, fixed_part_capabilities,
|
||||
ARRAY_SIZE(fixed_part_capabilities));
|
||||
}
|
||||
|
||||
static struct trans_tbl higher_layer_capabilities[] = {
|
||||
__ADD(DECT_HLC_ADPCM_G721_VOICE, adpcm_g721_voice)
|
||||
__ADD(DECT_HLC_GAP_PAP_BASIC_SPEECH, gap_pap_basic_speech)
|
||||
__ADD(DECT_HLC_NON_VOICE_CIRCUIT_SWITCHED, non_voice_circuit_switched_service)
|
||||
__ADD(DECT_HLC_NON_VOICE_PACKET_SWITCHED, non_voice_packet_switched_service)
|
||||
__ADD(DECT_HLC_STANDARD_AUTHENTICATION, standard_authentication)
|
||||
__ADD(DECT_HLC_STANDARD_CIPHERING, standard_ciphering)
|
||||
__ADD(DECT_HLC_LOCATION_REGISTRATION, location_registration)
|
||||
__ADD(DECT_HLC_SIM_SERVICES, sim_services)
|
||||
__ADD(DECT_HLC_NON_STATIC_FIXED_PART, non_static_fixed_part)
|
||||
__ADD(DECT_HLC_CISS_SERVICE, ciss_service)
|
||||
__ADD(DECT_HLC_CLMS_SERVICE, clms_service)
|
||||
__ADD(DECT_HLC_COMS_SERVICE, coms_service)
|
||||
__ADD(DECT_HLC_ACCESS_RIGHT_REQUESTS, access_right_requests)
|
||||
__ADD(DECT_HLC_EXTERNAL_HANDOVER, external_handover)
|
||||
__ADD(DECT_HLC_CONNECTION_HANDOVER, connection_handover)
|
||||
__ADD(DECT_HLC_RESERVED, reserved)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_hlc2str(uint16_t hlc, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(hlc, buf, len, higher_layer_capabilities,
|
||||
ARRAY_SIZE(higher_layer_capabilities));
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_str2hlc(const char *str)
|
||||
{
|
||||
return __str2flags(str, higher_layer_capabilities,
|
||||
ARRAY_SIZE(higher_layer_capabilities));
|
||||
}
|
||||
|
||||
static struct trans_tbl extended_higher_layer_capabilities[] = {
|
||||
__ADD(DECT_EHLC_ISDN_DATA_SERVICE, isdn_data_service)
|
||||
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_A_B, data_service_profile_a_b)
|
||||
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_C, data_service_profile_c)
|
||||
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_D, data_service_profile_d)
|
||||
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_E, data_service_profile_e)
|
||||
__ADD(DECT_EHLC_DATA_SERVICE_PROFILE_F, data_service_profile_f)
|
||||
__ADD(DECT_EHLC_ASYMETRIC_BEARERS, asymetric_bearers)
|
||||
__ADD(DECT_EHLC_TPUI_LOCATION_REGISTRATION, tpui_location_registration)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_ehlc2str(uint16_t ehlc, char *buf, size_t len)
|
||||
{
|
||||
return __flags2str(ehlc, buf, len, extended_higher_layer_capabilities,
|
||||
ARRAY_SIZE(extended_higher_layer_capabilities));
|
||||
}
|
||||
|
||||
uint16_t nl_dect_llme_str2ehlc(const char *str)
|
||||
{
|
||||
return __str2flags(str, extended_higher_layer_capabilities,
|
||||
ARRAY_SIZE(extended_higher_layer_capabilities));
|
||||
}
|
||||
|
||||
static void nl_dect_llme_mac_info_dump(const struct nl_dect_llme_msg *lmsg,
|
||||
struct nl_dump_params *p)
|
||||
{
|
||||
const struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
|
||||
char buf[256];
|
||||
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_PARI) {
|
||||
nl_dump(p, "\tARI: ");
|
||||
nl_dect_dump_ari(&mi->mi_pari, p);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_RPN)
|
||||
nl_dump(p, " RPN: %x", mi->mi_rpn);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_RSSI)
|
||||
nl_dump(p, " signal level: %.2fdBm", nl_dect_rssi_to_dbm(mi->mi_rssi));
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_FPC) {
|
||||
nl_dect_llme_fpc2str(mi->mi_fpc, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tCapabilities: %s", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_HLC) {
|
||||
nl_dect_llme_hlc2str(mi->mi_hlc, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tHigher layer capabilities: %s", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC) {
|
||||
nl_dect_llme_ehlc2str(mi->mi_ehlc, buf, sizeof(buf));
|
||||
nl_dump(p, "\n\tExtended higher layer capabilities: %s", buf);
|
||||
}
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
|
||||
static struct nla_policy nl_dect_efpc_policy[DECTA_EFPC_MAX + 1] = {
|
||||
[DECTA_EFPC_CRFP_HOPS] = { .type = NLA_U8 },
|
||||
[DECTA_EFPC_CRFP_ENCRYPTION] = { },
|
||||
[DECTA_EFPC_REP_HOPS] = { .type = NLA_U8 },
|
||||
[DECTA_EFPC_REP_INTERLACING] = { },
|
||||
[DECTA_EFPC_EHLC] = { .type = NLA_U16 },
|
||||
};
|
||||
|
||||
static struct nla_policy nl_dect_mac_info_policy[DECTA_MAC_INFO_MAX + 1] = {
|
||||
[DECTA_MAC_INFO_PARI] = { .type = NLA_NESTED },
|
||||
[DECTA_MAC_INFO_RPN] = { .type = NLA_U8 },
|
||||
[DECTA_MAC_INFO_RSSI] = { .type = NLA_U8 },
|
||||
[DECTA_MAC_INFO_SARI_LIST] = { .type = NLA_NESTED },
|
||||
[DECTA_MAC_INFO_FPC] = { .type = NLA_U32 },
|
||||
[DECTA_MAC_INFO_HLC] = { .type = NLA_U16 },
|
||||
[DECTA_MAC_INFO_EFPC] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static int nl_dect_llme_mac_info_parse(struct nl_dect_llme_msg *lmsg,
|
||||
struct nlattr *tb[])
|
||||
{
|
||||
struct nl_dect_ari pari;
|
||||
int err;
|
||||
|
||||
if (tb[DECTA_MAC_INFO_PARI] != NULL) {
|
||||
err = nl_dect_parse_ari(&pari, tb[DECTA_MAC_INFO_PARI]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
nl_dect_llme_mac_info_set_pari(lmsg, &pari);
|
||||
}
|
||||
if (tb[DECTA_MAC_INFO_RPN] != NULL)
|
||||
nl_dect_llme_mac_info_set_rpn(lmsg, nla_get_u8(tb[DECTA_MAC_INFO_RPN]));
|
||||
if (tb[DECTA_MAC_INFO_RSSI] != NULL)
|
||||
nl_dect_llme_mac_info_set_rssi(lmsg, nla_get_u8(tb[DECTA_MAC_INFO_RSSI]));
|
||||
if (tb[DECTA_MAC_INFO_FPC] != NULL)
|
||||
nl_dect_llme_mac_info_set_fpc(lmsg, nla_get_u32(tb[DECTA_MAC_INFO_FPC]));
|
||||
if (tb[DECTA_MAC_INFO_HLC] != NULL)
|
||||
nl_dect_llme_mac_info_set_hlc(lmsg, nla_get_u16(tb[DECTA_MAC_INFO_HLC]));
|
||||
if (tb[DECTA_MAC_INFO_EFPC] != NULL) {
|
||||
struct nlattr *nla[DECTA_EFPC_MAX + 1];
|
||||
|
||||
err = nla_parse_nested(nla, DECTA_EFPC_MAX, tb[DECTA_MAC_INFO_EFPC],
|
||||
nl_dect_efpc_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
nl_dect_llme_mac_info_set_ehlc(lmsg, nla_get_u16(nla[DECTA_EFPC_EHLC]));
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl_dect_llme_mac_info_build(struct nl_msg *msg,
|
||||
struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
struct nl_dect_llme_mac_info *mi = mac_info(lmsg);
|
||||
int err;
|
||||
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_PARI) {
|
||||
err = nl_dect_fill_ari(msg, &mi->mi_pari, DECTA_MAC_INFO_PARI);
|
||||
if (err < 0)
|
||||
return err;
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_RPN)
|
||||
NLA_PUT_U8(msg, DECTA_MAC_INFO_RPN, mi->mi_rpn);
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_FPC)
|
||||
NLA_PUT_U32(msg, DECTA_MAC_INFO_FPC, mi->mi_fpc);
|
||||
#ifdef FIXME
|
||||
if (lmsg->ce_mask & MAC_INFO_ATTR_EHLC)
|
||||
NLA_PUT_U16(msg, DECTA_MAC_INFO_EHLC, mi->mi_ehlc);
|
||||
#endif
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
#if 0
|
||||
#define MAC_CON_ATTR_MCEI 0x010000
|
||||
#define MAC_CON_ATTR_ARI 0x020000
|
||||
#define MAC_CON_ATTR_PMID 0x040000
|
||||
#define MAC_CON_ATTR_TYPE 0x080000
|
||||
#define MAC_CON_ATTR_ECN 0x100000
|
||||
#define MAC_CON_ATTR_SERVICE 0x200000
|
||||
|
||||
static inline struct nl_dect_llme_mac_con *mac_con(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return (void *)&lmsg->lm_mc;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_con_set_mcei(struct nl_dect_llme_msg *lmsg, uint32_t mcei)
|
||||
{
|
||||
mac_con(lmsg)->mc_mcei = mcei;
|
||||
lmsg->ce_mask |= MAC_CON_ATTR_MCEI;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_mac_con_get_mcei(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_con(lmsg)->mc_mcei;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_con_set_ari(struct nl_dect_llme_msg *lmsg, const struct nl_dect_ari *ari)
|
||||
{
|
||||
struct nl_dect_llme_mac_con *mc = mac_con(lmsg);
|
||||
|
||||
memcpy(&mc->mc_ari, ari, sizeof(mc->mc_ari));
|
||||
lmsg->ce_mask |= MAC_CON_ATTR_ARI;
|
||||
}
|
||||
|
||||
const struct nl_dect_ari *nl_dect_llme_mac_con_get_ari(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return &mac_con(lmsg)->mc_ari;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_con_set_pmid(struct nl_dect_llme_msg *lmsg, uint32_t pmid)
|
||||
{
|
||||
mac_con(lmsg)->mc_pmid = pmid;
|
||||
lmsg->ce_mask |= MAC_CON_ATTR_PMID;
|
||||
}
|
||||
|
||||
uint32_t nl_dect_llme_mac_con_get_pmid(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_con(lmsg)->mc_pmid;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_con_set_type(struct nl_dect_llme_msg *lmsg,
|
||||
enum nl_dect_mac_con_types type)
|
||||
{
|
||||
mac_con(lmsg)->mc_type = type;
|
||||
lmsg->ce_mask |= MAC_CON_ATTR_TYPE;
|
||||
}
|
||||
|
||||
enum nl_dect_mac_con_types nl_dect_llme_mac_con_get_type(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_con(lmsg)->mc_type;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_con_set_ecn(struct nl_dect_llme_msg *lmsg, uint8_t ecn)
|
||||
{
|
||||
mac_con(lmsg)->mc_ecn = ecn;
|
||||
lmsg->ce_mask |= MAC_CON_ATTR_ECN;
|
||||
}
|
||||
|
||||
uint8_t nl_dect_llme_mac_con_get_ecn(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_con(lmsg)->mc_ecn;
|
||||
}
|
||||
|
||||
void nl_dect_llme_mac_con_set_service(struct nl_dect_llme_msg *lmsg,
|
||||
enum nl_dect_mac_con_service_types service)
|
||||
{
|
||||
mac_con(lmsg)->mc_service = service;
|
||||
lmsg->ce_mask |= MAC_CON_ATTR_SERVICE;
|
||||
}
|
||||
|
||||
enum nl_dect_mac_con_service_types
|
||||
nl_dect_llme_mac_con_get_service(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return mac_con(lmsg)->mc_service;
|
||||
}
|
||||
|
||||
static struct trans_tbl con_types[] = {
|
||||
__ADD(DECT_MAC_CON_BASIC, basic)
|
||||
__ADD(DECT_MAC_CON_ADVANCED, advanced)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_contype2str(enum nl_dect_mac_con_types type, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(type, buf, len, con_types, ARRAY_SIZE(con_types));
|
||||
}
|
||||
|
||||
enum nl_dect_mac_con_types nl_dect_llme_str2contype(const char *str)
|
||||
{
|
||||
return __str2type(str, con_types, ARRAY_SIZE(con_types));
|
||||
}
|
||||
|
||||
static struct trans_tbl service_types[] = {
|
||||
__ADD(DECT_MAC_CON_IN_MIN_DELAY, I_N_minimal_delay)
|
||||
__ADD(DECT_MAC_CON_IN_NORM_DELAY, I_N_normal_delay)
|
||||
__ADD(DECT_MAC_CON_IP_ERROR_DETECTION, I_P_error_detection)
|
||||
__ADD(DECT_MAC_CON_IP_ERROR_CORRECTION, I_P_error_correction)
|
||||
__ADD(DECT_MAC_CON_UNKNOWN, unknown)
|
||||
__ADD(DECT_MAC_CON_C_ONLY, C_only)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_service2str(enum nl_dect_mac_con_service_types service,
|
||||
char *buf, size_t len)
|
||||
{
|
||||
return __type2str(service, buf, len, service_types,
|
||||
ARRAY_SIZE(service_types));
|
||||
}
|
||||
|
||||
enum nl_dect_mac_con_service_types nl_dect_llme_str2service(const char *str)
|
||||
{
|
||||
return __str2type(str, service_types, ARRAY_SIZE(service_types));
|
||||
}
|
||||
|
||||
static void nl_dect_llme_mac_con_dump(const struct nl_dect_llme_msg *lmsg,
|
||||
struct nl_dump_params *p)
|
||||
{
|
||||
const struct nl_dect_llme_mac_con *mc = mac_con(lmsg);
|
||||
char buf[256];
|
||||
|
||||
nl_dump(p, "\t");
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_MCEI)
|
||||
nl_dump(p, "MCEI %x: ", mc->mc_mcei);
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_PMID)
|
||||
nl_dump(p, "PMID: %x ", mc->mc_pmid);
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_ARI) {
|
||||
nl_dump(p, "=> ");
|
||||
nl_dect_dump_ari(&mc->mc_ari, p);
|
||||
nl_dump(p, " ");
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_ECN)
|
||||
nl_dump(p, "ECN: %x ", mc->mc_ecn);
|
||||
nl_dump(p, "\n");
|
||||
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_TYPE) {
|
||||
nl_dect_llme_contype2str(mc->mc_type, buf, sizeof(buf));
|
||||
nl_dump(p, "\tType: %s\n", buf);
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_SERVICE) {
|
||||
nl_dect_llme_service2str(mc->mc_service, buf, sizeof(buf));
|
||||
nl_dump(p, "\tService: %s\n", buf);
|
||||
}
|
||||
nl_dump(p, "\n");
|
||||
}
|
||||
|
||||
static struct nla_policy nl_dect_mac_con_policy[DECTA_MAC_CON_MAX + 1] = {
|
||||
[DECTA_MAC_CON_MCEI] = { .type = NLA_U32 },
|
||||
[DECTA_MAC_CON_ARI] = { .type = NLA_NESTED },
|
||||
[DECTA_MAC_CON_PMID] = { .type = NLA_U32 },
|
||||
[DECTA_MAC_CON_TYPE] = { .type = NLA_U8 },
|
||||
[DECTA_MAC_CON_ECN] = { .type = NLA_U8 },
|
||||
[DECTA_MAC_CON_SERVICE] = { .type = NLA_U8 },
|
||||
};
|
||||
|
||||
static int nl_dect_llme_mac_con_parse(struct nl_dect_llme_msg *lmsg,
|
||||
struct nlattr *tb[])
|
||||
{
|
||||
struct nl_dect_ari ari;
|
||||
int err;
|
||||
|
||||
if (tb[DECTA_MAC_CON_MCEI] != NULL)
|
||||
nl_dect_llme_mac_con_set_mcei(lmsg, nla_get_u32(tb[DECTA_MAC_CON_MCEI]));
|
||||
if (tb[DECTA_MAC_CON_ARI] != NULL) {
|
||||
err = nl_dect_parse_ari(&ari, tb[DECTA_MAC_CON_ARI]);
|
||||
if (err < 0)
|
||||
return err;
|
||||
nl_dect_llme_mac_con_set_ari(lmsg, &ari);
|
||||
}
|
||||
if (tb[DECTA_MAC_CON_PMID] != NULL)
|
||||
nl_dect_llme_mac_con_set_pmid(lmsg, nla_get_u32(tb[DECTA_MAC_CON_PMID]));
|
||||
if (tb[DECTA_MAC_CON_TYPE] != NULL)
|
||||
nl_dect_llme_mac_con_set_type(lmsg, nla_get_u8(tb[DECTA_MAC_CON_TYPE]));
|
||||
if (tb[DECTA_MAC_CON_ECN] != NULL)
|
||||
nl_dect_llme_mac_con_set_ecn(lmsg, nla_get_u8(tb[DECTA_MAC_CON_ECN]));
|
||||
if (tb[DECTA_MAC_CON_SERVICE] != NULL)
|
||||
nl_dect_llme_mac_con_set_service(lmsg, nla_get_u8(tb[DECTA_MAC_CON_SERVICE]));
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int nl_dect_llme_mac_con_build(struct nl_msg *msg,
|
||||
struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
struct nl_dect_llme_mac_con *mc = mac_con(lmsg);
|
||||
int err;
|
||||
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_MCEI)
|
||||
NLA_PUT_U32(msg, DECTA_MAC_CON_MCEI, mc->mc_mcei);
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_ARI) {
|
||||
err = nl_dect_fill_ari(msg, &mc->mc_ari, DECTA_MAC_CON_ARI);
|
||||
if (err < 0)
|
||||
goto nla_put_failure;
|
||||
}
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_PMID)
|
||||
NLA_PUT_U32(msg, DECTA_MAC_CON_PMID, mc->mc_pmid);
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_TYPE)
|
||||
NLA_PUT_U8(msg, DECTA_MAC_CON_TYPE, mc->mc_type);
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_ECN)
|
||||
NLA_PUT_U8(msg, DECTA_MAC_CON_ECN, mc->mc_ecn);
|
||||
if (lmsg->ce_mask & MAC_CON_ATTR_SERVICE)
|
||||
NLA_PUT_U8(msg, DECTA_MAC_CON_SERVICE, mc->mc_service);
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
#endif
|
||||
|
||||
static const struct nl_dect_llme_link {
|
||||
int (*parse)(struct nl_dect_llme_msg *, struct nlattr *[]);
|
||||
int (*build)(struct nl_msg *, struct nl_dect_llme_msg *);
|
||||
void (*dump)(const struct nl_dect_llme_msg *, struct nl_dump_params *);
|
||||
struct nla_policy *policy;
|
||||
unsigned int maxtype;
|
||||
} nl_dect_llme_dispatch[DECT_LLME_MAX + 1] = {
|
||||
[DECT_LLME_SCAN] = {
|
||||
.policy = nl_dect_mac_info_policy,
|
||||
.maxtype = DECTA_MAC_INFO_MAX,
|
||||
.parse = nl_dect_llme_mac_info_parse,
|
||||
.build = nl_dect_llme_mac_info_build,
|
||||
.dump = nl_dect_llme_mac_info_dump,
|
||||
},
|
||||
[DECT_LLME_MAC_INFO] = {
|
||||
.policy = nl_dect_mac_info_policy,
|
||||
.maxtype = DECTA_MAC_INFO_MAX,
|
||||
.parse = nl_dect_llme_mac_info_parse,
|
||||
.build = nl_dect_llme_mac_info_build,
|
||||
.dump = nl_dect_llme_mac_info_dump,
|
||||
},
|
||||
#if 0
|
||||
[DECT_LLME_MAC_CON] = {
|
||||
.policy = nl_dect_mac_con_policy,
|
||||
.maxtype = DECTA_MAC_CON_MAX,
|
||||
.parse = nl_dect_llme_mac_con_parse,
|
||||
.build = nl_dect_llme_mac_con_build,
|
||||
.dump = nl_dect_llme_mac_con_dump,
|
||||
},
|
||||
#endif
|
||||
};
|
||||
|
||||
static void llme_msg_dump(struct nl_object *obj, struct nl_dump_params *p)
|
||||
{
|
||||
struct nl_dect_llme_msg *lmsg = nl_object_priv(obj);
|
||||
const struct nl_dect_llme_link *link;
|
||||
char buf1[64], buf2[64];
|
||||
|
||||
nl_dect_llme_msgtype2str(lmsg->lm_type, buf1, sizeof(buf1));
|
||||
nl_dect_llme_op2str(lmsg->lm_op, buf2, sizeof(buf2));
|
||||
nl_dump(p, "%s-%s:\n", buf1, buf2);
|
||||
|
||||
link = &nl_dect_llme_dispatch[lmsg->lm_type];
|
||||
link->dump(lmsg, p);
|
||||
}
|
||||
|
||||
static struct nla_policy nl_dect_llme_policy[DECTA_LLME_MAX + 1] = {
|
||||
[DECTA_LLME_OP] = { .type = NLA_U8 },
|
||||
[DECTA_LLME_TYPE] = { .type = NLA_U8 },
|
||||
[DECTA_LLME_DATA] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static int llme_msg_parser(struct nl_cache_ops *ops, struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n, struct nl_parser_param *pp)
|
||||
{
|
||||
const struct nl_dect_llme_link *link;
|
||||
struct dectmsg *dm = nlmsg_data(n);
|
||||
struct nlattr *tb[DECTA_LLME_MAX + 1];
|
||||
struct nl_dect_llme_msg *lmsg;
|
||||
uint8_t op, type;
|
||||
int err;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(*dm), tb, DECTA_LLME_MAX, nl_dect_llme_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_LLME_OP] == NULL ||
|
||||
tb[DECTA_LLME_TYPE] == NULL ||
|
||||
tb[DECTA_LLME_DATA] == NULL)
|
||||
return -NLE_INVAL;
|
||||
|
||||
type = nla_get_u8(tb[DECTA_LLME_TYPE]);
|
||||
if (type > DECT_LLME_MAX)
|
||||
return -NLE_INVAL;
|
||||
link = &nl_dect_llme_dispatch[type];
|
||||
|
||||
op = nla_get_u8(tb[DECTA_LLME_OP]);
|
||||
switch (op) {
|
||||
case DECT_LLME_REQUEST:
|
||||
case DECT_LLME_INDICATE:
|
||||
case DECT_LLME_RESPONSE:
|
||||
case DECT_LLME_CONFIRM:
|
||||
if (link->parse == NULL)
|
||||
return -NLE_OPNOTSUPP;
|
||||
break;
|
||||
default:
|
||||
return -NLE_INVAL;
|
||||
}
|
||||
|
||||
lmsg = nl_dect_llme_msg_alloc();
|
||||
lmsg->ce_msgtype = n->nlmsg_type;
|
||||
lmsg->lm_index = dm->dm_index;
|
||||
|
||||
nl_dect_llme_msg_set_type(lmsg, type);
|
||||
nl_dect_llme_msg_set_op(lmsg, op);
|
||||
|
||||
if (1) {
|
||||
struct nlattr *nla[link->maxtype + 1];
|
||||
|
||||
err = nla_parse_nested(nla, link->maxtype, tb[DECTA_LLME_DATA],
|
||||
link->policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
err = link->parse(lmsg, nla);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)lmsg, pp);
|
||||
errout:
|
||||
nl_dect_llme_msg_put(lmsg);
|
||||
return err;
|
||||
}
|
||||
|
||||
/**
|
||||
* @name message creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int nl_dect_llme_build_msg(struct nl_msg *msg, struct nl_dect_llme_msg *lmsg,
|
||||
enum dect_llme_ops op)
|
||||
{
|
||||
const struct nl_dect_llme_link *link;
|
||||
struct nlattr *nest;
|
||||
struct dectmsg dm = {
|
||||
.dm_index = lmsg->lm_index,
|
||||
};
|
||||
|
||||
if (nlmsg_append(msg, &dm, sizeof(dm), NLMSG_ALIGNTO) < 0)
|
||||
goto nla_put_failure;
|
||||
NLA_PUT_U8(msg, DECTA_LLME_OP, op);
|
||||
NLA_PUT_U8(msg, DECTA_LLME_TYPE, lmsg->lm_type);
|
||||
|
||||
link = &nl_dect_llme_dispatch[lmsg->lm_type];
|
||||
nest = nla_nest_start(msg, DECTA_LLME_DATA);
|
||||
if (nest == NULL)
|
||||
goto nla_put_failure;
|
||||
if (link->build(msg, lmsg) < 0)
|
||||
goto nla_put_failure;
|
||||
nla_nest_end(msg, nest);
|
||||
|
||||
return 0;
|
||||
|
||||
nla_put_failure:
|
||||
return -NLE_MSGSIZE;
|
||||
}
|
||||
|
||||
static int build_llme_msg(struct nl_dect_llme_msg *tmpl, enum dect_llme_ops op,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if (!(msg = nlmsg_alloc_simple(DECT_LLME_MSG, 0)))
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if ((err = nl_dect_llme_build_msg(msg, tmpl, op)) < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_llme_build_request(struct nl_dect_llme_msg *tmpl,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_llme_msg(tmpl, DECT_LLME_REQUEST, result);
|
||||
}
|
||||
|
||||
int nl_dect_llme_request(struct nl_sock *sk, struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if ((err = nl_dect_llme_build_request(lmsg, &msg)) < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
int nl_dect_llme_build_response(struct nl_dect_llme_msg *tmpl,
|
||||
struct nl_msg **result)
|
||||
{
|
||||
return build_llme_msg(tmpl, DECT_LLME_RESPONSE, result);
|
||||
}
|
||||
|
||||
int nl_dect_llme_respond(struct nl_sock *sk, struct nl_dect_llme_msg *tmpl)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
if ((err = nl_dect_llme_build_response(tmpl, &msg)) < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_set_index(struct nl_dect_llme_msg *lmsg, int index)
|
||||
{
|
||||
lmsg->lm_index = index;
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_set_type(struct nl_dect_llme_msg *lmsg,
|
||||
enum dect_llme_msg_types type)
|
||||
{
|
||||
lmsg->lm_type = type;
|
||||
}
|
||||
|
||||
enum dect_llme_msg_types nl_dect_llme_msg_get_type(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return lmsg->lm_type;
|
||||
}
|
||||
|
||||
enum dect_llme_ops nl_dect_llme_msg_get_op(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
return lmsg->lm_op;
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_set_op(struct nl_dect_llme_msg *lmsg, enum dect_llme_ops op)
|
||||
{
|
||||
lmsg->lm_op = op;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Allocation/Freeing
|
||||
* @{
|
||||
*/
|
||||
|
||||
struct nl_dect_llme_msg *nl_dect_llme_msg_alloc(void)
|
||||
{
|
||||
return (struct nl_dect_llme_msg *)nl_object_alloc(&llme_msg_obj_ops);
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_get(struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
nl_object_get((struct nl_object *)lmsg);
|
||||
}
|
||||
|
||||
void nl_dect_llme_msg_put(struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
nl_object_put((struct nl_object *)lmsg);
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
static struct trans_tbl llme_types[] = {
|
||||
__ADD(DECT_LLME_SCAN, SCAN)
|
||||
__ADD(DECT_LLME_MAC_INFO, MAC_INFO)
|
||||
#if 0
|
||||
__ADD(DECT_LLME_MAC_CON, MAC_CON)
|
||||
#endif
|
||||
};
|
||||
|
||||
char *nl_dect_llme_msgtype2str(enum dect_llme_msg_types type, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(type, buf, len, llme_types, ARRAY_SIZE(llme_types));
|
||||
}
|
||||
|
||||
enum dect_llme_msg_types nl_dect_llme_str2msgtype(const char *str)
|
||||
{
|
||||
return __str2type(str, llme_types, ARRAY_SIZE(llme_types));
|
||||
}
|
||||
|
||||
static struct trans_tbl llme_ops[] = {
|
||||
__ADD(DECT_LLME_REQUEST, req)
|
||||
__ADD(DECT_LLME_INDICATE, ind)
|
||||
__ADD(DECT_LLME_RESPONSE, res)
|
||||
__ADD(DECT_LLME_CONFIRM, cfm)
|
||||
};
|
||||
|
||||
char *nl_dect_llme_op2str(enum dect_llme_ops op, char *buf, size_t len)
|
||||
{
|
||||
return __type2str(op, buf, len, llme_ops, ARRAY_SIZE(llme_ops));
|
||||
}
|
||||
|
||||
enum dect_llme_ops nl_dect_llme_str2op(const char *str)
|
||||
{
|
||||
return __str2type(str, llme_ops, ARRAY_SIZE(llme_ops));
|
||||
}
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_object_ops llme_msg_obj_ops = {
|
||||
.oo_name = "nl_dect/llme_msg",
|
||||
.oo_size = sizeof(struct nl_dect_llme_msg),
|
||||
.oo_dump = {
|
||||
[NL_DUMP_LINE] = llme_msg_dump,
|
||||
},
|
||||
};
|
||||
|
||||
static struct nl_cache_ops nl_dect_llme_msg_ops = {
|
||||
.co_name = "nl_dect/llme_msg",
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_msgtypes = {
|
||||
{ DECT_LLME_MSG, NL_ACT_NEW, "new" },
|
||||
END_OF_MSGTYPES_LIST,
|
||||
},
|
||||
.co_msg_parser = llme_msg_parser,
|
||||
.co_obj_ops = &llme_msg_obj_ops,
|
||||
};
|
||||
/** @endcond */
|
||||
|
||||
static void __init llme_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_llme_msg_ops);
|
||||
}
|
||||
|
||||
static void __exit llme_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_llme_msg_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,284 @@
|
|||
/*
|
||||
* lib/dect/transceiver.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>
|
||||
*/
|
||||
|
||||
/**
|
||||
* @ingroup dect
|
||||
* @defgroup dect Transceivers
|
||||
* @brief
|
||||
* @{
|
||||
*/
|
||||
|
||||
#include <netlink-local.h>
|
||||
#include <netlink/netlink.h>
|
||||
#include <netlink/utils.h>
|
||||
#include <netlink/dect/transceiver.h>
|
||||
|
||||
/** @cond SKIP */
|
||||
static struct nl_cache_ops nl_dect_transceiver_ops;
|
||||
/** @endcond */
|
||||
|
||||
#define DECTNAMSIZ 16
|
||||
|
||||
static struct nla_policy transceiver_policy[DECTA_TRANSCEIVER_MAX + 1] = {
|
||||
[DECTA_TRANSCEIVER_NAME] = { .type = NLA_STRING, .maxlen = DECTNAMSIZ },
|
||||
[DECTA_TRANSCEIVER_TYPE] = { .type = NLA_STRING },
|
||||
[DECTA_TRANSCEIVER_LINK] = { .type = NLA_U8 },
|
||||
[DECTA_TRANSCEIVER_STATS] = { .type = NLA_NESTED },
|
||||
[DECTA_TRANSCEIVER_BAND] = { .type = NLA_U8 },
|
||||
[DECTA_TRANSCEIVER_SLOTS] = { .type = NLA_NESTED },
|
||||
};
|
||||
|
||||
static struct nla_policy stats_policy[DECTA_TRANSCEIVER_STATS_MAX + 1] = {
|
||||
[DECTA_TRANSCEIVER_STATS_EVENT_BUSY] = { .type = NLA_U32 },
|
||||
[DECTA_TRANSCEIVER_STATS_EVENT_LATE] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static struct nla_policy slot_policy[DECTA_SLOT_MAX + 1] = {
|
||||
[DECTA_SLOT_NUM] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_STATE] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_CARRIER] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_FREQUENCY] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_RSSI] = { .type = NLA_U8 },
|
||||
[DECTA_SLOT_RX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_RX_PACKETS] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_TX_BYTES] = { .type = NLA_U32 },
|
||||
[DECTA_SLOT_TX_PACKETS] = { .type = NLA_U32 },
|
||||
};
|
||||
|
||||
static int slot_parser(struct nl_dect_transceiver *trx, struct nlattr *nla)
|
||||
{
|
||||
struct nlattr *tb[DECTA_SLOT_MAX + 1];
|
||||
struct nl_dect_transceiver_slot *dts;
|
||||
uint8_t slot;
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_SLOT_MAX, nla, slot_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_SLOT_NUM] == NULL)
|
||||
return -NLE_INVAL;
|
||||
slot = nla_get_u8(tb[DECTA_SLOT_NUM]);
|
||||
dts = &trx->trx_slots[slot];
|
||||
|
||||
dts->dts_valid = 1;
|
||||
if (tb[DECTA_SLOT_STATE] != NULL)
|
||||
dts->dts_state = nla_get_u8(tb[DECTA_SLOT_STATE]);
|
||||
if (tb[DECTA_SLOT_CARRIER] != NULL)
|
||||
dts->dts_carrier = nla_get_u8(tb[DECTA_SLOT_CARRIER]);
|
||||
if (tb[DECTA_SLOT_FREQUENCY] != NULL)
|
||||
dts->dts_frequency = nla_get_u32(tb[DECTA_SLOT_FREQUENCY]);
|
||||
if (tb[DECTA_SLOT_RSSI] != NULL)
|
||||
dts->dts_rssi = nla_get_u8(tb[DECTA_SLOT_RSSI]);
|
||||
if (tb[DECTA_SLOT_RX_BYTES] != NULL)
|
||||
dts->dts_rx_bytes = nla_get_u32(tb[DECTA_SLOT_RX_BYTES]);
|
||||
if (tb[DECTA_SLOT_RX_PACKETS] != NULL)
|
||||
dts->dts_rx_packets = nla_get_u32(tb[DECTA_SLOT_RX_PACKETS]);
|
||||
if (tb[DECTA_SLOT_TX_BYTES] != NULL)
|
||||
dts->dts_tx_bytes = nla_get_u32(tb[DECTA_SLOT_TX_BYTES]);
|
||||
if (tb[DECTA_SLOT_TX_PACKETS] != NULL)
|
||||
dts->dts_tx_packets = nla_get_u32(tb[DECTA_SLOT_TX_PACKETS]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int stats_parser(struct nl_dect_transceiver *trx, struct nlattr *nla)
|
||||
{
|
||||
struct nlattr *tb[DECTA_TRANSCEIVER_STATS_MAX + 1];
|
||||
struct nl_dect_transceiver_stats *stats = &trx->trx_stats;
|
||||
int err;
|
||||
|
||||
err = nla_parse_nested(tb, DECTA_TRANSCEIVER_STATS_MAX, nla, stats_policy);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_STATS_EVENT_BUSY] != NULL)
|
||||
stats->trx_event_busy =
|
||||
nla_get_u32(tb[DECTA_TRANSCEIVER_STATS_EVENT_BUSY]);
|
||||
if (tb[DECTA_TRANSCEIVER_STATS_EVENT_LATE] != NULL)
|
||||
stats->trx_event_late =
|
||||
nla_get_u32(tb[DECTA_TRANSCEIVER_STATS_EVENT_LATE]);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int transceiver_msg_parser(struct nl_cache_ops *ops,
|
||||
struct sockaddr_nl *who,
|
||||
struct nlmsghdr *n,
|
||||
struct nl_parser_param *pp)
|
||||
{
|
||||
struct nlattr *tb[DECTA_TRANSCEIVER_MAX + 1], *nla;
|
||||
struct nl_dect_transceiver *trx;
|
||||
int err;
|
||||
|
||||
trx = nl_dect_transceiver_alloc();
|
||||
if (trx == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
|
||||
trx->ce_msgtype = n->nlmsg_type;
|
||||
|
||||
err = nlmsg_parse(n, sizeof(struct dectmsg), tb, DECTA_TRANSCEIVER_MAX,
|
||||
transceiver_policy);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_NAME] != NULL) {
|
||||
char name[DECTNAMSIZ];
|
||||
nla_strlcpy(name, tb[DECTA_TRANSCEIVER_NAME], sizeof(name));
|
||||
nl_dect_transceiver_set_name(trx, name);
|
||||
}
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_TYPE] != NULL) {
|
||||
char *type = nla_strdup(tb[DECTA_TRANSCEIVER_TYPE]);
|
||||
if (type == NULL) {
|
||||
err = -NLE_NOMEM;
|
||||
goto errout;
|
||||
}
|
||||
nl_dect_transceiver_set_type(trx, type);
|
||||
free(type);
|
||||
}
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_LINK] != NULL)
|
||||
nl_dect_transceiver_set_link(trx, nla_get_u8(tb[DECTA_TRANSCEIVER_LINK]));
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_STATS] != NULL) {
|
||||
err = stats_parser(trx, tb[DECTA_TRANSCEIVER_STATS]);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_BAND] != NULL)
|
||||
nl_dect_transceiver_set_band(trx, nla_get_u8(tb[DECTA_TRANSCEIVER_BAND]));
|
||||
|
||||
if (tb[DECTA_TRANSCEIVER_SLOTS] != NULL) {
|
||||
int rem;
|
||||
nla_for_each_nested(nla, tb[DECTA_TRANSCEIVER_SLOTS], rem) {
|
||||
if (nla_type(nla) != DECTA_LIST_ELEM)
|
||||
continue;
|
||||
err = slot_parser(trx, nla);
|
||||
if (err < 0)
|
||||
goto errout;
|
||||
}
|
||||
}
|
||||
|
||||
err = pp->pp_cb((struct nl_object *)trx, pp);
|
||||
errout:
|
||||
nl_dect_transceiver_put(trx);
|
||||
return err;
|
||||
}
|
||||
|
||||
static int transceiver_request_update(struct nl_cache *c, struct nl_sock *h)
|
||||
{
|
||||
struct dectmsg dm;
|
||||
|
||||
memset(&dm, 0, sizeof(dm));
|
||||
return nl_send_simple(h, DECT_GET_TRANSCEIVER, NLM_F_DUMP,
|
||||
&dm, sizeof(dm));
|
||||
}
|
||||
|
||||
/**
|
||||
* @name Cache Management
|
||||
* @{
|
||||
*/
|
||||
int nl_dect_transceiver_alloc_cache(struct nl_sock *sk, struct nl_cache **result)
|
||||
{
|
||||
struct nl_cache *cache;
|
||||
int err;
|
||||
|
||||
cache = nl_cache_alloc(&nl_dect_transceiver_ops);
|
||||
if (cache == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
if (sk && (err = nl_cache_refill(sk, cache)) < 0) {
|
||||
free(cache);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = cache;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/**
|
||||
* @name Transceiver creation
|
||||
* @{
|
||||
*/
|
||||
|
||||
static int build_transceiver_msg(struct nl_dect_transceiver *tmpl, int cmd,
|
||||
int flags, struct nl_msg **result)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
msg = nlmsg_alloc_simple(cmd, flags);
|
||||
if (msg == NULL)
|
||||
return -NLE_NOMEM;
|
||||
|
||||
err = nl_dect_transceiver_build_msg(msg, tmpl);
|
||||
if (err < 0) {
|
||||
nlmsg_free(msg);
|
||||
return err;
|
||||
}
|
||||
|
||||
*result = msg;
|
||||
return 0;
|
||||
}
|
||||
|
||||
int nl_dect_transceiver_build_change_request(struct nl_dect_transceiver *tmpl,
|
||||
int flags, struct nl_msg **result)
|
||||
{
|
||||
return build_transceiver_msg(tmpl, DECT_NEW_TRANSCEIVER, flags, result);
|
||||
}
|
||||
|
||||
int nl_dect_transceiver_change(struct nl_sock *sk, struct nl_dect_transceiver *trx,
|
||||
int flags)
|
||||
{
|
||||
struct nl_msg *msg;
|
||||
int err;
|
||||
|
||||
err = nl_dect_transceiver_build_change_request(trx, flags, &msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
err = nl_send_auto_complete(sk, msg);
|
||||
nlmsg_free(msg);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
return wait_for_ack(sk);
|
||||
}
|
||||
|
||||
static struct nl_cache_ops nl_dect_transceiver_ops = {
|
||||
.co_name = "nl_dect/transceiver",
|
||||
.co_hdrsize = 0,
|
||||
.co_msgtypes = {
|
||||
{ DECT_NEW_TRANSCEIVER, NL_ACT_NEW, "new" },
|
||||
{ DECT_GET_TRANSCEIVER, NL_ACT_GET, "get" },
|
||||
END_OF_MSGTYPES_LIST
|
||||
},
|
||||
.co_protocol = NETLINK_DECT,
|
||||
.co_request_update = transceiver_request_update,
|
||||
.co_msg_parser = transceiver_msg_parser,
|
||||
.co_obj_ops = &nl_dect_transceiver_obj_ops,
|
||||
};
|
||||
|
||||
static void __init transceiver_init(void)
|
||||
{
|
||||
nl_cache_mngt_register(&nl_dect_transceiver_ops);
|
||||
}
|
||||
|
||||
static void __exit transceiver_exit(void)
|
||||
{
|
||||
nl_cache_mngt_unregister(&nl_dect_transceiver_ops);
|
||||
}
|
||||
|
||||
/** @} */
|
|
@ -0,0 +1,252 @@
|
|||
/*
|
||||
* 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-local.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_INDEX 0x0004
|
||||
#define TRANSCEIVER_ATTR_LINK 0x0008
|
||||
#define TRANSCEIVER_ATTR_BAND 0x0010
|
||||
/** @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)
|
||||
{
|
||||
char buf[64];
|
||||
|
||||
nl_dump(p, "\tslot %u: <%s> carrier: %u (%u.%3u MHz)", n,
|
||||
nl_dect_slot_state2str(dts->dts_state, buf, sizeof(buf)),
|
||||
dts->dts_carrier,
|
||||
dts->dts_frequency / 1000, dts->dts_frequency % 1000);
|
||||
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\n",
|
||||
dts->dts_rx_bytes, dts->dts_rx_packets);
|
||||
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);
|
||||
|
||||
nl_dump(p, "\tEvents: busy: %u late: %u\n",
|
||||
stats->trx_event_busy, stats->trx_event_late);
|
||||
nl_dump(p, "\tRF-band: %u\n", trx->trx_band);
|
||||
|
||||
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_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;
|
||||
}
|
||||
|
||||
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)
|
||||
};
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
|
||||
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 */
|
||||
|
||||
/** @} */
|
|
@ -29,3 +29,12 @@ nl-rule-list
|
|||
nl-tctree-list
|
||||
nl-util-addr
|
||||
nf-queue
|
||||
dect-transceiver-list
|
||||
dect-transceiver-bind
|
||||
dect-cell-add
|
||||
dect-cell-delete
|
||||
dect-cell-list
|
||||
dect-cluster-add
|
||||
dect-cluster-delete
|
||||
dect-cluster-list
|
||||
dect-llme-scan
|
||||
|
|
|
@ -14,7 +14,7 @@ ifeq ($(shell [ ! -r ../Makefile.opts ] && echo 1),)
|
|||
endif
|
||||
|
||||
LDFLAGS += -L../lib -lnl
|
||||
CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) $(wildcard nf-*.c)
|
||||
CIN := $(wildcard nl-*.c) $(wildcard genl-*.c) $(wildcard nf-*.c) $(wildcard dect-*.c)
|
||||
TOOLS := $(CIN:%.c=%)
|
||||
|
||||
all: $(TOOLS)
|
||||
|
@ -50,6 +50,10 @@ nf-%: nf-%.o
|
|||
@echo " LD $@"; \
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lnl-nf -lnl-route
|
||||
|
||||
dect-%: dect-%.c
|
||||
@echo " LD $@"; \
|
||||
$(CC) $(CFLAGS) -o $@ $^ $(LDFLAGS) -lnl-dect
|
||||
|
||||
clean:
|
||||
@echo " CLEAN src"; \
|
||||
rm -f $(TOOLS) *.o
|
||||
|
|
|
@ -0,0 +1,67 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_dect_cell *cell;
|
||||
struct nl_cache *cluster_cache;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
uint8_t cli;
|
||||
int err;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
|
||||
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cluster_cache);
|
||||
|
||||
cell = nl_dect_cell_alloc();
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
enum {
|
||||
ARG_NAME = 256,
|
||||
ARG_FLAGS,
|
||||
ARG_CLUSTER,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{ "name", 1, 0, ARG_NAME },
|
||||
{ "flags", 1, 0, ARG_FLAGS },
|
||||
{ "cluster", 1, 0, ARG_CLUSTER },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v': nlt_print_version(); break;
|
||||
case ARG_NAME:
|
||||
nl_dect_cell_set_name(cell, optarg);
|
||||
break;
|
||||
case ARG_FLAGS:
|
||||
nl_dect_cell_set_flags(cell, nl_dect_cell_str2flags(optarg));
|
||||
break;
|
||||
case ARG_CLUSTER:
|
||||
if (isdigit(*optarg))
|
||||
cli = strtoul(optarg, NULL, 0);
|
||||
else
|
||||
cli = nl_dect_cluster_name2i(cluster_cache, optarg);
|
||||
nl_dect_cell_set_link(cell, cli);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err = nl_dect_cell_add(sock, cell, 0);
|
||||
if (err < 0)
|
||||
fatal(err, "Unable to add cell: %s", nl_geterror(err));
|
||||
|
||||
printf("Added: ");
|
||||
nl_object_dump(OBJ_CAST(cell), ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,59 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_dect_cell *cell;
|
||||
struct nl_cache *cluster_cache;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
int err;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
|
||||
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cluster_cache);
|
||||
|
||||
cell = nl_dect_cell_alloc();
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
enum {
|
||||
ARG_CELL = 257,
|
||||
ARG_CLUSTER,
|
||||
ARG_TRANSCEIVER,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{ "cell", 1, 0, ARG_CELL },
|
||||
{ "cluster", 1, 0, ARG_CLUSTER },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v': nlt_print_version(); break;
|
||||
case ARG_CELL:
|
||||
nl_dect_cell_set_name(cell, optarg);
|
||||
break;
|
||||
case ARG_CLUSTER:
|
||||
nl_dect_cell_set_link(cell,
|
||||
nl_dect_cluster_name2i(cluster_cache, optarg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err = nl_dect_cell_delete(sock, cell, 0);
|
||||
if (err < 0)
|
||||
fatal(err, "Unable to delete cell: %s", nl_geterror(err));
|
||||
|
||||
printf("Deleted: ");
|
||||
nl_object_dump(OBJ_CAST(cell), ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,24 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_cache *cell_cache;
|
||||
struct nl_cache *cluster_cache;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cluster_cache);
|
||||
if (nl_dect_cell_alloc_cache(sock, &cell_cache))
|
||||
exit(1);
|
||||
|
||||
nl_cache_dump(cell_cache, ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_dect_cluster *cl;
|
||||
struct nl_dect_ari *pari;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
int err;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
cl = nl_dect_cluster_alloc();
|
||||
pari = (void *)nl_dect_cluster_get_pari(cl);
|
||||
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
enum {
|
||||
ARG_NAME = 257,
|
||||
ARG_MODE,
|
||||
ARG_EMC,
|
||||
ARG_FPN,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{ "name", 1, 0, ARG_NAME },
|
||||
{ "mode", 1, 0, ARG_MODE },
|
||||
{ "emc", 1, 0, ARG_EMC },
|
||||
{ "fpn", 1, 0, ARG_FPN },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v': nlt_print_version(); break;
|
||||
case ARG_NAME:
|
||||
nl_dect_cluster_set_name(cl, strdup(optarg));
|
||||
break;
|
||||
case ARG_MODE:
|
||||
nl_dect_cluster_set_mode(cl, nl_dect_cluster_str2mode(optarg));
|
||||
break;
|
||||
case ARG_EMC:
|
||||
nl_dect_ari_set_emc(pari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
case ARG_FPN:
|
||||
nl_dect_ari_set_fpn(pari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nl_dect_cluster_set_pari(cl, pari);
|
||||
err = nl_dect_cluster_add(sock, cl, 0);
|
||||
if (err < 0)
|
||||
fatal(err, "Unable to add cluster: %s", nl_geterror(err));
|
||||
|
||||
printf("Added: ");
|
||||
nl_object_dump(OBJ_CAST(cl), ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_dect_cluster *cl;
|
||||
struct nl_dect_ari *pari;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
int err;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
cl = nl_dect_cluster_alloc();
|
||||
pari = (void *)nl_dect_cluster_get_pari(cl);
|
||||
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
enum {
|
||||
ARG_NAME = 257,
|
||||
ARG_MODE,
|
||||
ARG_EMC,
|
||||
ARG_FPN,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{ "name", 1, 0, ARG_NAME },
|
||||
{ "mode", 1, 0, ARG_MODE },
|
||||
{ "emc", 1, 0, ARG_EMC },
|
||||
{ "fpn", 1, 0, ARG_FPN },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v': nlt_print_version(); break;
|
||||
case ARG_NAME:
|
||||
nl_dect_cluster_set_name(cl, strdup(optarg));
|
||||
break;
|
||||
case ARG_MODE:
|
||||
nl_dect_cluster_set_mode(cl, atoi(optarg));
|
||||
break;
|
||||
case ARG_EMC:
|
||||
nl_dect_ari_set_emc(pari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
case ARG_FPN:
|
||||
nl_dect_ari_set_fpn(pari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err = nl_dect_cluster_delete(sock, cl, 0);
|
||||
if (err < 0)
|
||||
fatal(err, "Unable to delete cluster: %s", nl_geterror(err));
|
||||
|
||||
printf("Deleted: ");
|
||||
nl_object_dump(OBJ_CAST(cl), ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_cache *cluster_cache;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
|
||||
exit(1);
|
||||
|
||||
nl_cache_dump(cluster_cache, ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,111 @@
|
|||
#if 0
|
||||
#include "utils.h"
|
||||
|
||||
static void obj_input(struct nl_object *obj, void *arg)
|
||||
{
|
||||
struct nl_dump_params dp = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
|
||||
printf("MAC Connection: ");
|
||||
nl_object_dump(obj, &dp);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int event_input(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
if (nl_msg_parse(msg, &obj_input, NULL) < 0)
|
||||
fprintf(stderr, "Unknown message type\n");
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_cache *cluster_cache;
|
||||
struct dect_llme_msg *lmsg;
|
||||
struct dect_ari *ari;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
int index;
|
||||
int err;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
if (dect_cluster_alloc_cache(sock, &cluster_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cluster_cache);
|
||||
|
||||
lmsg = dect_llme_msg_alloc();
|
||||
dect_llme_msg_set_type(lmsg, DECT_LLME_MAC_CON);
|
||||
|
||||
ari = (void *)dect_llme_mac_con_get_ari(lmsg);
|
||||
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
enum {
|
||||
ARG_CLUSTER = 257,
|
||||
ARG_MCEI,
|
||||
ARG_PMID,
|
||||
ARG_EMC,
|
||||
ARG_FPN,
|
||||
ARG_FPC,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{ "cluster", 1, 0, ARG_CLUSTER },
|
||||
{ "mcei", 1, 0, ARG_MCEI },
|
||||
{ "pmid", 1, 0, ARG_PMID },
|
||||
{ "emc", 1, 0, ARG_EMC },
|
||||
{ "fpn", 1, 0, ARG_FPN },
|
||||
{ "fpc", 0, 0, ARG_FPC },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v': nlt_print_version(); break;
|
||||
case ARG_CLUSTER:
|
||||
index = dect_cluster_name2i(cluster_cache, optarg);
|
||||
dect_llme_msg_set_index(lmsg, index);
|
||||
break;
|
||||
case ARG_MCEI:
|
||||
dect_llme_mac_con_set_mcei(lmsg, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
case ARG_PMID:
|
||||
dect_llme_mac_con_set_pmid(lmsg, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
case ARG_EMC:
|
||||
dect_ari_set_emc(ari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
case ARG_FPN:
|
||||
dect_ari_set_fpn(ari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
case ARG_FPC:
|
||||
dect_llme_mac_info_set_fpc(lmsg, 0);
|
||||
dect_llme_mac_info_set_ehlc(lmsg, 0);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//dect_llme_mac_con_set_ari(lmsg, ari);
|
||||
if ((err = dect_llme_request(sock, lmsg)) < 0)
|
||||
fatal(err, "Unable to send request: %s", nl_geterror(err));
|
||||
|
||||
printf("Requested: ");
|
||||
nl_object_dump(OBJ_CAST(lmsg), ¶ms);
|
||||
|
||||
nl_socket_add_membership(sock, DECTNLGRP_LLME);
|
||||
nl_socket_disable_seq_check(sock);
|
||||
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
|
||||
while (1)
|
||||
nl_recvmsgs_default(sock);
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
int main() {}
|
|
@ -0,0 +1,37 @@
|
|||
#include "utils.h"
|
||||
|
||||
static void obj_input(struct nl_object *obj, void *arg)
|
||||
{
|
||||
struct nl_dump_params dp = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
nl_object_dump(obj, &dp);
|
||||
}
|
||||
|
||||
static int event_input(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
if (nl_msg_parse(msg, &obj_input, NULL) < 0)
|
||||
fprintf(stderr, "Unknown message type\n");
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_cache *cluster_cache;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cluster_cache);
|
||||
|
||||
nl_socket_add_membership(sock, DECTNLGRP_LLME);
|
||||
nl_socket_disable_seq_check(sock);
|
||||
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
|
||||
while (1)
|
||||
nl_recvmsgs_default(sock);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,139 @@
|
|||
#include "utils.h"
|
||||
|
||||
#define CACHE_SIZE 64
|
||||
|
||||
static struct {
|
||||
unsigned int index;
|
||||
unsigned int used;
|
||||
struct {
|
||||
uint16_t emc;
|
||||
uint32_t fpn;
|
||||
uint8_t rpn;
|
||||
} ids[CACHE_SIZE];
|
||||
} cache;
|
||||
|
||||
static void add_ari(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
const struct nl_dect_ari *ari = nl_dect_llme_mac_info_get_pari(lmsg);
|
||||
unsigned int index = cache.index;
|
||||
|
||||
cache.ids[index].emc = nl_dect_ari_get_emc(ari);
|
||||
cache.ids[index].fpn = nl_dect_ari_get_fpn(ari);
|
||||
cache.ids[index].rpn = nl_dect_llme_mac_info_get_rpn(lmsg);
|
||||
|
||||
if (++cache.used > CACHE_SIZE)
|
||||
cache.used = CACHE_SIZE;
|
||||
if (++cache.index == CACHE_SIZE)
|
||||
cache.index = 0;
|
||||
}
|
||||
|
||||
static bool lookup_ari(const struct nl_dect_llme_msg *lmsg)
|
||||
{
|
||||
const struct nl_dect_ari *ari = nl_dect_llme_mac_info_get_pari(lmsg);
|
||||
unsigned int index;
|
||||
|
||||
for (index = 0; index < cache.used; index++) {
|
||||
if (cache.ids[index].emc == nl_dect_ari_get_emc(ari) &&
|
||||
cache.ids[index].fpn == nl_dect_ari_get_fpn(ari) &&
|
||||
cache.ids[index].rpn == nl_dect_llme_mac_info_get_rpn(lmsg))
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
static void obj_input(struct nl_object *obj, void *arg)
|
||||
{
|
||||
struct nl_dect_llme_msg *lmsg = nl_object_priv(obj);
|
||||
struct nl_dump_params dp = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
static unsigned int n;
|
||||
|
||||
if (lookup_ari(lmsg))
|
||||
return;
|
||||
add_ari(lmsg);
|
||||
|
||||
printf("%u: Station: ", ++n);
|
||||
nl_object_dump(obj, &dp);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
static int event_input(struct nl_msg *msg, void *arg)
|
||||
{
|
||||
if (nl_msg_parse(msg, &obj_input, NULL) < 0)
|
||||
fprintf(stderr, "Unknown message type\n");
|
||||
return NL_STOP;
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_cache *cluster_cache;
|
||||
struct nl_dect_llme_msg *lmsg;
|
||||
struct nl_dect_ari *pari;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
int index;
|
||||
int err;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
if (nl_dect_cluster_alloc_cache(sock, &cluster_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cluster_cache);
|
||||
|
||||
lmsg = nl_dect_llme_msg_alloc();
|
||||
nl_dect_llme_msg_set_type(lmsg, DECT_LLME_SCAN);
|
||||
|
||||
pari = (void *)nl_dect_llme_mac_info_get_pari(lmsg);
|
||||
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
enum {
|
||||
ARG_CLUSTER = 257,
|
||||
ARG_EMC,
|
||||
ARG_FPN,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{ "cluster", 1, 0, ARG_CLUSTER },
|
||||
{ "emc", 1, 0, ARG_EMC },
|
||||
{ "fpn", 1, 0, ARG_FPN },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v': nlt_print_version(); break;
|
||||
case ARG_CLUSTER:
|
||||
index = nl_dect_cluster_name2i(cluster_cache, optarg);
|
||||
nl_dect_llme_msg_set_index(lmsg, index);
|
||||
break;
|
||||
case ARG_EMC:
|
||||
nl_dect_ari_set_emc(pari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
case ARG_FPN:
|
||||
nl_dect_ari_set_fpn(pari, strtoul(optarg, NULL, 16));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//nl_dect_llme_mac_info_set_pari(lmsg, pari);
|
||||
if ((err = nl_dect_llme_request(sock, lmsg)) < 0)
|
||||
fatal(err, "Unable to send request: %s", nl_geterror(err));
|
||||
|
||||
printf("Requested: ");
|
||||
nl_object_dump(OBJ_CAST(lmsg), ¶ms);
|
||||
|
||||
nl_socket_disable_seq_check(sock);
|
||||
nl_socket_modify_cb(sock, NL_CB_VALID, NL_CB_CUSTOM, event_input, NULL);
|
||||
while (1)
|
||||
nl_recvmsgs_default(sock);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,57 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_dect_transceiver *trx;
|
||||
struct nl_cache *cell_cache;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
int err;
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
|
||||
if (nl_dect_cell_alloc_cache(sock, &cell_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cell_cache);
|
||||
|
||||
trx = nl_dect_transceiver_alloc();
|
||||
for (;;) {
|
||||
int c, optidx = 0;
|
||||
enum {
|
||||
ARG_TRANSCEIVER = 257,
|
||||
ARG_CELL,
|
||||
};
|
||||
static struct option long_opts[] = {
|
||||
{ "transceiver", 1, 0, ARG_TRANSCEIVER },
|
||||
{ "cell", 1, 0, ARG_CELL },
|
||||
{ 0, 0, 0, 0 }
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "qhvd:n:t:", long_opts, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
|
||||
switch (c) {
|
||||
case 'v': nlt_print_version(); break;
|
||||
case ARG_TRANSCEIVER:
|
||||
nl_dect_transceiver_set_name(trx, strdup(optarg));
|
||||
break;
|
||||
case ARG_CELL:
|
||||
nl_dect_transceiver_set_link(trx, nl_dect_cell_name2i(cell_cache, optarg));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
err = nl_dect_transceiver_change(sock, trx, 0);
|
||||
if (err < 0)
|
||||
fatal(err, "Unable to bind cell: %s", nl_geterror(err));
|
||||
|
||||
printf("Bound: ");
|
||||
nl_object_dump(OBJ_CAST(trx), ¶ms);
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -0,0 +1,60 @@
|
|||
#include "utils.h"
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
struct nl_sock *sock;
|
||||
struct nl_cache *cell_cache;
|
||||
struct nl_cache *transceiver_cache;
|
||||
struct nl_dect_transceiver *trx;
|
||||
struct nl_dump_params params = {
|
||||
.dp_type = NL_DUMP_LINE,
|
||||
.dp_fd = stdout,
|
||||
};
|
||||
|
||||
sock = nlt_alloc_socket();
|
||||
nlt_connect(sock, NETLINK_DECT);
|
||||
|
||||
if (nl_dect_cell_alloc_cache(sock, &cell_cache))
|
||||
exit(1);
|
||||
nl_cache_mngt_provide(cell_cache);
|
||||
|
||||
if (nl_dect_transceiver_alloc_cache(sock, &transceiver_cache))
|
||||
exit(1);
|
||||
trx = nl_dect_transceiver_alloc();
|
||||
if (trx == NULL)
|
||||
exit(1);
|
||||
|
||||
for (;;) {
|
||||
int c, optidx = 0, cidx;
|
||||
enum {
|
||||
ARG_NAME = 257,
|
||||
ARG_CELL,
|
||||
};
|
||||
static struct option long_ops[] = {
|
||||
{ "name", 1, 0, ARG_NAME },
|
||||
{ "cell", 1, 0, ARG_CELL },
|
||||
{}
|
||||
};
|
||||
|
||||
c = getopt_long(argc, argv, "n:c:", long_ops, &optidx);
|
||||
if (c == -1)
|
||||
break;
|
||||
switch (c) {
|
||||
case ARG_NAME:
|
||||
nl_dect_transceiver_set_name(trx, optarg);
|
||||
break;
|
||||
case ARG_CELL:
|
||||
cidx = nl_dect_cell_name2i(cell_cache, optarg);
|
||||
if (cidx == 0) {
|
||||
fprintf(stderr, "cell %s does not exist\n", optarg);
|
||||
exit(1);
|
||||
}
|
||||
nl_dect_transceiver_set_link(trx, cidx);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
nl_cache_dump_filter(transceiver_cache, ¶ms, OBJ_CAST(trx));
|
||||
return 0;
|
||||
}
|
||||
|
|
@ -20,6 +20,7 @@
|
|||
#include <stdint.h>
|
||||
#include <ctype.h>
|
||||
#include <getopt.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
|
||||
|
@ -42,6 +43,11 @@
|
|||
#include <netlink/genl/ctrl.h>
|
||||
#include <netlink/genl/mngt.h>
|
||||
#include <netlink/netfilter/ct.h>
|
||||
#include <netlink/dect/transceiver.h>
|
||||
#include <netlink/dect/cell.h>
|
||||
#include <netlink/dect/cluster.h>
|
||||
#include <netlink/dect/llme.h>
|
||||
#include <netlink/dect/ari.h>
|
||||
|
||||
extern uint32_t parse_u32(const char *);
|
||||
|
||||
|
|
Reference in New Issue