dect
/
libdect
Archived
13
0
Fork 0

libdect: add ConnetionLess Message Service (CLMS) support

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2010-08-13 00:03:56 +02:00
parent f04852105c
commit 77f31308d8
17 changed files with 490 additions and 11 deletions

View File

@ -584,6 +584,7 @@ INPUT = src/libdect.c \
src/mm.c \
src/cc.c \
src/ss.c \
src/clms.c \
src \
include/dect

1
example/.gitignore vendored
View File

@ -1,5 +1,6 @@
cc
ss
clms
mm-fp
mm-pp
discover

View File

@ -1,6 +1,6 @@
CFLAGS += $(EVENT_CFLAGS)
LDFLAGS += -Wl,-rpath $(PWD)/src -Lsrc -ldect $(EVENT_LDFLAGS)
PROGRAMS += cc ss mm-fp discover hijack
PROGRAMS += cc ss clms mm-fp discover hijack
PROGRAMS += pp-access-rights pp-access-rights-terminate pp-location-update
PROGRAMS += pp-detach pp-info-request pp-list-access pp-wait-page
@ -19,6 +19,10 @@ ss-destdir := $(destdir)
ss-obj += $(common-obj)
ss-obj += ss.o
clms-destdir := $(destdir)
clms-obj += $(common-obj)
clms-obj += clms.o
mm-fp-destdir := $(destdir)
mm-fp-obj += $(common-obj)
mm-fp-obj += mm-fp.o

81
example/clms.c Normal file
View File

@ -0,0 +1,81 @@
/*
* DECT FP CLMS example
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
#include <stdio.h>
#include <dect/libdect.h>
#include "common.h"
static const char *name = "- FP 1 -";
#define debug(fmt, args...) printf("IWU: " fmt, ## args);
static void dect_invoke_clms(struct dect_handle *dh)
{
DECT_DEFINE_MSG_BUF_ONSTACK(_mb), *mb = &_mb;
struct dect_ie_network_parameter network_parameter;
network_parameter.discriminator = DECT_NETWORK_PARAMETER_DEVICE_NAME;
network_parameter.len = strlen(name);
memcpy(network_parameter.data, name, network_parameter.len);
debug("build CLMS message\n");
if (dect_build_sfmt_ie(dh, DECT_IE_NETWORK_PARAMETER, mb,
&network_parameter.common) < 0)
return;
dect_mncl_unitdata_req(dh, DECT_CLMS_FIXED, NULL, mb);
}
static void dect_mncl_unitdata_ind(struct dect_handle *dh,
enum dect_clms_message_types type,
struct dect_mncl_unitdata_param *param,
struct dect_msg_buf *mb)
{
struct dect_ie_network_parameter *network_parameter;
struct dect_ie_common *dst;
struct dect_sfmt_ie ie;
debug("parse CLMS message\n");
if (dect_parse_sfmt_ie_header(&ie, mb) < 0)
return;
if (ie.id != DECT_IE_NETWORK_PARAMETER)
return;
if (dect_parse_sfmt_ie(dh, 0, &dst, &ie) < 0)
return;
network_parameter = dect_ie_container(network_parameter, dst);
debug("FP-Name: '%.*s'\n",
network_parameter->len, network_parameter->data);
dect_ie_put(dh, network_parameter);
dect_event_loop_stop();
}
static struct dect_clms_ops clms_ops = {
.mncl_unitdata_ind = dect_mncl_unitdata_ind,
};
static struct dect_ops ops = {
.clms_ops = &clms_ops,
};
int main(int argc, char **argv)
{
dect_common_init(&ops, argv[1]);
if (dh->mode == DECT_MODE_FP)
dect_invoke_clms(dh);
else
dect_event_loop();
dect_common_cleanup(dh);
return 0;
}

View File

@ -27,6 +27,7 @@ static const char * const debug_colors[] = {
[DECT_DEBUG_LCE] = LIGHT_BLUE,
[DECT_DEBUG_CC] = YELLOW,
[DECT_DEBUG_SS] = LIGHT_CYAN,
[DECT_DEBUG_CLMS] = LIGHT_RED,
[DECT_DEBUG_MM] = YELLOW,
[DECT_DEBUG_SFMT] = LIGHT_GREEN,
[DECT_DEBUG_NL] = LIGHT_PURPLE,

View File

@ -296,6 +296,19 @@ static void mnss_release_ind(struct dect_handle *dh, struct dect_ss_endpoint *ss
static struct dect_ss_ops dummy_ss_ops;
/*
* CLMS Ops
*/
static void mncl_unitdata_ind(struct dect_handle *dh,
enum dect_clms_message_types type,
struct dect_mncl_unitdata_param *param,
struct dect_msg_buf *mb)
{
}
static struct dect_clms_ops dummy_clms_ops;
void dect_dummy_ops_init(struct dect_ops *ops)
{
struct dect_llme_ops_ *llme_ops;
@ -303,6 +316,7 @@ void dect_dummy_ops_init(struct dect_ops *ops)
struct dect_cc_ops *cc_ops;
struct dect_mm_ops *mm_ops;
struct dect_ss_ops *ss_ops;
struct dect_clms_ops *clms_ops;
if (!ops->llme_ops)
ops->llme_ops = &dummy_llme_ops;
@ -416,4 +430,11 @@ void dect_dummy_ops_init(struct dect_ops *ops)
ss_ops->mnss_facility_ind = mnss_facility_ind;
if (!ss_ops->mnss_release_ind)
ss_ops->mnss_release_ind = mnss_release_ind;
if (!ops->clms_ops)
ops->clms_ops = &dummy_clms_ops;
clms_ops = (void *)ops->clms_ops;
if (!clms_ops->mncl_unitdata_ind)
clms_ops->mncl_unitdata_ind = mncl_unitdata_ind;
}

73
include/clms.h Normal file
View File

@ -0,0 +1,73 @@
/*
* DECT Connectionless Message Service (CLMS)
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*/
#ifndef _LIBDECT_CLMS_H
#define _LIBDECT_CLMS_H
#include <dect/ie.h>
enum dect_clms_msg_types {
CLMS_VARIABLE = 0x1,
};
struct dect_clms_variable_msg {
struct dect_msg_common common;
struct dect_ie_portable_identity *portable_identity;
struct dect_ie_mms_generic_header *mms_generic_header;
struct dect_ie_mms_object_header *mms_object_header;
struct dect_ie_list mms_extended_header;
struct dect_ie_list time_data;
struct dect_ie_list calling_party_number;
struct dect_ie_calling_party_name *calling_party_name;
struct dect_ie_list called_party_number;
struct dect_ie_called_party_subaddr *called_party_subaddr;
struct dect_ie_segmented_info *segmented_info;
struct dect_ie_alphanumeric *alphanumeric;
struct dect_ie_iwu_to_iwu *iwu_to_iwu;
struct dect_ie_iwu_packet *iwu_packet;
struct dect_ie_escape_to_proprietary *escape_to_proprietary;
};
struct dect_clms_fixed_addr_section {
uint8_t hdr;
uint16_t addr;
uint8_t pd;
uint8_t li;
} __packed;
#define DECT_CLMS_DATA_SIZE 4U
struct dect_clms_fixed_data_section {
uint8_t hdr;
uint8_t data[DECT_CLMS_DATA_SIZE];
} __packed;
enum dect_clms_section_types {
DECT_CLMS_SECTION_DATA = 0x0,
DECT_CLMS_SECTION_ADDR = 0x8,
};
#define DECT_CLMS_SECTION_TYPE_MASK 0x8
#define DECT_CLMS_SECTION_NUM_MASK 0x7
enum dect_clms_header_types {
DECT_CLMS_HDR_STANDARD_ONE_SECTION = 0x1,
DECT_CLMS_HDR_STANDARD_MULTI_SECTION = 0x2,
DECT_CLMS_HDR_BITSTREAM_ONE_SECTION = 0x3,
DECT_CLMS_HDR_BITSTREAM_MULTI_SECTION = 0x4,
DECT_CLMS_HDR_ALPHANUMERIC_ONE_SECTION = 0x5,
DECT_CLMS_HDR_ALPHANUMERIC_MULTI_SECTION = 0x6,
};
#define DECT_CLMS_HDR_MASK 0x7
enum dect_clms_protocol_discriminators {
DECT_CLMS_PD_DECT_IE_CODING = 0x1,
DECT_CLMS_PD_DISTRIBUTED_COMMUNICATIONS = 0x10,
};
extern void dect_clms_rcv_fixed(struct dect_handle *dh, struct dect_msg_buf *mb);
#endif /* _LIBDECT_CLMS_H */

51
include/dect/clms.h Normal file
View File

@ -0,0 +1,51 @@
/*
* DECT Connectionless Message Service (CLMS) NWK <-> IWU interface
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*/
#ifndef _LIBDECT_DECT_CLMS_H
#define _LIBDECT_DECT_CLMS_H
#ifdef __cplusplus
extern "C" {
#endif
/**
* @addtogroup clms
* @{
*/
#include <dect/ie.h>
struct dect_mncl_unitdata_param {
struct dect_ie_collection common;
struct dect_ie_alphanumeric *alphanumeric;
struct dect_ie_iwu_to_iwu *iwu_to_iwu;
struct dect_ie_iwu_packet *iwu_packet;
struct dect_ie_escape_to_proprietary *escape_to_proprietary;
};
enum dect_clms_message_types {
DECT_CLMS_FIXED,
DECT_CLMS_VARIABLE,
};
struct dect_clms_ops {
void (*mncl_unitdata_ind)(struct dect_handle *dh,
enum dect_clms_message_types type,
struct dect_mncl_unitdata_param *param,
struct dect_msg_buf *mb);
};
extern void dect_mncl_unitdata_req(struct dect_handle *dh,
enum dect_clms_message_types type,
const struct dect_mncl_unitdata_param *param,
const struct dect_msg_buf *mb);
/** @} */
#ifdef __cplusplus
}
#endif
#endif /* _LIBDECT_DECT_CLMS_H */

View File

@ -21,6 +21,7 @@ enum dect_debug_subsys {
DECT_DEBUG_LCE, /**< Link Control Entity */
DECT_DEBUG_CC, /**< Call Control */
DECT_DEBUG_SS, /**< Supplementary Services */
DECT_DEBUG_CLMS, /**< ConnectionLess Message Service */
DECT_DEBUG_MM, /**< Mobility Management */
DECT_DEBUG_SFMT, /**< S-Format message parsing/construction */
DECT_DEBUG_NL, /**< Netlink communication */

View File

@ -418,8 +418,25 @@ struct dect_ie_allocation_type {
* @{
*/
enum dect_character_types {
DECT_CHARACTER_TYPE_USER_SPECIFIC = 0x0,
DECT_CHARACTER_TYPE_STANDARD_8BIT = 0x1,
DECT_CHARACTER_TYPE_STANDARD_4BIT = 0x2,
};
enum dect_character_sets {
DECT_CHARSET_DECT_STANDARD = 0x1,
DECT_CHARSET_IA5 = 0x2,
DECT_CHARSET_ERMES = 0x4,
DECT_CHARSET_ASCII = 0x6,
};
struct dect_ie_alphanumeric {
struct dect_ie_common common;
struct dect_ie_common common;
enum dect_character_types type;
enum dect_character_sets charset;
uint8_t len;
uint8_t data[64];
};
/**

View File

@ -23,6 +23,7 @@ extern "C" {
#include <dect/cc.h>
#include <dect/mm.h>
#include <dect/ss.h>
#include <dect/clms.h>
#include <dect/debug.h>
#include <list.h>
@ -148,6 +149,7 @@ struct dect_ops {
const struct dect_cc_ops *cc_ops;
const struct dect_mm_ops *mm_ops;
const struct dect_ss_ops *ss_ops;
const struct dect_clms_ops *clms_ops;
const struct dect_raw_ops *raw_ops;
};

View File

@ -93,6 +93,10 @@ extern int dect_lce_send(const struct dect_handle *dh,
extern int dect_lce_retransmit(const struct dect_handle *dh,
struct dect_transaction *ta);
extern ssize_t dect_lce_broadcast(const struct dect_handle *dh,
const struct dect_msg_buf *mb,
bool long_page);
/**
* struct dect_nwk_protocol - NWK layer protocol
*

View File

@ -53,11 +53,6 @@ enum dect_pds {
/* Message type element */
#define DECT_S_PD_MSG_TYPE_MASK 0x7f
/* CLMS message types */
enum dect_clms_msg_types {
DECT_CLMS_VARIABLE = 0x1,
};
/*
* Information elements
*/

View File

@ -10,6 +10,7 @@ dect-obj += ie.o
dect-obj += lce.o
dect-obj += cc.o
dect-obj += ss.o
dect-obj += clms.o
dect-obj += mm.o
dect-obj += keypad.o
dect-obj += auth.o

223
src/clms.c Normal file
View File

@ -0,0 +1,223 @@
/*
* DECT Connetionless Message Service (CLMS)
*
* Copyright (c) 2010 Patrick McHardy <kaber@trash.net>
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License version 2 as
* published by the Free Software Foundation.
*/
/**
* @defgroup clms ConnectionLess Message Service
* @{
*/
#include <linux/byteorder/little_endian.h>
#include <libdect.h>
#include <clms.h>
#include <lce.h>
static DECT_SFMT_MSG_DESC(clms_variable,
DECT_SFMT_IE(DECT_IE_PORTABLE_IDENTITY, IE_MANDATORY, IE_MANDATORY, 0),
DECT_SFMT_IE(DECT_IE_MMS_GENERIC_HEADER, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_MMS_OBJECT_HEADER, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_REPEAT_INDICATOR, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_MMS_EXTENDED_HEADER, IE_OPTIONAL, IE_OPTIONAL, DECT_SFMT_IE_REPEAT),
DECT_SFMT_IE(DECT_IE_REPEAT_INDICATOR, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_TIME_DATE, IE_OPTIONAL, IE_OPTIONAL, DECT_SFMT_IE_REPEAT),
DECT_SFMT_IE(DECT_IE_REPEAT_INDICATOR, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_CALLING_PARTY_NUMBER, IE_OPTIONAL, IE_OPTIONAL, DECT_SFMT_IE_REPEAT),
DECT_SFMT_IE(DECT_IE_CALLING_PARTY_NAME, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_REPEAT_INDICATOR, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_CALLED_PARTY_NUMBER, IE_OPTIONAL, IE_OPTIONAL, DECT_SFMT_IE_REPEAT),
DECT_SFMT_IE(DECT_IE_CALLED_PARTY_SUBADDR, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_SEGMENTED_INFO, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_ALPHANUMERIC, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_IWU_TO_IWU, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_IWU_PACKET, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(DECT_IE_ESCAPE_TO_PROPRIETARY, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE_END_MSG
);
#define __clms_debug(pfx, fmt, args...) \
dect_debug(DECT_DEBUG_CLMS, "%sCLMS: " fmt "\n", pfx, ## args)
#define clms_debug(fmt, args...) \
__clms_debug("", fmt, ##args)
#define clms_debug_entry(fmt, args...) \
__clms_debug("\n", fmt, ##args)
void dect_clms_rcv_fixed(struct dect_handle *dh, struct dect_msg_buf *mb)
{
DECT_DEFINE_MSG_BUF_ONSTACK(_mb), *mbr = &_mb;
struct dect_clms_fixed_addr_section *as;
struct dect_clms_fixed_data_section *ds;
unsigned int n, len, section, sections;
clms_debug("parse {CLMS-FIXED} message");
assert(mb->len % 5 == 0);
as = (void *)mb->data;
if ((as->hdr & DECT_CLMS_SECTION_TYPE_MASK) != DECT_CLMS_SECTION_ADDR)
return;
dect_debug(DECT_DEBUG_CLMS, " address section:\n");
dect_debug(DECT_DEBUG_CLMS, "\tAddress: %04x\n", __be16_to_cpu(as->addr));
dect_debug(DECT_DEBUG_CLMS, "\tProtocol Discriminator: %02x\n", as->pd);
dect_debug(DECT_DEBUG_CLMS, "\tLength Indicator: %02x\n", as->li);
if (as->pd != DECT_CLMS_PD_DECT_IE_CODING)
return;
switch (as->hdr & DECT_CLMS_HDR_MASK) {
case DECT_CLMS_HDR_STANDARD_ONE_SECTION:
case DECT_CLMS_HDR_BITSTREAM_ONE_SECTION:
case DECT_CLMS_HDR_ALPHANUMERIC_ONE_SECTION:
memcpy(dect_mbuf_put(mbr, 1), &as->li, 1);
goto deliver;
case DECT_CLMS_HDR_STANDARD_MULTI_SECTION:
case DECT_CLMS_HDR_BITSTREAM_MULTI_SECTION:
case DECT_CLMS_HDR_ALPHANUMERIC_MULTI_SECTION:
if (as->li == 0 || as->li % 8)
return;
len = as->li / 8;
break;
default:
return;
}
dect_mbuf_pull(mb, sizeof(*as));
sections = 0;
while (mb->len > 0) {
ds = (void *)mb->data;
if ((ds->hdr & DECT_CLMS_SECTION_TYPE_MASK) !=
DECT_CLMS_SECTION_DATA)
return;
section = ds->hdr & DECT_CLMS_SECTION_NUM_MASK;
dect_debug(DECT_DEBUG_CLMS, " data section %u:\n", section);
dect_debug(DECT_DEBUG_CLMS, "\tData: %02x%02x%02x%02x\n",
ds->data[0], ds->data[1], ds->data[2], ds->data[3]);
if (section >= 5)
return;
if (section != sections)
return;
sections++;
n = min(len, DECT_CLMS_DATA_SIZE);
memcpy(dect_mbuf_put(mbr, n), ds->data, n);
len -= n;
dect_mbuf_pull(mb, sizeof(*ds));
}
if (len > 0)
return;
deliver:
dect_mbuf_dump(DECT_DEBUG_CLMS, mbr, "CLMS");
clms_debug("MNCL_UNITDATA-ind: type: %u", DECT_CLMS_FIXED);
dh->ops->clms_ops->mncl_unitdata_ind(dh, DECT_CLMS_FIXED, NULL, mbr);
}
static void dect_clms_send_fixed(struct dect_handle *dh,
const void *data, unsigned int len)
{
DECT_DEFINE_MSG_BUF_ONSTACK(_mb), *mb = &_mb;
struct dect_clms_fixed_addr_section *as;
struct dect_clms_fixed_data_section *ds;
unsigned int n, section;
as = dect_mbuf_put(mb, sizeof(*as));
as->hdr = DECT_CLMS_SECTION_ADDR;
as->addr = __cpu_to_be16(DECT_TPUI_CBI);
as->pd = DECT_CLMS_PD_DECT_IE_CODING;
if (len > 1) {
as->hdr |= DECT_CLMS_HDR_STANDARD_MULTI_SECTION;
as->li = len * 8;
} else {
as->hdr |= DECT_CLMS_HDR_STANDARD_ONE_SECTION;
as->li = *(uint8_t *)data;
goto deliver;
}
section = 0;
while (len > 0) {
ds = dect_mbuf_put(mb, sizeof(*ds));
ds->hdr = DECT_CLMS_SECTION_DATA;
ds->hdr |= section;
n = min(len, DECT_CLMS_DATA_SIZE);
memcpy(ds->data, data, n);
if (n < DECT_CLMS_DATA_SIZE)
memset(ds->data + n, 0, DECT_CLMS_DATA_SIZE - n);
data += n;
len -= n;
section++;
}
deliver:
dect_lce_broadcast(dh, mb, true);
}
/**
* DECT_MNCL_UNITDATA-req primitive
*
* @param dh libdect DECT handle
* @param type message type (fixed/variable) to use
* @param param unitdata parameters
*/
void dect_mncl_unitdata_req(struct dect_handle *dh,
enum dect_clms_message_types type,
const struct dect_mncl_unitdata_param *param,
const struct dect_msg_buf *mb)
{
clms_debug_entry("MNCL_UNITDATA-req");
dect_clms_send_fixed(dh, mb->data, mb->len);
}
EXPORT_SYMBOL(dect_mncl_unitdata_req);
static void dect_clms_rcv_variable(struct dect_handle *dh,
struct dect_msg_buf *mb)
{
struct dect_clms_variable_msg msg;
clms_debug("CLMS-VARIABLE");
if (dect_parse_sfmt_msg(dh, &clms_variable_msg_desc,
&msg.common, mb) < 0)
return;
dect_msg_free(dh, &clms_variable_msg_desc, &msg.common);
}
static void dect_clms_open(struct dect_handle *dh,
struct dect_transaction *req,
struct dect_msg_buf *mb)
{
clms_debug("msg type: %x", mb->type);
switch (mb->type) {
case CLMS_VARIABLE:
return dect_clms_rcv_variable(dh, mb);
default:
return;
}
}
static const struct dect_nwk_protocol clms_protocol = {
.name = "ConnectionLess Message Service",
.pd = DECT_PD_CLMS,
.max_transactions = 1,
.open = dect_clms_open,
};
static void __init dect_clms_init(void)
{
dect_lce_register_protocol(&clms_protocol);
}
/** @} */

View File

@ -33,6 +33,7 @@
#include <io.h>
#include <s_fmt.h>
#include <b_fmt.h>
#include <clms.h>
#include <lce.h>
#include <ss.h>
#include <dect/auth.h>
@ -782,9 +783,9 @@ err1:
* Paging
*/
static ssize_t dect_lce_broadcast(const struct dect_handle *dh,
const struct dect_msg_buf *mb,
bool long_page)
ssize_t dect_lce_broadcast(const struct dect_handle *dh,
const struct dect_msg_buf *mb,
bool long_page)
{
struct msghdr msg;
struct dect_bsap_auxdata aux;
@ -1046,6 +1047,7 @@ static void dect_lce_rcv_long_page(struct dect_handle *dh,
struct dect_msg_buf *mb)
{
lce_debug("long page: length: %u\n", mb->len);
dect_clms_rcv_fixed(dh, mb);
}
static void dect_lce_bsap_event(struct dect_handle *dh, struct dect_fd *dfd,

View File

@ -1054,7 +1054,8 @@ static void dect_sfmt_dump_network_parameter(const struct dect_ie_common *_ie)
sfmt_debug("\tDiscriminator: %s\n",
dect_val2str(dect_network_parameter_discriminators,
buf, sizeof(buf)));
buf, ie->discriminator));
sfmt_debug("\tData: %.*s\n", ie->len, ie->data);
}
static int dect_sfmt_parse_network_parameter(const struct dect_handle *dh,