dect
/
libdect
Archived
13
0
Fork 0

libdect: add preliminary wideband support

Unfinished, so far only meant for testing the kernel side.

Signed-off-by: Patrick McHardy <kaber@trash.net>
This commit is contained in:
Patrick McHardy 2011-10-05 19:06:54 +02:00
parent 56e4149e01
commit ecc2c7d990
16 changed files with 451 additions and 121 deletions

View File

@ -18,6 +18,7 @@ static struct dect_llme_ops_ dummy_llme_ops;
*/
static bool lce_page_response(struct dect_handle *dh,
struct dect_data_link *ddl,
struct dect_lce_page_param *param)
{
return false;
@ -28,6 +29,12 @@ static void lce_group_ring_ind(struct dect_handle *dh,
{
}
static void dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
}
static struct dect_lce_ops dummy_lce_ops;
/*
@ -339,6 +346,8 @@ void dect_dummy_ops_init(struct dect_ops *ops)
lce_ops->lce_page_response = lce_page_response;
if (!lce_ops->lce_group_ring_ind)
lce_ops->lce_group_ring_ind = lce_group_ring_ind;
if (!lce_ops->dl_establish_cfm)
lce_ops->dl_establish_cfm = dl_establish_cfm;
if (!ops->cc_ops)
ops->cc_ops = &dummy_cc_ops;

View File

@ -21,38 +21,61 @@ static void mm_locate_ind(struct dect_handle *dh,
struct dect_mm_endpoint *mme,
struct dect_mm_locate_param *param)
{
struct dect_mm_locate_param res = {
.portable_identity = param->portable_identity,
.location_area = param->location_area,
};
dect_mm_locate_res(dh, mme, true, &res);
}
static void mm_info_req(struct dect_handle *dh,
const struct dect_ipui *ipui)
static void mm_info_req(struct dect_handle *dh, struct dect_mm_endpoint *mme)
{
struct dect_ie_info_type info_type;
struct dect_mm_info_param req = { .info_type = &info_type };
struct dect_mm_endpoint *mme;
mme = dect_mm_endpoint_alloc(dh, ipui);
if (mme == NULL)
return;
info_type.num = 1;
info_type.type[0] = DECT_INFO_LOCATE_SUGGEST;
dect_mm_info_req(dh, mme, &req);
}
static void dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
struct dect_mm_endpoint *mme;
if (!success)
return dect_event_loop_stop();
mme = dect_mm_endpoint_alloc(dh, ddl);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_info_req(dh, mme);
}
static struct dect_mm_ops mm_ops = {
.mm_locate_ind = mm_locate_ind,
};
static struct dect_lce_ops lce_ops = {
.dl_establish_cfm = dl_establish_cfm,
};
static struct dect_ops ops = {
.lce_ops = &lce_ops,
.mm_ops = &mm_ops,
};
int main(int argc, char **argv)
{
struct dect_mac_conn_params mcp = {};
dect_fp_common_options(argc, argv);
dect_common_init(&ops, argv[1]);
mm_info_req(dh, &ipui);
dect_dl_establish_req(dh, &ipui, &mcp);
dect_event_loop();
dect_common_cleanup(dh);

View File

@ -29,13 +29,14 @@ static struct dect_mm_ops mm_ops = {
.mm_locate_ind = mm_locate_ind,
};
static bool lce_page_response(struct dect_handle *dh, struct dect_lce_page_param *param)
static bool lce_page_response(struct dect_handle *dh, struct dect_data_link *ddl,
struct dect_lce_page_param *param)
{
struct dect_ie_info_type info_type;
struct dect_mm_info_param req = { .info_type = &info_type };
struct dect_mm_endpoint *mme;
mme = dect_mm_endpoint_alloc(dh, &param->portable_identity->ipui);
mme = dect_mm_endpoint_alloc(dh, ddl);
if (mme == NULL)
return false;
@ -91,7 +92,19 @@ static void page_timer(struct dect_handle *dh, struct dect_timer *timer)
dect_timer_start(dh, timer, 1);
}
static void dect_mac_me_info_ind(struct dect_handle *dh,
const struct dect_ari *pari,
const struct dect_fp_capabilities *fpc)
{
printf("pari %p fpc %p\n", pari, fpc);
}
static struct dect_llme_ops_ llme_ops = {
.mac_me_info_ind = dect_mac_me_info_ind,
};
static struct dect_ops ops = {
.llme_ops = &llme_ops,
.lce_ops = &lce_ops,
.mm_ops = &mm_ops,
};

View File

@ -37,22 +37,36 @@ static struct dect_mm_ops mm_ops = {
.mm_access_rights_terminate_cfm = mm_access_rights_terminate_cfm,
};
static struct dect_ops ops = {
.mm_ops = &mm_ops,
};
int main(int argc, char **argv)
static void dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
struct dect_mm_endpoint *mme;
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
mme = dect_mm_endpoint_alloc(dh, &ipui);
mme = dect_mm_endpoint_alloc(dh, ddl);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_access_rights_terminate_req(dh, mme);
}
static struct dect_lce_ops lce_ops = {
.dl_establish_cfm = dl_establish_cfm,
};
static struct dect_ops ops = {
.lce_ops = &lce_ops,
.mm_ops = &mm_ops,
};
int main(int argc, char **argv)
{
struct dect_mac_conn_params mcp = {};
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
dect_dl_establish_req(dh, &ipui, &mcp);
dect_event_loop();
dect_common_cleanup(dh);

View File

@ -149,6 +149,19 @@ static int mm_access_rights_req(struct dect_handle *dh, struct dect_mm_endpoint
return dect_mm_access_rights_req(dh, mme, &param);
}
static void dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
struct dect_mm_endpoint *mme;
mme = dect_mm_endpoint_alloc(dh, ddl);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_access_rights_req(dh, mme);
}
static void llme_mac_me_info_ind(struct dect_handle *dh,
const struct dect_ari *pari,
const struct dect_fp_capabilities *fpc)
@ -157,6 +170,10 @@ static void llme_mac_me_info_ind(struct dect_handle *dh,
dect_event_loop_stop();
}
static struct dect_lce_ops lce_ops = {
.dl_establish_cfm = dl_establish_cfm,
};
static struct dect_llme_ops_ llme_ops = {
.mac_me_info_ind = llme_mac_me_info_ind,
};
@ -171,6 +188,7 @@ static struct dect_mm_ops mm_ops = {
static struct dect_ops ops = {
.llme_ops = &llme_ops,
.lce_ops = &lce_ops,
.mm_ops = &mm_ops,
};
@ -191,7 +209,6 @@ static const struct option options[] = {
int main(int argc, char **argv)
{
struct dect_mm_endpoint *mme;
const char *cluster = NULL;
int optidx = 0, c;
@ -232,11 +249,7 @@ int main(int argc, char **argv)
dect_event_loop();
}
mme = dect_mm_endpoint_alloc(dh, &ipui);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_access_rights_req(dh, mme);
dect_dl_establish_req(dh, &ipui, NULL);
dect_event_loop();
dect_common_cleanup(dh);

View File

@ -25,20 +25,35 @@ static int mm_detach_req(struct dect_handle *dh, struct dect_mm_endpoint *mme)
return dect_mm_detach_req(dh, mme, &param);
}
static struct dect_ops ops;
int main(int argc, char **argv)
static void dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
struct dect_mm_endpoint *mme;
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
mme = dect_mm_endpoint_alloc(dh, &ipui);
mme = dect_mm_endpoint_alloc(dh, ddl);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_detach_req(dh, mme);
}
static struct dect_lce_ops lce_ops = {
.dl_establish_cfm = dl_establish_cfm,
};
static struct dect_ops ops = {
.lce_ops = &lce_ops,
};
int main(int argc, char **argv)
{
struct dect_mac_conn_params mcp = {};
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
dect_dl_establish_req(dh, &ipui, &mcp);
dect_event_loop();
dect_common_cleanup(dh);

View File

@ -38,25 +38,39 @@ static int mm_info_req(struct dect_handle *dh, struct dect_mm_endpoint *mme)
}
static struct dect_mm_ops mm_ops = {
.mm_info_cfm = mm_info_cfm,
.mm_info_cfm = mm_info_cfm,
};
static struct dect_ops ops = {
.mm_ops = &mm_ops,
};
int main(int argc, char **argv)
static void dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
struct dect_mm_endpoint *mme;
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
mme = dect_mm_endpoint_alloc(dh, &ipui);
mme = dect_mm_endpoint_alloc(dh, ddl);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_info_req(dh, mme);
}
static struct dect_lce_ops lce_ops = {
.dl_establish_cfm = dl_establish_cfm,
};
static struct dect_ops ops = {
.lce_ops = &lce_ops,
.mm_ops = &mm_ops,
};
int main(int argc, char **argv)
{
struct dect_mac_conn_params mcp = {};
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
dect_dl_establish_req(dh, &ipui, &mcp);
dect_event_loop();
dect_common_cleanup(dh);

View File

@ -32,15 +32,28 @@ static void dect_iwu_info_req(struct dect_handle *dh, struct dect_call *call)
dect_mncc_iwu_info_req(dh, call, &req);
}
static void dect_mncc_connect_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_connect_param *param)
static void dect_mncc_call_proc_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_call_proc_param *param)
{
struct dect_mncc_connect_param reply = {};
dect_mncc_connect_res(dh, call, &reply);
dect_iwu_info_req(dh, call);
}
static void dect_mncc_reject_ind(struct dect_handle *dh, struct dect_call *call,
enum dect_causes cause,
struct dect_mncc_release_param *param)
{
dect_event_loop_stop();
}
static void dect_mncc_release_ind(struct dect_handle *dh, struct dect_call *call,
struct dect_mncc_release_param *param)
{
struct dect_mncc_release_param res = {};
dect_mncc_release_res(dh, call, &res);
dect_event_loop_stop();
}
static void dect_open_call(struct dect_handle *dh, const struct dect_ipui *ipui)
{
struct dect_ie_basic_service basic_service;
@ -53,23 +66,41 @@ static void dect_open_call(struct dect_handle *dh, const struct dect_ipui *ipui)
if (call == NULL)
return;
basic_service.class = DECT_CALL_CLASS_NORMAL;
basic_service.service = DECT_SERVICE_BASIC_SPEECH_DEFAULT;
basic_service.class = DECT_CALL_CLASS_LIA_SERVICE_SETUP;
basic_service.service = DECT_SERVICE_WIDEBAND_SPEECH;
dect_mncc_setup_req(dh, call, ipui, &req);
}
static void dect_dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
dect_open_call(dh, &ipui);
}
static struct dect_cc_ops cc_ops = {
.mncc_connect_ind = dect_mncc_connect_ind,
.mncc_call_proc_ind = dect_mncc_call_proc_ind,
.mncc_release_ind = dect_mncc_release_ind,
.mncc_reject_ind = dect_mncc_reject_ind,
};
static struct dect_lce_ops lce_ops = {
.dl_establish_cfm = dect_dl_establish_cfm,
};
static struct dect_ops ops = {
.lce_ops = &lce_ops,
.cc_ops = &cc_ops,
};
int main(int argc, char **argv)
{
const struct dect_fp_capabilities *fpc;
struct dect_mac_conn_params mcp = {
.service = DECT_SERVICE_IN_MIN_DELAY,
.slot = DECT_LONG_SLOT_640,
};
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
@ -80,7 +111,7 @@ int main(int argc, char **argv)
goto out;
}
dect_open_call(dh, &ipui);
dect_dl_establish_req(dh, &ipui, &mcp);
dect_event_loop();
out:
dect_common_cleanup(dh);

View File

@ -47,18 +47,36 @@ static int mm_locate_req(struct dect_handle *dh, struct dect_mm_endpoint *mme)
return dect_mm_locate_req(dh, mme, &param);
}
static void dl_establish_cfm(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp)
{
struct dect_mm_endpoint *mme;
mme = dect_mm_endpoint_alloc(dh, ddl);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_locate_req(dh, mme);
}
static struct dect_mm_ops mm_ops = {
.mm_locate_cfm = mm_locate_cfm,
};
static struct dect_lce_ops lce_ops = {
.dl_establish_cfm = dl_establish_cfm,
};
static struct dect_ops ops = {
.lce_ops = &lce_ops,
.mm_ops = &mm_ops,
};
int main(int argc, char **argv)
{
const struct dect_fp_capabilities *fpc;
struct dect_mm_endpoint *mme;
struct dect_mac_conn_params mcp = {};
dect_pp_common_options(argc, argv);
dect_pp_common_init(&ops, cluster, &ipui);
@ -69,11 +87,7 @@ int main(int argc, char **argv)
goto out;
}
mme = dect_mm_endpoint_alloc(dh, &ipui);
if (mme == NULL)
pexit("dect_mm_endpoint_alloc");
mm_locate_req(dh, mme);
dect_dl_establish_req(dh, &ipui, &mcp);
dect_event_loop();
out:
dect_common_cleanup(dh);

View File

@ -2083,11 +2083,11 @@ enum dect_mac_dlc_service {
/** Slot sizes */
enum dect_slot_size {
DECT_HALF_SLOT = 0x0, /**< Half slot; j = 0. */
DECT_LONG_SLOT_640 = 0x1, /**< Long slot; j = 640 */
DECT_LONG_SLOT_672 = 0x2, /**< Long slot; j = 640 */
DECT_FULL_SLOT = 0x4, /**< Full slot */
DECT_DOUBLE_SLOT = 0x5, /**< Double slot */
DECT_HALF_SLOT_SIZE = 0x0, /**< Half slot; j = 0. */
DECT_LONG_SLOT_640_SIZE = 0x1, /**< Long slot; j = 640 */
DECT_LONG_SLOT_672_SIZE = 0x2, /**< Long slot; j = 640 */
DECT_FULL_SLOT_SIZE = 0x4, /**< Full slot */
DECT_DOUBLE_SLOT_SIZE = 0x5, /**< Double slot */
};
/** C-Plane routing options */

View File

@ -28,6 +28,9 @@ struct dect_lce_page_param {
struct dect_ie_escape_to_proprietary *escape_to_proprietary;
};
struct dect_mac_conn_params;
struct dect_data_link;
/**
* Link Control Entity Ops.
*
@ -36,16 +39,26 @@ struct dect_lce_page_param {
*/
struct dect_lce_ops {
bool (*lce_page_response)(struct dect_handle *dh,
struct dect_data_link *ddl,
struct dect_lce_page_param *param);
/**< LCE_PAGE_RESPONSE-ind primitive */
void (*lce_group_ring_ind)(struct dect_handle *dh,
enum dect_alerting_patterns pattern);
/**< LCE_GROUP_RING-ind primitive */
void (*dl_establish_cfm)(struct dect_handle *dh, bool success,
struct dect_data_link *ddl,
const struct dect_mac_conn_params *mcp);
/**< DL_ESTABLISH-cfm primitive */
};
extern int dect_lce_group_ring_req(struct dect_handle *dh,
enum dect_alerting_patterns pattern);
extern int dect_dl_establish_req(struct dect_handle *dh, const struct dect_ipui *ipui,
const struct dect_mac_conn_params *mcp);
/** @} */
#ifdef __cplusplus

View File

@ -231,9 +231,7 @@ struct dect_mm_iwu_param {
struct dect_mm_endpoint;
extern struct dect_mm_endpoint *dect_mm_endpoint_alloc(struct dect_handle *dh,
const struct dect_ipui *ipui);
extern struct dect_mm_endpoint *dect_mm_endpoint_get(struct dect_handle *dh,
const struct dect_ipui *ipui);
struct dect_data_link *ddl);
extern void dect_mm_endpoint_destroy(struct dect_handle *dh,
struct dect_mm_endpoint *mme);
extern void *dect_mm_priv(struct dect_mm_endpoint *mme);

View File

@ -183,9 +183,10 @@ enum dect_data_link_flags {
* struct dect_data_link
*
* @list: DECT handle link list node
* @dfd: Associated socket file descriptor
* @dlei: Data Link Endpoint identifier
* @ipui: International Portable User ID
* @dfd: Associated socket file descriptor
* @mcp: MAC connections parameters
* @state: Data link state
* @sdu_timer: Establish without SDU timer (LCE.05)
* @release_timer: Normal link release timer (LCE.01)
@ -198,6 +199,7 @@ struct dect_data_link {
struct sockaddr_dect_ssap dlei;
struct dect_ipui ipui;
struct dect_fd *dfd;
struct dect_mac_conn_params mcp;
enum dect_data_link_states state;
enum dect_cipher_states cipher;
struct dect_timer *sdu_timer;

244
src/lce.c
View File

@ -361,6 +361,28 @@ static const char * const ddl_states[DECT_DATA_LINK_STATE_MAX + 1] = {
[DECT_DATA_LINK_RESUME_PENDING] = "RESUME_PENDING",
};
static const struct dect_trans_tbl dect_conn_types[] = {
TRANS_TBL(DECT_MAC_CONN_BASIC, "basic"),
TRANS_TBL(DECT_MAC_CONN_ADVANCED, "advanced"),
};
static const struct dect_trans_tbl dect_slot_types[] = {
TRANS_TBL(DECT_FULL_SLOT, "full slot"),
TRANS_TBL(DECT_HALF_SLOT, "half slot"),
TRANS_TBL(DECT_DOUBLE_SLOT, "double slot"),
TRANS_TBL(DECT_LONG_SLOT_640, "long slot j=640"),
TRANS_TBL(DECT_LONG_SLOT_672, "long slot j=672"),
};
static const struct dect_trans_tbl dect_service_types[] = {
TRANS_TBL(DECT_SERVICE_IN_MIN_DELAY, "In_minimum_delay"),
TRANS_TBL(DECT_SERVICE_IN_NORMAL_DELAY, "In_normal_delay"),
TRANS_TBL(DECT_SERVICE_UNKNOWN, "unknown"),
TRANS_TBL(DECT_SERVICE_C_CHANNEL_ONLY, "C channel only"),
TRANS_TBL(DECT_SERVICE_IP_ERROR_DETECTION, "Ip_error_detection"),
TRANS_TBL(DECT_SERVICE_IPQ_ERROR_DETECTION, "Ipq_error_detection"),
};
int dect_ddl_set_ipui(struct dect_handle *dh, struct dect_data_link *ddl,
const struct dect_ipui *ipui)
{
@ -846,17 +868,36 @@ static void dect_ddl_complete_direct_establish(struct dect_handle *dh,
struct dect_data_link *ddl)
{
struct dect_msg_buf *mb;
socklen_t optlen;
char buf1[128], buf2[128], buf3[128];
dect_fd_unregister(dh, ddl->dfd);
if (dect_fd_register(dh, ddl->dfd, DECT_FD_READ) < 0)
goto err1;
optlen = sizeof(ddl->mcp);
if (getsockopt(ddl->dfd->fd, SOL_DECT, DECT_DL_MAC_CONN_PARAMS,
&ddl->mcp, &optlen))
goto err1;
ddl->state = DECT_DATA_LINK_ESTABLISHED;
ddl_debug(ddl, "complete direct link establishment");
dect_fd_unregister(dh, ddl->dfd);
if (dect_fd_register(dh, ddl->dfd, DECT_FD_READ) < 0)
return dect_ddl_shutdown(dh, ddl);
ddl_debug(ddl, "MAC connection: type: %s service: %s slot: %s",
dect_val2str(dect_conn_types, buf1, ddl->mcp.type),
dect_val2str(dect_service_types, buf2, ddl->mcp.service),
dect_val2str(dect_slot_types, buf3, ddl->mcp.slot));
ddl_debug(ddl, "DL_ESTABLISH-cfm: success: 1");
dh->ops->lce_ops->dl_establish_cfm(dh, true, ddl, &ddl->mcp);
/* Send queued messages */
while ((mb = ptrlist_dequeue_head(&ddl->msg_queue)))
dect_ddl_send(dh, ddl, mb);
return;
err1:
dect_ddl_shutdown(dh, ddl);
}
static void dect_ddl_complete_indirect_establish(struct dect_handle *dh,
@ -893,6 +934,9 @@ static void dect_ddl_complete_indirect_establish(struct dect_handle *dh,
/* Release pending link */
dect_ddl_destroy(dh, req);
ddl_debug(ddl, "DL_ESTABLISH-cfm: success: 1");
dh->ops->lce_ops->dl_establish_cfm(dh, true, ddl, &ddl->mcp);
/* If the link was established for a connectionless transmission,
* no transaction exists. Perform a partial release. */
if (list_empty(&ddl->transactions))
@ -903,17 +947,24 @@ static void dect_ddl_page_timer(struct dect_handle *dh, struct dect_timer *timer
static void dect_lce_data_link_event(struct dect_handle *dh,
struct dect_fd *dfd, uint32_t events);
static const struct dect_mac_conn_params default_mcp = {
.service = DECT_SERVICE_IN_MIN_DELAY,
.slot = DECT_FULL_SLOT,
};
/**
* dect_ddl_establish - Establish an outgoing data link
*/
static struct dect_data_link *dect_ddl_establish(struct dect_handle *dh,
const struct dect_ipui *ipui)
const struct dect_ipui *ipui,
const struct dect_mac_conn_params *mcp)
{
struct dect_data_link *ddl;
ddl = dect_ddl_alloc(dh);
if (ddl == NULL)
goto err1;
ddl->mcp = mcp ? *mcp : default_mcp;
ddl->state = DECT_DATA_LINK_ESTABLISH_PENDING;
dect_ddl_set_ipui(dh, ddl, ipui);
@ -936,6 +987,11 @@ static struct dect_data_link *dect_ddl_establish(struct dect_handle *dh,
ddl->dlei.dect_lln = 1;
ddl->dlei.dect_sapi = 0;
if (mcp != NULL &&
setsockopt(ddl->dfd->fd, SOL_DECT, DECT_DL_MAC_CONN_PARAMS,
mcp, sizeof(*mcp)) < 0)
goto err2;
dect_fd_setup(ddl->dfd, dect_lce_data_link_event, ddl);
if (dect_fd_register(dh, ddl->dfd, DECT_FD_WRITE) < 0)
goto err2;
@ -957,6 +1013,16 @@ err1:
return NULL;
}
int dect_dl_establish_req(struct dect_handle *dh, const struct dect_ipui *ipui,
const struct dect_mac_conn_params *mcp)
{
lce_debug("DL_ESTABLISH-req: IPUI: N EMC: %04x PSN: %05x\n",
ipui->pun.n.ipei.emc, ipui->pun.n.ipei.psn);
dect_ddl_establish(dh, ipui, mcp);
return 0;
}
EXPORT_SYMBOL(dect_dl_establish_req);
struct dect_data_link *dect_ddl_connect(struct dect_handle *dh,
const struct dect_ipui *ipui)
{
@ -964,7 +1030,7 @@ struct dect_data_link *dect_ddl_connect(struct dect_handle *dh,
ddl = dect_ddl_get_by_ipui(dh, ipui);
if (ddl == NULL)
ddl = dect_ddl_establish(dh, ipui);
ddl = dect_ddl_establish(dh, ipui, NULL);
return ddl;
}
@ -1004,6 +1070,8 @@ static void dect_lce_ssap_listener_event(struct dect_handle *dh,
{
struct dect_data_link *ddl;
struct dect_fd *nfd;
socklen_t optlen;
char buf1[128], buf2[128], buf3[128];
dect_debug(DECT_DEBUG_LCE, "\n");
ddl = dect_ddl_alloc(dh);
@ -1016,6 +1084,11 @@ static void dect_lce_ssap_listener_event(struct dect_handle *dh,
goto err2;
ddl->dfd = nfd;
optlen = sizeof(ddl->mcp);
if (getsockopt(nfd->fd, SOL_DECT, DECT_DL_MAC_CONN_PARAMS,
&ddl->mcp, &optlen))
goto err3;
dect_fd_setup(nfd, dect_lce_data_link_event, ddl);
if (dect_fd_register(dh, nfd, DECT_FD_READ) < 0)
goto err3;
@ -1028,6 +1101,10 @@ static void dect_lce_ssap_listener_event(struct dect_handle *dh,
ddl_debug(ddl, "new link: PMID: %x LCN: %u LLN: %u SAPI: %u",
ddl->dlei.dect_pmid, ddl->dlei.dect_lcn,
ddl->dlei.dect_lln, ddl->dlei.dect_sapi);
ddl_debug(ddl, "MAC connection: type: %s service: %s slot: %s",
dect_val2str(dect_conn_types, buf1, ddl->mcp.type),
dect_val2str(dect_service_types, buf2, ddl->mcp.service),
dect_val2str(dect_slot_types, buf3, ddl->mcp.slot));
return;
err4:
@ -1084,6 +1161,94 @@ ssize_t dect_lce_broadcast(const struct dect_handle *dh,
return 0;
}
static enum lce_request_page_hdr_codes
dect_page_service_to_hdr(enum dect_mac_service_types service)
{
switch (service) {
case DECT_SERVICE_IN_MIN_DELAY:
return DECT_LCE_PAGE_GENERAL_VOICE;
case DECT_SERVICE_IN_NORMAL_DELAY:
return DECT_LCE_PAGE_AUXILIARY;
case DECT_SERVICE_UNKNOWN:
return DECT_LCE_PAGE_UNKNOWN_RINGING;
case DECT_SERVICE_C_CHANNEL_ONLY:
return DECT_LCE_PAGE_U_PLANE_NONE;
default:
return DECT_LCE_PAGE_GENERAL_PURPOSE;
}
}
static enum dect_mac_service_types
dect_page_hdr_to_service(enum lce_request_page_hdr_codes hdr)
{
switch (hdr) {
case DECT_LCE_PAGE_U_PLANE_NONE:
return DECT_SERVICE_C_CHANNEL_ONLY;
case DECT_LCE_PAGE_UNKNOWN_RINGING:
return DECT_SERVICE_UNKNOWN;
case DECT_LCE_PAGE_GENERAL_PURPOSE:
return DECT_SERVICE_UNKNOWN;
case DECT_LCE_PAGE_GENERAL_VOICE:
return DECT_SERVICE_IN_MIN_DELAY;
case DECT_LCE_PAGE_AUXILIARY:
return DECT_SERVICE_IN_NORMAL_DELAY;
default:
BUG(); // FIXME
}
}
static enum dect_request_page_slot_types
dect_page_slot_to_info(enum dect_slot_types slot)
{
switch (slot) {
case DECT_FULL_SLOT:
return DECT_LCE_PAGE_FULL_SLOT;
case DECT_HALF_SLOT:
return DECT_LCE_PAGE_HALF_SLOT;
case DECT_DOUBLE_SLOT:
return DECT_LCE_PAGE_DOUBLE_SLOT;
case DECT_LONG_SLOT_640:
return DECT_LCE_PAGE_LONG_SLOT_J640;
case DECT_LONG_SLOT_672:
return DECT_LCE_PAGE_LONG_SLOT_J672;
default:
BUG();
}
}
static enum dect_slot_types
dect_page_info_to_slot(enum dect_request_page_slot_types slot)
{
/* 8.2.4.2: backwards compatibility: bit 8 indicates "full slot" */
if (slot & 0x80)
return DECT_FULL_SLOT;
switch (slot) {
case DECT_LCE_PAGE_HALF_SLOT:
return DECT_HALF_SLOT;
case DECT_LCE_PAGE_LONG_SLOT_J640:
return DECT_LONG_SLOT_640;
case DECT_LCE_PAGE_LONG_SLOT_J672:
return DECT_LONG_SLOT_672;
case DECT_LCE_PAGE_FULL_SLOT:
return DECT_FULL_SLOT;
case DECT_LCE_PAGE_DOUBLE_SLOT:
return DECT_DOUBLE_SLOT;
default:
BUG(); // FIXME
}
}
static enum dect_request_page_setup_info
dect_page_service_to_setup_info(const struct dect_mac_conn_params *mcp)
{
if (mcp->service == DECT_SERVICE_IN_MIN_DELAY &&
mcp->slot == DECT_FULL_SLOT)
return DECT_LCE_PAGE_BASIC_CONN_ATTR_OPTIONAL;
else
return DECT_LCE_PAGE_NO_SETUP_INFO;
}
/**
* Request collective or group ringing
*
@ -1113,7 +1278,8 @@ int dect_lce_group_ring_req(struct dect_handle *dh,
EXPORT_SYMBOL(dect_lce_group_ring_req);
static int dect_lce_send_short_page(const struct dect_handle *dh,
const struct dect_ipui *ipui)
const struct dect_ipui *ipui,
const struct dect_mac_conn_params *mcp)
{
DECT_DEFINE_MSG_BUF_ONSTACK(_mb), *mb = &_mb;
struct dect_short_page_msg *msg;
@ -1123,7 +1289,7 @@ static int dect_lce_send_short_page(const struct dect_handle *dh,
uint16_t page;
msg = dect_mbuf_put(mb, sizeof(*msg));
msg->hdr = DECT_LCE_PAGE_GENERAL_VOICE;
msg->hdr = dect_page_service_to_hdr(mcp->service);
tpui = dect_tpui(dh, ipui);
if (tpui == NULL)
@ -1142,7 +1308,8 @@ static int dect_lce_send_short_page(const struct dect_handle *dh,
}
static int dect_lce_send_full_page(const struct dect_handle *dh,
const struct dect_ipui *ipui)
const struct dect_ipui *ipui,
const struct dect_mac_conn_params *mcp)
{
DECT_DEFINE_MSG_BUF_ONSTACK(_mb), *mb = &_mb;
struct dect_full_page_msg *msg;
@ -1153,7 +1320,7 @@ static int dect_lce_send_full_page(const struct dect_handle *dh,
uint32_t page;
msg = dect_mbuf_put(mb, sizeof(*msg));
msg->hdr = DECT_LCE_PAGE_GENERAL_VOICE;
msg->hdr = dect_page_service_to_hdr(mcp->service);
if (1) {
msg->hdr |= DECT_LCE_PAGE_W_FLAG;
@ -1163,9 +1330,9 @@ static int dect_lce_send_full_page(const struct dect_handle *dh,
tpui = dect_ipui_to_tpui(&_tpui, ipui);
page = dect_build_tpui(tpui) << DECT_LCE_FULL_PAGE_TPUI_SHIFT;
page |= DECT_LCE_PAGE_FULL_SLOT <<
page |= dect_page_slot_to_info(mcp->slot) <<
DECT_LCE_FULL_PAGE_SLOT_TYPE_SHIFT;
page |= DECT_LCE_PAGE_BASIC_CONN_ATTR_OPTIONAL <<
page |= dect_page_service_to_setup_info(mcp) <<
DECT_LCE_FULL_PAGE_SETUP_INFO_SHIFT;
} else {
dect_build_ipui(ipui_buf, ipui);
@ -1185,12 +1352,14 @@ static int dect_lce_send_full_page(const struct dect_handle *dh,
}
static int dect_lce_page(const struct dect_handle *dh,
const struct dect_ipui *ipui)
const struct dect_ipui *ipui,
const struct dect_mac_conn_params *mcp)
{
if (dect_profile_indicator(dh, ipui) & DECT_PROFILE_NG_DECT_PART_1)
return dect_lce_send_full_page(dh, ipui);
if (mcp->service == DECT_SERVICE_IN_MIN_DELAY &&
mcp->slot == DECT_FULL_SLOT)
return dect_lce_send_short_page(dh, ipui, mcp);
else
return dect_lce_send_short_page(dh, ipui);
return dect_lce_send_full_page(dh, ipui, mcp);
}
static void dect_ddl_page_timer(struct dect_handle *dh, struct dect_timer *timer)
@ -1202,10 +1371,12 @@ static void dect_ddl_page_timer(struct dect_handle *dh, struct dect_timer *timer
ddl_debug(ddl, "<LCE.03>: Page timer");
}
if (ddl->page_count++ == DECT_DDL_PAGE_RETRANS_MAX)
if (ddl->page_count++ == DECT_DDL_PAGE_RETRANS_MAX) {
ddl_debug(ddl, "DL_ESTABLISH-cfm: success: 0");
dh->ops->lce_ops->dl_establish_cfm(dh, false, NULL, NULL);
dect_ddl_shutdown(dh, ddl);
else {
dect_lce_page(dh, &ddl->ipui);
} else {
dect_lce_page(dh, &ddl->ipui, &ddl->mcp);
dect_timer_start(dh, ddl->page_timer, DECT_DDL_PAGE_TIMEOUT);
}
}
@ -1269,7 +1440,7 @@ static void dect_lce_rcv_page_response(struct dect_handle *dh,
param->cipher_info = dect_ie_hold(msg.cipher_info);
param->escape_to_proprietary = dect_ie_hold(msg.escape_to_proprietary);
reject = !dh->ops->lce_ops->lce_page_response(dh, param);
reject = !dh->ops->lce_ops->lce_page_response(dh, ta->link, param);
dect_ie_collection_put(dh, param);
}
err:
@ -1297,8 +1468,10 @@ static void dect_lce_rcv_page_reject(struct dect_handle *dh,
dect_msg_free(dh, &lce_page_reject_msg_desc, &msg.common);
}
static void dect_lce_send_page_response(struct dect_handle *dh)
static void dect_lce_send_page_response(struct dect_handle *dh,
const struct dect_mac_conn_params *mcp)
{
struct dect_data_link *ddl;
struct dect_ie_portable_identity portable_identity;
struct dect_ie_fixed_identity fixed_identity;
struct dect_lce_page_response_msg msg = {
@ -1312,12 +1485,20 @@ static void dect_lce_send_page_response(struct dect_handle *dh)
fixed_identity.type = DECT_FIXED_ID_TYPE_PARK;
fixed_identity.ari = dh->pari;
if (dect_transaction_open(dh, &dh->page_transaction, &dh->ipui,
DECT_PD_LCE) < 0)
ddl = dect_ddl_establish(dh, &dh->ipui, mcp);
if (ddl == NULL)
return;
if (dect_ddl_transaction_open(dh, &dh->page_transaction, ddl,
DECT_PD_LCE) < 0)
goto err1;
dect_lce_send(dh, &dh->page_transaction, &lce_page_response_msg_desc,
&msg.common, DECT_LCE_PAGE_RESPONSE);
return;
err1:
dect_ddl_destroy(dh, ddl);
}
static void dect_lce_rcv_short_page(struct dect_handle *dh,
@ -1363,7 +1544,7 @@ static void dect_lce_rcv_short_page(struct dect_handle *dh,
return;
}
dect_lce_send_page_response(dh);
dect_lce_send_page_response(dh, NULL);
}
}
@ -1371,9 +1552,10 @@ static void dect_lce_rcv_full_page(struct dect_handle *dh,
struct dect_msg_buf *mb)
{
struct dect_full_page_msg *msg = (void *)mb->data;
struct dect_mac_conn_params mcp;
uint32_t info, ipui, tpui, t;
uint8_t ipui_buf[8];
uint8_t hdr, pattern;
uint8_t hdr, pattern, slot, setup;
bool w;
w = msg->hdr & DECT_LCE_PAGE_W_FLAG;
@ -1399,6 +1581,8 @@ static void dect_lce_rcv_full_page(struct dect_handle *dh,
lce_debug("LCE_GROUP_RING-ind: pattern: %x\n", pattern);
dh->ops->lce_ops->lce_group_ring_ind(dh, pattern);
} else {
memset(&mcp, 0, sizeof(mcp));
if (w == 0) {
/* IPUI */
dect_build_ipui(ipui_buf, &dh->ipui);
@ -1416,11 +1600,19 @@ static void dect_lce_rcv_full_page(struct dect_handle *dh,
DECT_LCE_FULL_PAGE_TPUI_SHIFT;
t = dect_build_tpui(&dh->tpui);
if (tpui != t && tpui != DECT_TPUI_CBI)
if (0 && tpui != t && tpui != DECT_TPUI_CBI)
return;
slot = (info & DECT_LCE_FULL_PAGE_SLOT_TYPE_MASK) >>
DECT_LCE_FULL_PAGE_SLOT_TYPE_SHIFT;
setup = (info & DECT_LCE_FULL_PAGE_SETUP_INFO_MASK) >>
DECT_LCE_FULL_PAGE_SETUP_INFO_SHIFT;
mcp.service = dect_page_hdr_to_service(hdr);
mcp.slot = dect_page_info_to_slot(slot);
}
dect_lce_send_page_response(dh);
dect_lce_send_page_response(dh, &mcp);
}
}

View File

@ -522,22 +522,8 @@ dect_mm_endpoint_get_by_link(const struct dect_handle *dh,
return NULL;
}
struct dect_mm_endpoint *dect_mm_endpoint_get(struct dect_handle *dh,
const struct dect_ipui *ipui)
{
struct dect_mm_endpoint *mme;
list_for_each_entry(mme, &dh->mme_list, list) {
if (!dect_ipui_cmp(&mme->link->ipui, ipui))
return mme;
}
return dect_mm_endpoint_alloc(dh, ipui);
}
EXPORT_SYMBOL(dect_mm_endpoint_get);
struct dect_mm_endpoint *dect_mm_endpoint_alloc(struct dect_handle *dh,
const struct dect_ipui *ipui)
struct dect_data_link *ddl)
{
struct dect_mm_endpoint *mme;
@ -548,17 +534,11 @@ struct dect_mm_endpoint *dect_mm_endpoint_alloc(struct dect_handle *dh,
goto err2;
if (dect_mm_procedure_init(dh, mme, DECT_TRANSACTION_RESPONDER) < 0)
goto err3;
if (ipui != NULL) {
mme->link = dect_ddl_connect(dh, ipui);
if (mme->link == NULL)
goto err4;
}
mme->link = ddl;
list_add_tail(&mme->list, &dh->mme_list);
return mme;
err4:
dect_timer_free(dh, mme->procedure[DECT_TRANSACTION_RESPONDER].timer);
err3:
dect_timer_free(dh, mme->procedure[DECT_TRANSACTION_INITIATOR].timer);
@ -3245,10 +3225,9 @@ static void dect_mm_open(struct dect_handle *dh,
mme = dect_mm_endpoint_get_by_link(dh, req->link);
if (mme == NULL) {
mme = dect_mm_endpoint_alloc(dh, NULL);
mme = dect_mm_endpoint_alloc(dh, req->link);
if (mme == NULL)
return;
mme->link = req->link;
}
ta = &mme->procedure[DECT_TRANSACTION_RESPONDER].transaction;

View File

@ -2011,11 +2011,11 @@ static const struct dect_trans_tbl dect_mac_dlc_services[] = {
};
static const struct dect_trans_tbl dect_slot_sizes[] = {
TRANS_TBL(DECT_HALF_SLOT, "half slot"),
TRANS_TBL(DECT_LONG_SLOT_640, "long slot j=640"),
TRANS_TBL(DECT_LONG_SLOT_672, "long slot j=672"),
TRANS_TBL(DECT_FULL_SLOT, "full slot"),
TRANS_TBL(DECT_DOUBLE_SLOT, "double slot"),
TRANS_TBL(DECT_HALF_SLOT_SIZE, "half slot"),
TRANS_TBL(DECT_LONG_SLOT_640_SIZE, "long slot j=640"),
TRANS_TBL(DECT_LONG_SLOT_672_SIZE, "long slot j=672"),
TRANS_TBL(DECT_FULL_SLOT_SIZE, "full slot"),
TRANS_TBL(DECT_DOUBLE_SLOT_SIZE, "double slot"),
};
static const struct dect_trans_tbl dect_cplane_routing[] = {