dect
/
libdect
Archived
13
0
Fork 0

ss: add CISS support

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2010-01-10 20:45:55 +01:00
parent a037cb0c20
commit dcd8473fcd
9 changed files with 557 additions and 2 deletions

View File

@ -1,5 +1,5 @@
LDFLAGS += -Wl,-rpath $(PWD)/src -Lsrc -ldect
PROGRAMS += cc mm-fp discover hijack
PROGRAMS += cc ss mm-fp discover hijack
cc-destdir := usr/bin
cc-obj += event_ops.o
@ -7,6 +7,11 @@ cc-obj += dummy_ops.o
cc-obj += audio.o
cc-obj += cc.o
ss-destdir := usr/bin
ss-obj += event_ops.o
ss-obj += dummy_ops.o
ss-obj += ss.o
mm-fp-destdir := usr/bin
mm-fp-obj += event_ops.o
mm-fp-obj += dummy_ops.o

View File

@ -222,10 +222,32 @@ static void mm_iwu_ind(struct dect_handle *dh,
static struct dect_mm_ops dummy_mm_ops;
static void mnss_setup_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static void mnss_facility_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static void mnss_release_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static struct dect_ss_ops dummy_ss_ops;
void 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;
if (!ops->cc_ops)
ops->cc_ops = &dummy_cc_ops;
@ -312,4 +334,15 @@ void dummy_ops_init(struct dect_ops *ops)
mm_ops->mm_info_cfm = mm_info_cfm;
if (!mm_ops->mm_iwu_ind)
mm_ops->mm_iwu_ind = mm_iwu_ind;
if (!ops->ss_ops)
ops->ss_ops = &dummy_ss_ops;
ss_ops = (void *)ops->ss_ops;
if (!ss_ops->mnss_setup_ind)
ss_ops->mnss_setup_ind = mnss_setup_ind;
if (!ss_ops->mnss_facility_ind)
ss_ops->mnss_facility_ind = mnss_facility_ind;
if (!ss_ops->mnss_release_ind)
ss_ops->mnss_release_ind = mnss_release_ind;
}

85
example/ss.c Normal file
View File

@ -0,0 +1,85 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/time.h>
#include <event.h>
#include <dect/libdect.h>
#include "common.h"
static struct dect_ipui ipui = {
.put = DECT_IPUI_N,
.pun.n.ipei = {
.emc = 0x0ba8,
.psn = 0xa782a,
},
};
static void mnss_setup_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static void mnss_facility_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static void mnss_release_ind(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param)
{
}
static void dect_invoke_ss(struct dect_handle *dh, const struct dect_ipui *ipui)
{
struct dect_ss_endpoint *sse;
struct dect_ie_feature_activate feature_activate;
struct dect_mnss_param param = {
.feature_activate = &feature_activate,
};
sse = dect_ss_endpoint_alloc(dh);
if (sse == NULL)
return;
feature_activate.feature = DECT_FEATURE_INDICATION_OF_SUBSCRIBER_NUMBER;
dect_mnss_setup_req(dh, sse, ipui, &param);
}
static struct dect_ss_ops ss_ops = {
.mnss_setup_ind = mnss_setup_ind,
.mnss_facility_ind = mnss_facility_ind,
.mnss_release_ind = mnss_release_ind,
};
static struct dect_ops ops = {
.ss_ops = &ss_ops,
};
int main(int argc, char **argv)
{
dummy_ops_init(&ops);
if (dect_event_ops_init(&ops) < 0)
exit(1);
dh = dect_alloc_handle(&ops);
if (dh == NULL)
exit(1);
if (dect_init(dh) < 0)
exit(1);
dect_invoke_ss(dh, &ipui);
dect_event_loop();
dect_close_handle(dh);
dect_event_ops_cleanup();
return 0;
}

View File

@ -486,20 +486,48 @@ struct dect_ie_end_to_end_compatibility {
/* Facility IE */
enum dect_facility_discriminators {
DECT_FACILITY_SS = 0x17,
};
struct dect_ie_facility {
struct dect_ie_common common;
struct dect_ie_common common;
enum dect_facility_discriminators service;
};
/* Feature activate IE */
enum dect_feature {
DECT_FEATURE_REGISTER_RECALL = 0x1,
DECT_FEATURE_EXTERNAL_HO_SWITCH = 0xf,
DECT_FEATURE_QUEUE_ENTRY_REQUEST = 0x20,
DECT_FEATURE_INDICATION_OF_SUBSCRIBER_NUMBER = 0x30,
DECT_FEATURE_FEATURE_KEY = 0x42,
DECT_FEATURE_SPECIFIC_LINE_SELECTION = 0x44,
DECT_FEATURE_SPECIFIC_TRUNK_SELECTION = 0x47,
DECT_FEATURE_ECHO_CONTROL = 0x48,
DECT_FEATURE_COST_INFORMATION = 0x60,
};
struct dect_ie_feature_activate {
struct dect_ie_common common;
enum dect_feature feature;
};
/* Feature indicate IE */
enum dect_feature_status {
DECT_FEATURE_SERVICE_REQUEST_REJECTED = 0x80,
DECT_FEATURE_SERVICE_REQUEST_ACCEPTED = 0x81,
DECT_FEATURE_SERVICE_REQUEST_PENDING = 0x83,
DECT_FEATURE_SERVICE_BUSY = 0x84,
DECT_FEATURE_SERVICE_UNOBTAINABLE = 0x86,
};
struct dect_ie_feature_indicate {
struct dect_ie_common common;
enum dect_feature feature;
enum dect_feature_status status;
};
/* Fixed identity IE */

View File

@ -16,6 +16,7 @@
#include <dect/auth.h>
#include <dect/cc.h>
#include <dect/mm.h>
#include <dect/ss.h>
#include <list.h>
struct dect_handle;
@ -127,6 +128,7 @@ struct dect_ops {
const struct dect_event_ops *event_ops;
const struct dect_cc_ops *cc_ops;
const struct dect_mm_ops *mm_ops;
const struct dect_ss_ops *ss_ops;
};
extern struct dect_handle *dect_alloc_handle(struct dect_ops *ops);

46
include/dect/ss.h Normal file
View File

@ -0,0 +1,46 @@
/*
* DECT Suplementary Services (SS) NWK <-> IWU interface
*
* Copyright (c) 2009 Patrick McHardy <kaber@trash.net>
*/
#ifndef _LIBDECT_DECT_SS_H
#define _LIBDECT_DECT_SS_H
#include <dect/ie.h>
struct dect_mnss_param {
struct dect_ie_collection common;
struct dect_ie_list facility;
struct dect_ie_display *display;
struct dect_ie_keypad *keypad;
struct dect_ie_feature_activate *feature_activate;
struct dect_ie_feature_indicate *feature_indicate;
struct dect_ie_escape_to_proprietary *escape_to_proprietary;
};
struct dect_handle;
struct dect_ss_endpoint;
extern void *dect_ss_priv(struct dect_ss_endpoint *sse);
extern struct dect_ss_endpoint *dect_ss_endpoint_alloc(struct dect_handle *dh);
struct dect_ss_ops {
size_t priv_size;
void (*mnss_setup_ind)(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param);
void (*mnss_facility_ind)(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param);
void (*mnss_release_ind)(struct dect_handle *dh, struct dect_ss_endpoint *sse,
struct dect_mnss_param *param);
};
extern int dect_mnss_setup_req(struct dect_handle *dh, struct dect_ss_endpoint *sse,
const struct dect_ipui *ipui,
const struct dect_mnss_param *param);
extern int dect_mnss_facility_req(struct dect_handle *dh, struct dect_ss_endpoint *sse,
const struct dect_mnss_param *param);
extern int dect_mnss_release_req(struct dect_handle *dh, struct dect_ss_endpoint *sse,
const struct dect_mnss_param *param);
#endif /* _LIBDECT_DECT_SS_H */

View File

@ -52,6 +52,17 @@ struct dect_ciss_register_msg {
struct dect_ie_escape_to_proprietary *escape_to_proprietary;
};
/**
* struct dect_ss_endpoint - Supplementary Services Endpoint
*
* @transaction: LCE link transaction
* @priv: libdect user private storage
*/
struct dect_ss_endpoint {
struct dect_transaction transaction;
uint8_t priv[];
};
extern void dect_clss_rcv(struct dect_handle *dh, struct dect_msg_buf *mb);
/**

View File

@ -863,6 +863,57 @@ static int dect_sfmt_build_multi_keypad(struct dect_sfmt_ie *dst,
return 0;
}
static const struct dect_trans_tbl dect_features[] = {
TRANS_TBL(DECT_FEATURE_REGISTER_RECALL, "register recall"),
TRANS_TBL(DECT_FEATURE_EXTERNAL_HO_SWITCH, "external handover switch"),
TRANS_TBL(DECT_FEATURE_QUEUE_ENTRY_REQUEST, "queue entry request"),
TRANS_TBL(DECT_FEATURE_INDICATION_OF_SUBSCRIBER_NUMBER, "indication of subscriber number"),
TRANS_TBL(DECT_FEATURE_FEATURE_KEY, "feature key"),
TRANS_TBL(DECT_FEATURE_SPECIFIC_LINE_SELECTION, "specific line selection"),
TRANS_TBL(DECT_FEATURE_SPECIFIC_TRUNK_SELECTION, "specific trunk carrier selection"),
TRANS_TBL(DECT_FEATURE_ECHO_CONTROL, "echo control"),
TRANS_TBL(DECT_FEATURE_COST_INFORMATION, "cost information"),
};
static void dect_sfmt_dump_feature_activate(const struct dect_ie_common *_ie)
{
const struct dect_ie_feature_activate *ie = dect_ie_container(ie, _ie);
char buf[64];
dect_debug("\tfeature: %s\n", dect_val2str(dect_features, buf, ie->feature));
}
static int dect_sfmt_build_feature_activate(struct dect_sfmt_ie *dst,
const struct dect_ie_common *ie)
{
struct dect_ie_feature_activate *src = dect_ie_container(src, ie);
dst->data[2] = src->feature;
dst->data[2] |= DECT_OCTET_GROUP_END;
dst->len = 3;
return 0;
}
static void dect_sfmt_dump_feature_indicate(const struct dect_ie_common *_ie)
{
const struct dect_ie_feature_indicate *ie = dect_ie_container(ie, _ie);
char buf[64];
dect_debug("\tfeature: %s\n", dect_val2str(dect_features, buf, ie->feature));
dect_debug("\tstatus: %x\n", ie->status);
}
static int dect_sfmt_parse_feature_indicate(const struct dect_handle *dh,
struct dect_ie_common **ie,
const struct dect_sfmt_ie *src)
{
struct dect_ie_feature_indicate *dst = dect_ie_container(dst, *ie);
dst->feature = src->data[2] & ~DECT_OCTET_GROUP_END;
dst->status = src->data[3];
return 0;
}
static const struct dect_trans_tbl dect_reject_reasons[] = {
TRANS_TBL(DECT_REJECT_TPUI_UNKNOWN, "TPUI unknown"),
TRANS_TBL(DECT_REJECT_IPUI_UNKNOWN, "IPUI unknown"),
@ -1686,10 +1737,14 @@ static const struct dect_ie_handler {
[S_VL_IE_FEATURE_ACTIVATE] = {
.name = "feature activate",
.size = sizeof(struct dect_ie_feature_activate),
.build = dect_sfmt_build_feature_activate,
.dump = dect_sfmt_dump_feature_activate,
},
[S_VL_IE_FEATURE_INDICATE] = {
.name = "feature indicate",
.size = sizeof(struct dect_ie_feature_indicate),
.parse = dect_sfmt_parse_feature_indicate,
.dump = dect_sfmt_dump_feature_indicate,
},
[S_VL_IE_NETWORK_PARAMETER] = {
.name = "network parameter",

290
src/ss.c
View File

@ -22,6 +22,29 @@
#include <lce.h>
#include <ss.h>
static DECT_SFMT_MSG_DESC(ciss_register,
DECT_SFMT_IE(S_VL_IE_PORTABLE_IDENTITY, IE_OPTIONAL, IE_MANDATORY, 0),
DECT_SFMT_IE(S_SO_IE_REPEAT_INDICATOR, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(S_VL_IE_FACILITY, IE_OPTIONAL, IE_OPTIONAL, DECT_SFMT_IE_REPEAT),
DECT_SFMT_IE(S_DO_IE_SINGLE_DISPLAY, IE_OPTIONAL, IE_NONE, 0),
DECT_SFMT_IE(S_DO_IE_SINGLE_KEYPAD, IE_NONE, IE_OPTIONAL, 0),
DECT_SFMT_IE(S_VL_IE_FEATURE_ACTIVATE, IE_NONE, IE_OPTIONAL, 0),
DECT_SFMT_IE(S_VL_IE_FEATURE_INDICATE, IE_OPTIONAL, IE_NONE, 0),
DECT_SFMT_IE(S_VL_IE_ESCAPE_TO_PROPRIETARY, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE_END_MSG
);
static DECT_SFMT_MSG_DESC(ciss_release_com,
DECT_SFMT_IE(S_VL_IE_PORTABLE_IDENTITY, IE_OPTIONAL, IE_MANDATORY, 0),
DECT_SFMT_IE(S_SO_IE_REPEAT_INDICATOR, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE(S_VL_IE_FACILITY, IE_OPTIONAL, IE_OPTIONAL, DECT_SFMT_IE_REPEAT),
DECT_SFMT_IE(S_DO_IE_SINGLE_DISPLAY, IE_OPTIONAL, IE_NONE, 0),
DECT_SFMT_IE(S_DO_IE_SINGLE_KEYPAD, IE_NONE, IE_OPTIONAL, 0),
DECT_SFMT_IE(S_VL_IE_FEATURE_ACTIVATE, IE_NONE, IE_OPTIONAL, 0),
DECT_SFMT_IE(S_VL_IE_FEATURE_INDICATE, IE_OPTIONAL, IE_NONE, 0),
DECT_SFMT_IE(S_VL_IE_ESCAPE_TO_PROPRIETARY, IE_OPTIONAL, IE_OPTIONAL, 0),
DECT_SFMT_IE_END_MSG
);
static DECT_SFMT_MSG_DESC(ciss_facility,
DECT_SFMT_IE(S_SO_IE_REPEAT_INDICATOR, IE_OPTIONAL, IE_OPTIONAL, 0),
@ -39,6 +62,16 @@ static DECT_SFMT_MSG_DESC(ciss_facility,
DECT_SFMT_IE_END_MSG
);
#define __ss_debug(pfx, fmt, args...) \
dect_debug("%sSS (link %d): " fmt "\n", pfx, \
(sse)->transaction.link ? (sse)->transaction.link->dfd->fd : -1, \
## args)
#define ss_debug(sse, fmt, args...) \
__ss_debug("", fmt, ## args)
#define ss_debug_entry(sse, fmt, args...) \
__ss_debug("\n", fmt, ## args)
void dect_clss_rcv(struct dect_handle *dh, struct dect_msg_buf *mb)
{
struct dect_ciss_facility_msg msg;
@ -51,3 +84,260 @@ void dect_clss_rcv(struct dect_handle *dh, struct dect_msg_buf *mb)
dect_msg_free(dh, &ciss_facility_msg_desc, &msg.common);
}
void *dect_ss_priv(struct dect_ss_endpoint *sse)
{
return sse->priv;
}
struct dect_ss_endpoint *dect_ss_endpoint_alloc(struct dect_handle *dh)
{
struct dect_ss_endpoint *sse;
sse = dect_zalloc(dh, sizeof(*sse) + dh->ops->ss_ops->priv_size);
if (sse == NULL)
goto err1;
return sse;
err1:
return NULL;
}
static struct dect_ss_endpoint *dect_ss_endpoint(struct dect_transaction *ta)
{
return container_of(ta, struct dect_ss_endpoint, transaction);
}
/**
* dect_mnss_setup_req - MNSS_SETUP-req primitive
*
* @dh: libdect DECT handle
* @sse: Supplementary Services Endpoint
* @ipui: PT IPUI
* @param: Supplementary Services parameters
*/
int dect_mnss_setup_req(struct dect_handle *dh, struct dect_ss_endpoint *sse,
const struct dect_ipui *ipui,
const struct dect_mnss_param *param)
{
struct dect_ie_portable_identity portable_identity;
struct dect_ciss_register_msg msg = {
.facility = param->facility,
.display = param->display,
.keypad = param->keypad,
.feature_activate = param->feature_activate,
.feature_indicate = param->feature_indicate,
};
ss_debug_entry(sse, "MNSS_SETUP-req");
if (dect_open_transaction(dh, &sse->transaction, ipui, DECT_PD_CISS) < 0)
goto err1;
if (dh->mode == DECT_MODE_PP) {
portable_identity.type = DECT_PORTABLE_ID_TYPE_IPUI;
portable_identity.ipui = *ipui;
msg.portable_identity = &portable_identity;
}
if (dect_lce_send(dh, &sse->transaction, &ciss_register_msg_desc,
&msg.common, CISS_REGISTER) < 0)
goto err2;
return 0;
err2:
dect_close_transaction(dh, &sse->transaction, DECT_DDL_RELEASE_NORMAL);
err1:
return -1;
}
/**
* dect_mnss_facility_req - MNSS_FACILITY-req primitive
*
* @dh: libdect DECT handle
* @sse: Supplementary Services Endpoint
* @param: Supplementary Services parameters
*/
int dect_mnss_facility_req(struct dect_handle *dh, struct dect_ss_endpoint *sse,
const struct dect_mnss_param *param)
{
struct dect_ciss_facility_msg msg = {
.facility = param->facility,
.display = param->display,
.keypad = param->keypad,
.feature_activate = param->feature_activate,
.feature_indicate = param->feature_indicate,
};
ss_debug_entry(sse, "MNSS_FACILITY-req");
return dect_lce_send(dh, &sse->transaction, &ciss_facility_msg_desc,
&msg.common, CISS_FACILITY);
}
static void dect_ciss_rcv_facility(struct dect_handle *dh,
struct dect_ss_endpoint *sse,
struct dect_msg_buf *mb)
{
struct dect_ciss_facility_msg msg;
struct dect_mnss_param *param;
ss_debug(sse, "CISS-FACILITY");
if (dect_parse_sfmt_msg(dh, &ciss_facility_msg_desc, &msg.common, mb) < 0)
return;
param = dect_ie_collection_alloc(dh, sizeof(*param));
if (param == NULL)
goto out;
param->facility = *dect_ie_list_hold(&msg.facility);
param->display = dect_ie_hold(msg.display);
param->keypad = dect_ie_hold(msg.keypad);
param->feature_activate = dect_ie_hold(msg.feature_activate);
param->feature_indicate = dect_ie_hold(msg.feature_indicate);
param->escape_to_proprietary = dect_ie_hold(msg.escape_to_proprietary);
ss_debug(sse, "MNSS_FACILITY-ind");
dh->ops->ss_ops->mnss_facility_ind(dh, sse, param);
dect_ie_collection_put(dh, param);
out:
dect_msg_free(dh, &ciss_facility_msg_desc, &msg.common);
}
/**
* dect_mnss_release_req - MNSS_RELEASE-req primitive
*
* @dh: libdect DECT handle
* @sse: Supplementary Services Endpoint
* @param: Supplementary Services parameters
*/
int dect_mnss_release_req(struct dect_handle *dh, struct dect_ss_endpoint *sse,
const struct dect_mnss_param *param)
{
struct dect_ciss_release_com_msg msg = {
.facility = param->facility,
.display = param->display,
.keypad = param->keypad,
.feature_activate = param->feature_activate,
.feature_indicate = param->feature_indicate,
};
ss_debug_entry(sse, "MNSS_RELEASE-req");
return dect_lce_send(dh, &sse->transaction, &ciss_release_com_msg_desc,
&msg.common, CISS_RELEASE_COM);
}
static void dect_ciss_rcv_release_com(struct dect_handle *dh,
struct dect_ss_endpoint *sse,
struct dect_msg_buf *mb)
{
struct dect_ciss_release_com_msg msg;
struct dect_mnss_param *param;
ss_debug(sse, "CISS-RELEASE-COM");
if (dect_parse_sfmt_msg(dh, &ciss_release_com_msg_desc, &msg.common, mb) < 0)
return;
param = dect_ie_collection_alloc(dh, sizeof(*param));
if (param == NULL)
goto out;
param->facility = *dect_ie_list_hold(&msg.facility);
param->display = dect_ie_hold(msg.display);
param->keypad = dect_ie_hold(msg.keypad);
param->feature_activate = dect_ie_hold(msg.feature_activate);
param->feature_indicate = dect_ie_hold(msg.feature_indicate);
param->escape_to_proprietary = dect_ie_hold(msg.escape_to_proprietary);
ss_debug(sse, "MNSS_FACILITY-ind");
dh->ops->ss_ops->mnss_facility_ind(dh, sse, param);
dect_ie_collection_put(dh, param);
out:
dect_msg_free(dh, &ciss_release_com_msg_desc, &msg.common);
}
static void dect_ciss_rcv(struct dect_handle *dh, struct dect_transaction *ta,
struct dect_msg_buf *mb)
{
struct dect_ss_endpoint *sse = dect_ss_endpoint(ta);
switch (mb->type) {
case CISS_FACILITY:
return dect_ciss_rcv_facility(dh, sse, mb);
case CISS_RELEASE_COM:
return dect_ciss_rcv_release_com(dh, sse, mb);
}
ss_debug(sse, "receive unknown msg type %x", mb->type);
}
static void dect_ciss_rcv_register(struct dect_handle *dh,
const struct dect_transaction *req,
struct dect_msg_buf *mb)
{
struct dect_ciss_register_msg msg;
struct dect_mnss_param *param;
struct dect_ss_endpoint *sse;
dect_debug("CISS-REGISTER");
if (dect_parse_sfmt_msg(dh, &ciss_register_msg_desc, &msg.common, mb) < 0)
return;
sse = dect_ss_endpoint_alloc(dh);
if (sse == NULL)
goto out;
param = dect_ie_collection_alloc(dh, sizeof(*param));
if (param == NULL)
goto out;
param->facility = *dect_ie_list_hold(&msg.facility);
param->display = dect_ie_hold(msg.display);
param->keypad = dect_ie_hold(msg.keypad);
param->feature_activate = dect_ie_hold(msg.feature_activate);
param->feature_indicate = dect_ie_hold(msg.feature_indicate);
param->escape_to_proprietary = dect_ie_hold(msg.escape_to_proprietary);
dect_confirm_transaction(dh, &sse->transaction, req);
ss_debug(sse, "MNSS_SETUP-ind");
dh->ops->ss_ops->mnss_setup_ind(dh, sse, param);
dect_ie_collection_put(dh, param);
out:
dect_msg_free(dh, &ciss_register_msg_desc, &msg.common);
}
static void dect_ciss_open(struct dect_handle *dh,
const struct dect_transaction *req,
struct dect_msg_buf *mb)
{
dect_debug("SS: unknown transaction: msg type: %x\n", mb->type);
switch (mb->type) {
case CISS_REGISTER:
return dect_ciss_rcv_register(dh, req, mb);
default:
return;
}
}
static void dect_ciss_shutdown(struct dect_handle *dh,
struct dect_transaction *ta)
{
struct dect_ss_endpoint *sse = dect_ss_endpoint(ta);
ss_debug(sse, "shutdown");
dect_close_transaction(dh, &sse->transaction, DECT_DDL_RELEASE_NORMAL);
}
static const struct dect_nwk_protocol ciss_protocol = {
.name = "Call Independant Supplementary Services",
.pd = DECT_PD_CISS,
.max_transactions = 7,
.open = dect_ciss_open,
.shutdown = dect_ciss_shutdown,
.rcv = dect_ciss_rcv,
};
static void __init dect_ciss_init(void)
{
dect_lce_register_protocol(&ciss_protocol);
}