diff --git a/example/ss.c b/example/ss.c index bf9dc80..f45e9f6 100644 --- a/example/ss.c +++ b/example/ss.c @@ -34,13 +34,13 @@ static void dect_invoke_ss(struct dect_handle *dh, const struct dect_ipui *ipui) .feature_activate = &feature_activate, }; - sse = dect_ss_endpoint_alloc(dh); + sse = dect_ss_endpoint_alloc(dh, ipui); if (sse == NULL) return; feature_activate.feature = DECT_FEATURE_INDICATION_OF_SUBSCRIBER_NUMBER; - dect_mnss_setup_req(dh, sse, ipui, ¶m); + dect_mnss_setup_req(dh, sse, ¶m); } static struct dect_ss_ops ss_ops = { diff --git a/include/dect/ss.h b/include/dect/ss.h index 547effd..f1f7ef8 100644 --- a/include/dect/ss.h +++ b/include/dect/ss.h @@ -38,7 +38,8 @@ 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); +extern struct dect_ss_endpoint *dect_ss_endpoint_alloc(struct dect_handle *dh, + const struct dect_ipui *ipui); extern void dect_ss_endpoint_destroy(struct dect_handle *dh, struct dect_ss_endpoint *sse); /** @@ -62,7 +63,6 @@ struct dect_ss_ops { }; 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); diff --git a/include/lce.h b/include/lce.h index 2e010e3..e7bab06 100644 --- a/include/lce.h +++ b/include/lce.h @@ -56,7 +56,6 @@ enum dect_release_modes { * @role: Role (initiator/responder) * @tv: Transaction value */ -enum dect_s_pd_values; struct dect_transaction { struct list_head list; struct dect_data_link *link; @@ -96,6 +95,11 @@ extern int dect_lce_send(const struct dect_handle *dh, extern int dect_lce_retransmit(const struct dect_handle *dh, struct dect_transaction *ta); +extern int dect_lce_send_cl(struct dect_handle *dh, const struct dect_ipui *ipui, + const struct dect_sfmt_msg_desc *desc, + const struct dect_msg_common *msg, + enum dect_pds pd, uint8_t type); + extern ssize_t dect_lce_broadcast(const struct dect_handle *dh, const struct dect_msg_buf *mb, bool long_page); diff --git a/include/ss.h b/include/ss.h index 90801fd..a2075a0 100644 --- a/include/ss.h +++ b/include/ss.h @@ -55,10 +55,12 @@ struct dect_ciss_register_msg { /** * struct dect_ss_endpoint - Supplementary Services Endpoint * + * @ipui: PT's IPUI * @transaction: LCE link transaction * @priv: libdect user private storage */ struct dect_ss_endpoint { + struct dect_ipui ipui; struct dect_transaction transaction; uint8_t priv[] __aligned(__alignof__(uint64_t)); }; diff --git a/src/lce.c b/src/lce.c index 10d2c98..f9ebac6 100644 --- a/src/lce.c +++ b/src/lce.c @@ -542,6 +542,38 @@ static ssize_t dect_ddl_send(const struct dect_handle *dh, return size; } +static struct dect_msg_buf * +dect_lce_build_msg(const struct dect_handle *dh, + const struct dect_transaction *ta, + const struct dect_sfmt_msg_desc *desc, + const struct dect_msg_common *msg, uint8_t type) +{ + struct dect_msg_buf *mb; + int err; + + mb = dect_mbuf_alloc(dh); + if (mb == NULL) + goto err1; + + dect_mbuf_reserve(mb, DECT_S_HDR_SIZE); + err = dect_build_sfmt_msg(dh, desc, msg, mb); + if (err < 0) + goto err2; + + dect_mbuf_push(mb, DECT_S_HDR_SIZE); + mb->data[1] = type; + mb->data[0] = ta->pd; + mb->data[0] |= ta->tv << DECT_S_TI_TV_SHIFT; + if (ta->role == DECT_TRANSACTION_RESPONDER) + mb->data[0] |= DECT_S_TI_F_FLAG; + return mb; + +err2: + dect_mbuf_free(dh, mb); +err1: + return NULL; +} + /** * dect_lce_send - Queue a S-Format message for transmission to the LCE */ @@ -552,27 +584,14 @@ int dect_lce_send(const struct dect_handle *dh, { struct dect_data_link *ddl = ta->link; struct dect_msg_buf *mb; - int err; - mb = dect_mbuf_alloc(dh); + mb = dect_lce_build_msg(dh, ta, desc, msg, type); if (mb == NULL) return -1; - dect_mbuf_reserve(mb, DECT_S_HDR_SIZE); - err = dect_build_sfmt_msg(dh, desc, msg, mb); - if (err < 0) - return err; - if (ddl->sdu_timer && dect_timer_running(ddl->sdu_timer)) dect_ddl_stop_sdu_timer(dh, ddl); - dect_mbuf_push(mb, DECT_S_HDR_SIZE); - mb->data[1] = type; - mb->data[0] = ta->pd; - mb->data[0] |= ta->tv << DECT_S_TI_TV_SHIFT; - if (ta->role == DECT_TRANSACTION_RESPONDER) - mb->data[0] |= DECT_S_TI_F_FLAG; - if (ta->mb != NULL) dect_mbuf_free(dh, ta->mb); ta->mb = mb; @@ -590,6 +609,38 @@ int dect_lce_send(const struct dect_handle *dh, } } +int dect_lce_send_cl(struct dect_handle *dh, const struct dect_ipui *ipui, + const struct dect_sfmt_msg_desc *desc, + const struct dect_msg_common *msg, + enum dect_pds pd, uint8_t type) +{ + struct dect_data_link *ddl; + struct dect_msg_buf *mb; + struct dect_transaction ta = { + .pd = pd, + .tv = DECT_TV_CONNECTIONLESS, + }; + + ddl = dect_ddl_connect(dh, ipui); + if (ddl == NULL) + return -1; + + mb = dect_lce_build_msg(dh, &ta, desc, msg, type); + if (mb == NULL) + return -1; + + switch (ddl->state) { + case DECT_DATA_LINK_ESTABLISHED: + return dect_ddl_send(dh, ddl, mb); + case DECT_DATA_LINK_ESTABLISH_PENDING: + ptrlist_add_tail(mb, &ddl->msg_queue); + return 0; + default: + ddl_debug(ddl, "Invalid state: %u\n", ddl->state); + BUG(); + } +} + int dect_lce_retransmit(const struct dect_handle *dh, struct dect_transaction *ta) { @@ -745,6 +796,11 @@ static void dect_ddl_complete_indirect_establish(struct dect_handle *dh, /* Release pending link */ dect_ddl_destroy(dh, req); + + /* If the link was established for a connectionless transmission, + * no transaction exists. Perform a partial release. */ + if (list_empty(&ddl->transactions)) + return dect_ddl_partial_release(dh, ddl); } static void dect_ddl_page_timer(struct dect_handle *dh, struct dect_timer *timer); diff --git a/src/ss.c b/src/ss.c index 6861908..ce37666 100644 --- a/src/ss.c +++ b/src/ss.c @@ -103,13 +103,15 @@ void *dect_ss_priv(struct dect_ss_endpoint *sse) } EXPORT_SYMBOL(dect_ss_priv); -struct dect_ss_endpoint *dect_ss_endpoint_alloc(struct dect_handle *dh) +struct dect_ss_endpoint *dect_ss_endpoint_alloc(struct dect_handle *dh, + const struct dect_ipui *ipui) { struct dect_ss_endpoint *sse; sse = dect_zalloc(dh, sizeof(*sse) + dh->ops->ss_ops->priv_size); if (sse == NULL) goto err1; + sse->ipui = *ipui; return sse; @@ -138,7 +140,6 @@ static struct dect_ss_endpoint *dect_ss_endpoint(struct dect_transaction *ta) * @param 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; @@ -151,12 +152,13 @@ int dect_mnss_setup_req(struct dect_handle *dh, struct dect_ss_endpoint *sse, }; ss_debug_entry(sse, "MNSS_SETUP-req"); - if (dect_transaction_open(dh, &sse->transaction, ipui, DECT_PD_CISS) < 0) + if (dect_transaction_open(dh, &sse->transaction, &sse->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; + portable_identity.ipui = sse->ipui; msg.portable_identity = &portable_identity; } @@ -196,8 +198,14 @@ int dect_mnss_facility_req(struct dect_handle *dh, struct dect_ss_endpoint *sse, }; ss_debug_entry(sse, "MNSS_FACILITY-req"); - return dect_lce_send(dh, &sse->transaction, &ciss_facility_msg_desc, - &msg.common, DECT_CISS_FACILITY); + + if (sse->transaction.link != NULL) + return dect_lce_send(dh, &sse->transaction, &ciss_facility_msg_desc, + &msg.common, DECT_CISS_FACILITY); + else + return dect_lce_send_cl(dh, &sse->ipui, &ciss_facility_msg_desc, + &msg.common, DECT_PD_CISS, + DECT_CISS_FACILITY); } EXPORT_SYMBOL(dect_mnss_facility_req); @@ -320,7 +328,7 @@ static void dect_ciss_rcv_register(struct dect_handle *dh, if (dect_ddl_set_ipui(dh, req->link, &msg.portable_identity->ipui) < 0) goto out; - sse = dect_ss_endpoint_alloc(dh); + sse = dect_ss_endpoint_alloc(dh, &msg.portable_identity->ipui); if (sse == NULL) goto out;