summaryrefslogtreecommitdiffstats
path: root/src/host/gsm48-andreas
diff options
context:
space:
mode:
authorAndreas Eversberg2010-04-04 15:34:53 +0200
committerAndreas Eversberg2010-04-04 15:34:53 +0200
commit6be5c597f9fceb5f84c0f7c19b17f684dc847ff4 (patch)
treec147be9252386125dfcabf2fae5921a0c6c598fd /src/host/gsm48-andreas
parentAdded minimal call application as required in GSM 04.08. (diff)
downloadosmocom-6be5c597f9fceb5f84c0f7c19b17f684dc847ff4.tar.gz
osmocom-6be5c597f9fceb5f84c0f7c19b17f684dc847ff4.tar.xz
osmocom-6be5c597f9fceb5f84c0f7c19b17f684dc847ff4.zip
Adopted transaction.c and transaction.h from OpenBSC.
Pointers and structure is modified for the mobile station environment. The transactions are required to handle calls and SMS.
Diffstat (limited to 'src/host/gsm48-andreas')
-rw-r--r--src/host/gsm48-andreas/gsm48_cc.c26
-rw-r--r--src/host/gsm48-andreas/gsm48_l3.h3
-rw-r--r--src/host/gsm48-andreas/gsm48_mm.c46
-rw-r--r--src/host/gsm48-andreas/transaction.c136
-rw-r--r--src/host/gsm48-andreas/transaction.h66
5 files changed, 232 insertions, 45 deletions
diff --git a/src/host/gsm48-andreas/gsm48_cc.c b/src/host/gsm48-andreas/gsm48_cc.c
index 7272c2b..0f13902 100644
--- a/src/host/gsm48-andreas/gsm48_cc.c
+++ b/src/host/gsm48-andreas/gsm48_cc.c
@@ -651,6 +651,25 @@ static int gsm48_cc_tx_modify_reject(struct gsm_trans *trans, void *arg)
return gsm48_cc_to_mm(nmsg, trans, MMCC_DATA_REQ);
}
+/* Call Control Specific transaction release.
+ * gets called by trans_free, DO NOT CALL YOURSELF!
+ */
+void _gsm48_cc_trans_free(struct gsm_trans *trans)
+{
+ gsm48_stop_cc_timer(trans);
+
+ /* send release to L4, if callref still exists */
+ if (trans->callref) {
+ /* Ressource unavailable */
+ mncc_release_ind(trans->ms, trans, trans->callref,
+ GSM48_CAUSE_LOC_USER,
+ GSM48_CC_CAUSE_RESOURCE_UNAVAIL);
+ }
+ if (trans->cc.state != GSM_CSTATE_NULL)
+ new_cc_state(trans, GSM_CSTATE_NULL);
+}
+
+
/* state trasitions for MNCC messages (upper layer) */
static struct downstate {
u_int32_t states;
@@ -701,6 +720,13 @@ static struct downstate {
#define DOWNSLLEN \
(sizeof(downstatelist) / sizeof(struct downstate))
+int mncc_send(struct gsm_network *net, int msg_type, void *arg)
+{
+ struct gsm_mncc *data = arg, rel;
+
+ /* Find callref */
+ trans = trans_find_by_ref(net, data->callref);
+}
/* reply status enquiry */
diff --git a/src/host/gsm48-andreas/gsm48_l3.h b/src/host/gsm48-andreas/gsm48_l3.h
index a406861..605e743 100644
--- a/src/host/gsm48-andreas/gsm48_l3.h
+++ b/src/host/gsm48-andreas/gsm48_l3.h
@@ -133,7 +133,8 @@ struct gsm48_rr_hdr {
/* GSM 04.08 MMxx-SAP header */
struct gsm48_mmxx_hdr {
int msg_type; /* MMxx_* primitive */
- u_int32_t ref; /* transaction reference */
+ u_int32_t ref; /* reference to transaction */
+ u_int32_t trans_id; /* transaction identifier */
u_int8_t emergency; /* emergency type of call */
u_int8_t cause; /* cause used for release */
};
diff --git a/src/host/gsm48-andreas/gsm48_mm.c b/src/host/gsm48-andreas/gsm48_mm.c
index 9ba6be1..e6ecc56 100644
--- a/src/host/gsm48-andreas/gsm48_mm.c
+++ b/src/host/gsm48-andreas/gsm48_mm.c
@@ -222,41 +222,6 @@ void mm_conn_free(struct gsm48_mm_conn *conn)
talloc_free(conn);
}
-/* taken from OpenBSC project:
- * allocate an unused transaction ID for the given protocol
- * using the ti_flag specified
- */
-int mm_conn_assign_trans_id(struct gsm48_mmlayer *mm,
- uint8_t protocol, uint8_t ti_flag)
-{
- struct gsm48_mm_conn *conn;
- unsigned int used_tid_bitmask = 0;
- int i, j, h;
-
- if (ti_flag)
- ti_flag = 0x8;
-
- /* generate bitmask of already-used TIDs for this (proto) */
- llist_for_each_entry(conn, &mm->mm_conn, list) {
- if (conn->protocol != protocol ||
- conn->transaction_id == 0xff)
- continue;
- used_tid_bitmask |= (1 << conn->transaction_id);
- }
-
- /* find a new one, trying to go in a 'circular' pattern */
- for (h = 6; h > 0; h--)
- if (used_tid_bitmask & (1 << (h | ti_flag)))
- break;
- for (i = 0; i < 7; i++) {
- j = ((h + i) % 7) | ti_flag;
- if ((used_tid_bitmask & (1 << j)) == 0)
- return j;
- }
-
- return -1;
-}
-
static const char *gsm48_mmxx_state_names[] = {
"IDLE",
"CONN_PEND",
@@ -1131,7 +1096,7 @@ static int gsm48_mm_release_mm_conn(struct osmocom_ms *ms, int abort_any, uint8_
}
if (!nmsg) {
/* this should not happen */
- free(conn);
+ mm_conn_free(conn);
continue; /* skip if not of CC type */
}
nmmh = (struct gsm48_mmxx_hdr *)nmsg->data;
@@ -1955,15 +1920,8 @@ static int gsm48_mm_init_mm(struct osmocom_ms *ms, struct mgsb *msg, int rr_prim
break;
}
- /* hunt transaction ID */
- trans_id = mm_conn_assign_trans_id(mm, proto, 0);
- if (!trans_id < 0) {
- cause = 47;
- goto reject;
- }
-
/* create MM connection instance */
- conn = mm_conn_new(mm, proto, trans_id, mmh->ref);
+ conn = mm_conn_new(mm, proto, mmh->trans_id, mmh->ref);
if (!conn)
return -ENOMEM;
diff --git a/src/host/gsm48-andreas/transaction.c b/src/host/gsm48-andreas/transaction.c
new file mode 100644
index 0000000..32864d6
--- /dev/null
+++ b/src/host/gsm48-andreas/transaction.c
@@ -0,0 +1,136 @@
+/* GSM 04.07 Transaction handling */
+
+/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * All Rights Reserved
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
+ *
+ */
+
+#include <osmocom/transaction.h>
+#include <osmocom/mnccms.h>
+#include <osmocom/debug.h>
+#include <osmocore/talloc.h>
+#include <osmocom/gsm_04_08.h>
+
+void *tall_trans_ctx;
+
+void _gsm48_cc_trans_free(struct gsm_trans *trans);
+
+struct gsm_trans *trans_find_by_id(struct osmocom_ms *ms,
+ u_int8_t proto, u_int8_t trans_id)
+{
+ struct gsm_trans *trans;
+
+ llist_for_each_entry(trans, &ms->trans_list, entry) {
+ if (trans->subscr == subscr &&
+ trans->protocol == proto &&
+ trans->transaction_id == trans_id)
+ return trans;
+ }
+ return NULL;
+}
+
+struct gsm_trans *trans_find_by_callref(struct osmocom_ms *ms,
+ u_int32_t callref)
+{
+ struct gsm_trans *trans;
+
+ llist_for_each_entry(trans, &ms->trans_list, entry) {
+ if (trans->callref == callref)
+ return trans;
+ }
+ return NULL;
+}
+
+struct gsm_trans *trans_alloc(struct osmocom_ms *ms,
+ u_int8_t protocol, u_int8_t trans_id,
+ u_int32_t callref)
+{
+ struct gsm_trans *trans;
+
+ DEBUGP(DCC, "ms %s\n", ms->name);
+
+ trans = talloc_zero(tall_trans_ctx, struct gsm_trans);
+ if (!trans)
+ return NULL;
+
+ trans->ms = ms;
+
+ trans->protocol = protocol;
+ trans->transaction_id = trans_id;
+ trans->callref = callref;
+
+ llist_add_tail(&trans->entry, &ms->trans_list);
+
+ return trans;
+}
+
+void trans_free(struct gsm_trans *trans)
+{
+ switch (trans->protocol) {
+ case GSM48_PDISC_CC:
+ _gsm48_cc_trans_free(trans);
+ break;
+#if 0
+ case GSM48_PDISC_SS:
+ _gsm411_ss_trans_free(trans);
+ break;
+ }
+ case GSM48_PDISC_SMS:
+ _gsm411_sms_trans_free(trans);
+ break;
+ }
+#endif
+
+ llist_del(&trans->entry);
+
+ talloc_free(trans);
+}
+
+/* allocate an unused transaction ID
+ * in the given protocol using the ti_flag specified */
+int trans_assign_trans_id(struct osmocom_ms *ms,
+ u_int8_t protocol, u_int8_t ti_flag)
+{
+ struct gsm_trans *trans;
+ unsigned int used_tid_bitmask = 0;
+ int i, j, h;
+
+ if (ti_flag)
+ ti_flag = 0x8;
+
+ /* generate bitmask of already-used TIDs for this (subscr,proto) */
+ llist_for_each_entry(trans, &ms->trans_list, entry) {
+ if (trans->subscr != subscr ||
+ trans->protocol != protocol ||
+ trans->transaction_id == 0xff)
+ continue;
+ used_tid_bitmask |= (1 << trans->transaction_id);
+ }
+
+ /* find a new one, trying to go in a 'circular' pattern */
+ for (h = 6; h > 0; h--)
+ if (used_tid_bitmask & (1 << (h | ti_flag)))
+ break;
+ for (i = 0; i < 7; i++) {
+ j = ((h + i) % 7) | ti_flag;
+ if ((used_tid_bitmask & (1 << j)) == 0)
+ return j;
+ }
+
+ return -1;
+}
+
diff --git a/src/host/gsm48-andreas/transaction.h b/src/host/gsm48-andreas/transaction.h
new file mode 100644
index 0000000..a2f506b
--- /dev/null
+++ b/src/host/gsm48-andreas/transaction.h
@@ -0,0 +1,66 @@
+#ifndef _TRANSACT_H
+#define _TRANSACT_H
+
+#include <osmocore/linuxlist.h>
+
+/* One transaction */
+struct gsm_trans {
+ /* Entry in list of all transactions */
+ struct llist_head entry;
+
+ /* The protocol within which we live */
+ u_int8_t protocol;
+
+ /* The current transaction ID */
+ u_int8_t transaction_id;
+
+ /* To whom we belong */
+ struct osmocom_ms *ms;
+
+ /* reference from MNCC or other application */
+ u_int32_t callref;
+
+ /* if traffic channel receive was requested */
+ int tch_recv;
+
+ union {
+ struct {
+
+ /* current call state */
+ int state;
+
+ /* current timer and message queue */
+ int Tcurrent; /* current CC timer */
+ int T308_second; /* used to send release again */
+ struct timer_list timer;
+ struct gsm_mncc msg; /* stores setup/disconnect/release message */
+ } cc;
+ struct {
+ u_int8_t link_id; /* RSL Link ID to be used for this trans */
+ int is_mt; /* is this a MO (0) or MT (1) transfer */
+ enum gsm411_cp_state cp_state;
+ struct timer_list cp_timer;
+
+ enum gsm411_rp_state rp_state;
+
+ struct gsm_sms *sms;
+ } sms;
+ };
+};
+
+
+
+struct gsm_trans *trans_find_by_id(struct osmocom_ms *ms,
+ u_int8_t proto, u_int8_t trans_id);
+struct gsm_trans *trans_find_by_callref(struct gsm_network *net,
+ u_int32_t callref);
+
+struct gsm_trans *trans_alloc(struct osmocom_ms *ms,
+ u_int8_t protocol, u_int8_t trans_id,
+ u_int32_t callref);
+void trans_free(struct gsm_trans *trans);
+
+int trans_assign_trans_id(struct osmocom_ms *ms,
+ u_int8_t protocol, u_int8_t ti_flag);
+
+#endif