ss: add CISS support
Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
parent
a037cb0c20
commit
dcd8473fcd
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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, ¶m);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -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 */
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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 */
|
11
include/ss.h
11
include/ss.h
|
@ -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);
|
||||
|
||||
/**
|
||||
|
|
55
src/s_msg.c
55
src/s_msg.c
|
@ -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
290
src/ss.c
|
@ -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);
|
||||
}
|
||||
|
|
Reference in New Issue