From ecc2c7d990d0e2f5c8a9511d208e38290b9969f8 Mon Sep 17 00:00:00 2001 From: Patrick McHardy Date: Wed, 5 Oct 2011 19:06:54 +0200 Subject: [PATCH] libdect: add preliminary wideband support Unfinished, so far only meant for testing the kernel side. Signed-off-by: Patrick McHardy --- example/dummy_ops.c | 9 + example/fp-locate-suggest.c | 39 ++++- example/hijack.c | 17 +- example/pp-access-rights-terminate.c | 32 +++- example/pp-access-rights.c | 25 ++- example/pp-detach.c | 29 +++- example/pp-info-request.c | 34 ++-- example/pp-list-access.c | 49 +++++- example/pp-location-update.c | 26 ++- include/dect/ie.h | 10 +- include/dect/lce.h | 13 ++ include/dect/mm.h | 4 +- include/lce.h | 4 +- src/lce.c | 244 ++++++++++++++++++++++++--- src/mm.c | 27 +-- src/s_msg.c | 10 +- 16 files changed, 451 insertions(+), 121 deletions(-) diff --git a/example/dummy_ops.c b/example/dummy_ops.c index e33b940..4641592 100644 --- a/example/dummy_ops.c +++ b/example/dummy_ops.c @@ -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; diff --git a/example/fp-locate-suggest.c b/example/fp-locate-suggest.c index 9f16d3d..82f709d 100644 --- a/example/fp-locate-suggest.c +++ b/example/fp-locate-suggest.c @@ -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); diff --git a/example/hijack.c b/example/hijack.c index cb4f43b..ecad978 100644 --- a/example/hijack.c +++ b/example/hijack.c @@ -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, ¶m->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, }; diff --git a/example/pp-access-rights-terminate.c b/example/pp-access-rights-terminate.c index 210f06e..5991d39 100644 --- a/example/pp-access-rights-terminate.c +++ b/example/pp-access-rights-terminate.c @@ -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); diff --git a/example/pp-access-rights.c b/example/pp-access-rights.c index 1162d5d..f4b2333 100644 --- a/example/pp-access-rights.c +++ b/example/pp-access-rights.c @@ -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, ¶m); } +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); diff --git a/example/pp-detach.c b/example/pp-detach.c index 70c2530..8b1f1ae 100644 --- a/example/pp-detach.c +++ b/example/pp-detach.c @@ -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, ¶m); } -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); diff --git a/example/pp-info-request.c b/example/pp-info-request.c index 6310c6c..8a52286 100644 --- a/example/pp-info-request.c +++ b/example/pp-info-request.c @@ -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); diff --git a/example/pp-list-access.c b/example/pp-list-access.c index d58acae..72bbe32 100644 --- a/example/pp-list-access.c +++ b/example/pp-list-access.c @@ -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); diff --git a/example/pp-location-update.c b/example/pp-location-update.c index 099fbc0..d7c19f3 100644 --- a/example/pp-location-update.c +++ b/example/pp-location-update.c @@ -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, ¶m); } +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); diff --git a/include/dect/ie.h b/include/dect/ie.h index e05bb67..36d3805 100644 --- a/include/dect/ie.h +++ b/include/dect/ie.h @@ -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 */ diff --git a/include/dect/lce.h b/include/dect/lce.h index 5126e6b..b207c34 100644 --- a/include/dect/lce.h +++ b/include/dect/lce.h @@ -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 diff --git a/include/dect/mm.h b/include/dect/mm.h index f2e0e06..b055044 100644 --- a/include/dect/mm.h +++ b/include/dect/mm.h @@ -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); diff --git a/include/lce.h b/include/lce.h index 6b00538..4b3d615 100644 --- a/include/lce.h +++ b/include/lce.h @@ -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; diff --git a/src/lce.c b/src/lce.c index 8aae519..95a8274 100644 --- a/src/lce.c +++ b/src/lce.c @@ -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, ": 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); } } diff --git a/src/mm.c b/src/mm.c index 54d7c6f..4d54220 100644 --- a/src/mm.c +++ b/src/mm.c @@ -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; diff --git a/src/s_msg.c b/src/s_msg.c index ca09ba8..da83e8c 100644 --- a/src/s_msg.c +++ b/src/s_msg.c @@ -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[] = {