summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <zecke@selfish.org>2010-09-30 18:30:41 +0800
committerHolger Hans Peter Freyther <zecke@selfish.org>2010-09-30 19:00:58 +0800
commit55aea5099c1780700e5acebda712e47b575853e5 (patch)
treec6e2f199d32ccce10bc271174aaf73867439d714
parent47ee693170d589f760c4a9c7a5c4ad0b289aa65d (diff)
gsm0480: Add USSD format functions to libosmocore
These routines come from OpenBSC, the msgb_wrap_* functions belong to Mike Haben, the rest is mine. The msgb allocation is compatible to the GSM48 allocation in OpenBSC.
-rw-r--r--include/osmocore/Makefile.am2
-rw-r--r--include/osmocore/gsm0480.h12
-rw-r--r--src/Makefile.am2
-rw-r--r--src/gsm0480.c190
4 files changed, 204 insertions, 2 deletions
diff --git a/include/osmocore/Makefile.am b/include/osmocore/Makefile.am
index c8b614f6..74102bdb 100644
--- a/include/osmocore/Makefile.am
+++ b/include/osmocore/Makefile.am
@@ -2,7 +2,7 @@ osmocore_HEADERS = signal.h linuxlist.h timer.h select.h msgb.h \
tlv.h bitvec.h comp128.h statistics.h gsm_utils.h utils.h \
gsmtap.h write_queue.h rsl.h gsm48.h rxlev_stat.h mncc.h \
gsm48_ie.h logging.h gsm0808.h rate_ctr.h gsmtap_util.h \
- plugin.h crc16.h panic.h process.h
+ plugin.h crc16.h panic.h process.h gsm0480.h
if ENABLE_TALLOC
osmocore_HEADERS += talloc.h
diff --git a/include/osmocore/gsm0480.h b/include/osmocore/gsm0480.h
new file mode 100644
index 00000000..52592f77
--- /dev/null
+++ b/include/osmocore/gsm0480.h
@@ -0,0 +1,12 @@
+#ifndef gsm0480_h
+#define gsm0480_h
+
+#include "msgb.h"
+
+struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text);
+struct msgb *gsm0480_create_notifySS(const char *text);
+
+int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id);
+int gsm0480_wrap_facility(struct msgb *msg);
+
+#endif
diff --git a/src/Makefile.am b/src/Makefile.am
index 1e97bb9b..288a0b92 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -13,7 +13,7 @@ libosmocore_la_SOURCES = timer.c select.c signal.c msgb.c rxlev_stat.c \
tlv_parser.c bitvec.c comp128.c gsm_utils.c statistics.c \
write_queue.c utils.c rsl.c gsm48.c gsm48_ie.c \
logging.c gsm0808.c rate_ctr.c gsmtap_util.c \
- gprs_cipher_core.c crc16.c panic.c process.c
+ gprs_cipher_core.c crc16.c panic.c process.c gsm0480.c
if ENABLE_PLUGIN
libosmocore_la_SOURCES += plugin.c
diff --git a/src/gsm0480.c b/src/gsm0480.c
new file mode 100644
index 00000000..ffcbc449
--- /dev/null
+++ b/src/gsm0480.c
@@ -0,0 +1,190 @@
+/* Format functions for GSM 04.80 */
+
+/*
+ * (C) 2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009 by Mike Haben <michael.haben@btinternet.com>
+ *
+ * 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 <osmocore/gsm0480.h>
+#include <osmocore/gsm_utils.h>
+
+#include <osmocore/protocol/gsm_04_80.h>
+
+#include <string.h>
+
+static inline unsigned char *msgb_wrap_with_TL(struct msgb *msgb, uint8_t tag)
+{
+ uint8_t *data = msgb_push(msgb, 2);
+
+ data[0] = tag;
+ data[1] = msgb->len - 2;
+ return data;
+}
+
+static inline unsigned char *msgb_push_TLV1(struct msgb *msgb, uint8_t tag,
+ uint8_t value)
+{
+ uint8_t *data = msgb_push(msgb, 3);
+
+ data[0] = tag;
+ data[1] = 1;
+ data[2] = value;
+ return data;
+}
+
+/* wrap an invoke around it... the other way around
+ *
+ * 1.) Invoke Component tag
+ * 2.) Invoke ID Tag
+ * 3.) Operation
+ * 4.) Data
+ */
+int gsm0480_wrap_invoke(struct msgb *msg, int op, int link_id)
+{
+ /* 3. operation */
+ msgb_push_TLV1(msg, GSM0480_OPERATION_CODE, op);
+
+ /* 2. invoke id tag */
+ msgb_push_TLV1(msg, GSM0480_COMPIDTAG_INVOKE_ID, link_id);
+
+ /* 1. component tag */
+ msgb_wrap_with_TL(msg, GSM0480_CTYPE_INVOKE);
+
+ return 0;
+}
+
+/* wrap the GSM 04.08 Facility IE around it */
+int gsm0480_wrap_facility(struct msgb *msg)
+{
+ msgb_wrap_with_TL(msg, GSM0480_IE_FACILITY);
+
+ return 0;
+}
+
+struct msgb *gsm0480_create_unstructuredSS_Notify(int alertPattern, const char *text)
+{
+ struct msgb *msg;
+ uint8_t *seq_len_ptr, *ussd_len_ptr, *data;
+ int len;
+
+ msg = msgb_alloc_headroom(1024, 128, "GSM 04.80");
+ if (!msg)
+ return NULL;
+
+ /* SEQUENCE { */
+ msgb_put_u8(msg, GSM_0480_SEQUENCE_TAG);
+ seq_len_ptr = msgb_put(msg, 1);
+
+ /* DCS { */
+ msgb_put_u8(msg, ASN1_OCTET_STRING_TAG);
+ msgb_put_u8(msg, 1);
+ msgb_put_u8(msg, 0x0F);
+ /* } DCS */
+
+ /* USSD-String { */
+ msgb_put_u8(msg, ASN1_OCTET_STRING_TAG);
+ ussd_len_ptr = msgb_put(msg, 1);
+ data = msgb_put(msg, 0);
+ len = gsm_7bit_encode(data, text);
+ msgb_put(msg, len);
+ ussd_len_ptr[0] = len;
+ /* USSD-String } */
+
+ /* alertingPattern { */
+ msgb_put_u8(msg, ASN1_OCTET_STRING_TAG);
+ msgb_put_u8(msg, 1);
+ msgb_put_u8(msg, alertPattern);
+ /* } alertingPattern */
+
+ seq_len_ptr[0] = 3 + 2 + ussd_len_ptr[0] + 3;
+ /* } SEQUENCE */
+
+ return msg;
+}
+
+struct msgb *gsm0480_create_notifySS(const char *text)
+{
+ struct msgb *msg;
+ uint8_t *data, *tmp_len;
+ uint8_t *seq_len_ptr, *cal_len_ptr, *opt_len_ptr, *nam_len_ptr;
+ int len;
+
+ len = strlen(text);
+ if (len < 1 || len > 160)
+ return NULL;
+
+ msg = msgb_alloc_headroom(1024, 128, "GSM 04.80");
+ if (!msg)
+ return NULL;
+
+ msgb_put_u8(msg, GSM_0480_SEQUENCE_TAG);
+ seq_len_ptr = msgb_put(msg, 1);
+
+ /* ss_code for CNAP { */
+ msgb_put_u8(msg, 0x81);
+ msgb_put_u8(msg, 1);
+ msgb_put_u8(msg, 0x19);
+ /* } ss_code */
+
+
+ /* nameIndicator { */
+ msgb_put_u8(msg, 0xB4);
+ nam_len_ptr = msgb_put(msg, 1);
+
+ /* callingName { */
+ msgb_put_u8(msg, 0xA0);
+ opt_len_ptr = msgb_put(msg, 1);
+ msgb_put_u8(msg, 0xA0);
+ cal_len_ptr = msgb_put(msg, 1);
+
+ /* namePresentationAllowed { */
+ /* add the DCS value */
+ msgb_put_u8(msg, 0x80);
+ msgb_put_u8(msg, 1);
+ msgb_put_u8(msg, 0x0F);
+
+ /* add the lengthInCharacters */
+ msgb_put_u8(msg, 0x81);
+ msgb_put_u8(msg, 1);
+ msgb_put_u8(msg, strlen(text));
+
+ /* add the actual string */
+ msgb_put_u8(msg, 0x82);
+ tmp_len = msgb_put(msg, 1);
+ data = msgb_put(msg, 0);
+ len = gsm_7bit_encode(data, text);
+ tmp_len[0] = len;
+ msgb_put(msg, len);
+
+ /* }; namePresentationAllowed */
+
+ cal_len_ptr[0] = 3 + 3 + 2 + len;
+ opt_len_ptr[0] = cal_len_ptr[0] + 2;
+ /* }; callingName */
+
+ nam_len_ptr[0] = opt_len_ptr[0] + 2;
+ /* ); nameIndicator */
+
+ /* write the lengths... */
+ seq_len_ptr[0] = 3 + nam_len_ptr[0] + 2;
+
+ return msg;
+}
+