summaryrefslogtreecommitdiffstats
path: root/include/osmocom/gsm
diff options
context:
space:
mode:
authorPablo Neira Ayuso <pablo@gnumonks.org>2011-03-22 16:36:13 +0100
committerHarald Welte <laforge@gnumonks.org>2011-03-23 18:09:28 +0100
commit834193484439acd6056a891e9b2df5992a370088 (patch)
treee31e73e1364119617416273610f7b851c89d25c4 /include/osmocom/gsm
parentfba495e5f6084800c076e0ecae990ed9e6483530 (diff)
include: reorganize headers file to include/osmocom/[gsm|core]
This patch moves all GSM-specific definitions to include/osmocom/gsm. Moreover, the headers in include/osmocore/ have been moved to include/osmocom/core. This has been proposed by Harald Welte and Sylvain Munaunt. Tested with `make distcheck'. Signed-off-by: Pablo Neira Ayuso <pablo@gnumonks.org>
Diffstat (limited to 'include/osmocom/gsm')
-rw-r--r--include/osmocom/gsm/Makefile.am6
-rw-r--r--include/osmocom/gsm/comp128.h22
-rw-r--r--include/osmocom/gsm/gsm0480.h26
-rw-r--r--include/osmocom/gsm/gsm0808.h46
-rw-r--r--include/osmocom/gsm/gsm48.h36
-rw-r--r--include/osmocom/gsm/gsm48_ie.h117
-rw-r--r--include/osmocom/gsm/gsm_utils.h117
-rw-r--r--include/osmocom/gsm/mncc.h71
-rw-r--r--include/osmocom/gsm/protocol/Makefile.am6
-rw-r--r--include/osmocom/gsm/protocol/gsm_03_41.h51
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_08.h1262
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_11.h188
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_12.h31
-rw-r--r--include/osmocom/gsm/protocol/gsm_04_80.h126
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_08.h303
-rw-r--r--include/osmocom/gsm/protocol/gsm_08_58.h546
-rw-r--r--include/osmocom/gsm/protocol/gsm_12_21.h713
-rw-r--r--include/osmocom/gsm/rsl.h41
-rw-r--r--include/osmocom/gsm/rxlev_stat.h22
-rw-r--r--include/osmocom/gsm/tlv.h260
20 files changed, 3990 insertions, 0 deletions
diff --git a/include/osmocom/gsm/Makefile.am b/include/osmocom/gsm/Makefile.am
new file mode 100644
index 00000000..8685fc9a
--- /dev/null
+++ b/include/osmocom/gsm/Makefile.am
@@ -0,0 +1,6 @@
+osmogsm_HEADERS = comp128.h gsm0808.h gsm48_ie.h mncc.h rxlev_stat.h \
+ gsm0480.h gsm48.h gsm_utils.h rsl.h tlv.h
+
+SUBDIRS = protocol
+
+osmogsmdir = $(includedir)/osmocom/gsm
diff --git a/include/osmocom/gsm/comp128.h b/include/osmocom/gsm/comp128.h
new file mode 100644
index 00000000..c37808f0
--- /dev/null
+++ b/include/osmocom/gsm/comp128.h
@@ -0,0 +1,22 @@
+/*
+ * COMP128 header
+ *
+ * See comp128.c for details
+ */
+
+#ifndef __COMP128_H__
+#define __COMP128_H__
+
+#include <stdint.h>
+
+/*
+ * Performs the COMP128 algorithm (used as A3/A8)
+ * ki : uint8_t [16]
+ * srand : uint8_t [16]
+ * sres : uint8_t [4]
+ * kc : uint8_t [8]
+ */
+void comp128(uint8_t *ki, uint8_t *srand, uint8_t *sres, uint8_t *kc);
+
+#endif /* __COMP128_H__ */
+
diff --git a/include/osmocom/gsm/gsm0480.h b/include/osmocom/gsm/gsm0480.h
new file mode 100644
index 00000000..d6626d60
--- /dev/null
+++ b/include/osmocom/gsm/gsm0480.h
@@ -0,0 +1,26 @@
+#ifndef gsm0480_h
+#define gsm0480_h
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/protocol/gsm_04_80.h>
+
+#define MAX_LEN_USSD_STRING 31
+
+struct ussd_request {
+ char text[MAX_LEN_USSD_STRING + 1];
+ uint8_t transaction_id;
+ uint8_t invoke_id;
+};
+
+int gsm0480_decode_ussd_request(const struct gsm48_hdr *hdr, uint16_t len,
+ struct ussd_request *request);
+
+struct msgb *gsm0480_create_ussd_resp(uint8_t invoke_id, uint8_t trans_id, const char *text);
+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/include/osmocom/gsm/gsm0808.h b/include/osmocom/gsm/gsm0808.h
new file mode 100644
index 00000000..1d853775
--- /dev/null
+++ b/include/osmocom/gsm/gsm0808.h
@@ -0,0 +1,46 @@
+/* (C) 2009,2010 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009,2010 by On-Waves
+ * 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.
+ *
+ */
+#ifndef OSMOCORE_GSM0808_H
+#define OSMOCORE_GSM0808_H
+
+#include "tlv.h"
+
+struct msgb;
+
+struct msgb *gsm0808_create_layer3(struct msgb *msg, uint16_t netcode, uint16_t countrycode, int lac, uint16_t ci);
+struct msgb *gsm0808_create_reset(void);
+struct msgb *gsm0808_create_clear_command(uint8_t reason);
+struct msgb *gsm0808_create_clear_complete(void);
+struct msgb *gsm0808_create_cipher_complete(struct msgb *layer3, uint8_t alg_id);
+struct msgb *gsm0808_create_cipher_reject(uint8_t cause);
+struct msgb *gsm0808_create_classmark_update(const uint8_t *classmark, uint8_t length);
+struct msgb *gsm0808_create_sapi_reject(uint8_t link_id);
+struct msgb *gsm0808_create_assignment_completed(uint8_t rr_cause,
+ uint8_t chosen_channel, uint8_t encr_alg_id,
+ uint8_t speech_mode);
+struct msgb *gsm0808_create_assignment_failure(uint8_t cause, uint8_t *rr_cause);
+struct msgb *gsm0808_create_clear_rqst(uint8_t cause);
+
+struct msgb *gsm0808_create_dtap(struct msgb *msg, uint8_t link_id);
+void gsm0808_prepend_dtap_header(struct msgb *msg, uint8_t link_id);
+
+const struct tlv_definition *gsm0808_att_tlvdef();
+
+#endif
diff --git a/include/osmocom/gsm/gsm48.h b/include/osmocom/gsm/gsm48.h
new file mode 100644
index 00000000..1e9403bc
--- /dev/null
+++ b/include/osmocom/gsm/gsm48.h
@@ -0,0 +1,36 @@
+#ifndef _OSMOCORE_GSM48_H
+#define _OSMOCORE_GSM48_H
+
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+#include <osmocom/gsm/gsm48_ie.h>
+
+/* A parsed GPRS routing area */
+struct gprs_ra_id {
+ uint16_t mnc;
+ uint16_t mcc;
+ uint16_t lac;
+ uint8_t rac;
+};
+
+extern const struct tlv_definition gsm48_att_tlvdef;
+extern const struct tlv_definition gsm48_rr_att_tlvdef;
+extern const struct tlv_definition gsm48_mm_att_tlvdef;
+const char *gsm48_cc_state_name(uint8_t state);
+const char *gsm48_cc_msg_name(uint8_t msgtype);
+const char *rr_cause_name(uint8_t cause);
+
+void gsm48_generate_lai(struct gsm48_loc_area_id *lai48, uint16_t mcc,
+ uint16_t mnc, uint16_t lac);
+int gsm48_generate_mid_from_tmsi(uint8_t *buf, uint32_t tmsi);
+int gsm48_generate_mid_from_imsi(uint8_t *buf, const char *imsi);
+
+/* Convert Mobile Identity (10.5.1.4) to string */
+int gsm48_mi_to_string(char *string, const int str_len,
+ const uint8_t *mi, const int mi_len);
+
+/* Parse Routeing Area Identifier */
+void gsm48_parse_ra(struct gprs_ra_id *raid, const uint8_t *buf);
+int gsm48_construct_ra(uint8_t *buf, const struct gprs_ra_id *raid);
+
+#endif
diff --git a/include/osmocom/gsm/gsm48_ie.h b/include/osmocom/gsm/gsm48_ie.h
new file mode 100644
index 00000000..f4fce25c
--- /dev/null
+++ b/include/osmocom/gsm/gsm48_ie.h
@@ -0,0 +1,117 @@
+#ifndef _OSMOCORE_GSM48_IE_H
+#define _OSMOCORE_GSM48_IE_H
+
+#include <stdint.h>
+#include <string.h>
+#include <errno.h>
+
+#include <osmocom/core/msgb.h>
+#include <osmocom/gsm/tlv.h>
+#include <osmocom/gsm/mncc.h>
+#include <osmocom/gsm/protocol/gsm_04_08.h>
+
+/* decode a 'called/calling/connect party BCD number' as in 10.5.4.7 */
+int gsm48_decode_bcd_number(char *output, int output_len,
+ const uint8_t *bcd_lv, int h_len);
+
+/* convert a ASCII phone number to 'called/calling/connect party BCD number' */
+int gsm48_encode_bcd_number(uint8_t *bcd_lv, uint8_t max_len,
+ int h_len, const char *input);
+/* decode 'bearer capability' */
+int gsm48_decode_bearer_cap(struct gsm_mncc_bearer_cap *bcap,
+ const uint8_t *lv);
+/* encode 'bearer capability' */
+int gsm48_encode_bearer_cap(struct msgb *msg, int lv_only,
+ const struct gsm_mncc_bearer_cap *bcap);
+/* decode 'call control cap' */
+int gsm48_decode_cccap(struct gsm_mncc_cccap *ccap, const uint8_t *lv);
+/* encode 'call control cap' */
+int gsm48_encode_cccap(struct msgb *msg,
+ const struct gsm_mncc_cccap *ccap);
+/* decode 'called party BCD number' */
+int gsm48_decode_called(struct gsm_mncc_number *called,
+ const uint8_t *lv);
+/* encode 'called party BCD number' */
+int gsm48_encode_called(struct msgb *msg,
+ const struct gsm_mncc_number *called);
+/* decode callerid of various IEs */
+int gsm48_decode_callerid(struct gsm_mncc_number *callerid,
+ const uint8_t *lv);
+/* encode callerid of various IEs */
+int gsm48_encode_callerid(struct msgb *msg, int ie, int max_len,
+ const struct gsm_mncc_number *callerid);
+/* decode 'cause' */
+int gsm48_decode_cause(struct gsm_mncc_cause *cause,
+ const uint8_t *lv);
+/* encode 'cause' */
+int gsm48_encode_cause(struct msgb *msg, int lv_only,
+ const struct gsm_mncc_cause *cause);
+/* decode 'calling number' */
+int gsm48_decode_calling(struct gsm_mncc_number *calling,
+ const uint8_t *lv);
+/* encode 'calling number' */
+int gsm48_encode_calling(struct msgb *msg,
+ const struct gsm_mncc_number *calling);
+/* decode 'connected number' */
+int gsm48_decode_connected(struct gsm_mncc_number *connected,
+ const uint8_t *lv);
+/* encode 'connected number' */
+int gsm48_encode_connected(struct msgb *msg,
+ const struct gsm_mncc_number *connected);
+/* decode 'redirecting number' */
+int gsm48_decode_redirecting(struct gsm_mncc_number *redirecting,
+ const uint8_t *lv);
+/* encode 'redirecting number' */
+int gsm48_encode_redirecting(struct msgb *msg,
+ const struct gsm_mncc_number *redirecting);
+/* decode 'facility' */
+int gsm48_decode_facility(struct gsm_mncc_facility *facility,
+ const uint8_t *lv);
+/* encode 'facility' */
+int gsm48_encode_facility(struct msgb *msg, int lv_only,
+ const struct gsm_mncc_facility *facility);
+/* decode 'notify' */
+int gsm48_decode_notify(int *notify, const uint8_t *v);
+/* encode 'notify' */
+int gsm48_encode_notify(struct msgb *msg, int notify);
+/* decode 'signal' */
+int gsm48_decode_signal(int *signal, const uint8_t *v);
+/* encode 'signal' */
+int gsm48_encode_signal(struct msgb *msg, int signal);
+/* decode 'keypad' */
+int gsm48_decode_keypad(int *keypad, const uint8_t *lv);
+/* encode 'keypad' */
+int gsm48_encode_keypad(struct msgb *msg, int keypad);
+/* decode 'progress' */
+int gsm48_decode_progress(struct gsm_mncc_progress *progress,
+ const uint8_t *lv);
+/* encode 'progress' */
+int gsm48_encode_progress(struct msgb *msg, int lv_only,
+ const struct gsm_mncc_progress *p);
+/* decode 'user-user' */
+int gsm48_decode_useruser(struct gsm_mncc_useruser *uu,
+ const uint8_t *lv);
+/* encode 'useruser' */
+int gsm48_encode_useruser(struct msgb *msg, int lv_only,
+ const struct gsm_mncc_useruser *uu);
+/* decode 'ss version' */
+int gsm48_decode_ssversion(struct gsm_mncc_ssversion *ssv,
+ const uint8_t *lv);
+/* encode 'ss version' */
+int gsm48_encode_ssversion(struct msgb *msg,
+ const struct gsm_mncc_ssversion *ssv);
+/* decode 'more data' does not require a function, because it has no value */
+/* encode 'more data' */
+int gsm48_encode_more(struct msgb *msg);
+
+/* structure of one frequency */
+struct gsm_sysinfo_freq {
+ /* if the frequency included in the sysinfo */
+ uint8_t mask;
+};
+
+/* decode "Cell Channel Description" (10.5.2.1b) and other frequency lists */
+int gsm48_decode_freq_list(struct gsm_sysinfo_freq *f, uint8_t *cd,
+ uint8_t len, uint8_t mask, uint8_t frqt);
+
+#endif
diff --git a/include/osmocom/gsm/gsm_utils.h b/include/osmocom/gsm/gsm_utils.h
new file mode 100644
index 00000000..19adb70a
--- /dev/null
+++ b/include/osmocom/gsm/gsm_utils.h
@@ -0,0 +1,117 @@
+/* GSM utility functions, e.g. coding and decoding */
+/*
+ * (C) 2008 by Daniel Willmann <daniel@totalueberwachung.de>
+ * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
+ * (C) 2009-2010 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.
+ *
+ */
+
+#ifndef GSM_UTILS_H
+#define GSM_UTILS_H
+
+#include <stdint.h>
+
+#define ADD_MODULO(sum, delta, modulo) do { \
+ if ((sum += delta) >= modulo) \
+ sum -= modulo; \
+ } while (0)
+
+#define GSM_MAX_FN (26*51*2048)
+
+struct gsm_time {
+ uint32_t fn; /* FN count */
+ uint16_t t1; /* FN div (26*51) */
+ uint8_t t2; /* FN modulo 26 */
+ uint8_t t3; /* FN modulo 51 */
+ uint8_t tc;
+};
+
+enum gsm_band {
+ GSM_BAND_850 = 1,
+ GSM_BAND_900 = 2,
+ GSM_BAND_1800 = 4,
+ GSM_BAND_1900 = 8,
+ GSM_BAND_450 = 0x10,
+ GSM_BAND_480 = 0x20,
+ GSM_BAND_750 = 0x40,
+ GSM_BAND_810 = 0x80,
+};
+
+const char *gsm_band_name(enum gsm_band band);
+enum gsm_band gsm_band_parse(const char *mhz);
+
+int gsm_7bit_decode(char *decoded, const uint8_t *user_data, uint8_t length);
+int gsm_7bit_encode(uint8_t *result, const char *data);
+
+int ms_pwr_ctl_lvl(enum gsm_band band, unsigned int dbm);
+int ms_pwr_dbm(enum gsm_band band, uint8_t lvl);
+
+/* According to TS 08.05 Chapter 8.1.4 */
+int rxlev2dbm(uint8_t rxlev);
+uint8_t dbm2rxlev(int dbm);
+
+/* According to GSM 04.08 Chapter 10.5.1.6 */
+static inline int ms_cm2_a5n_support(uint8_t *cm2, int n) {
+ switch (n) {
+ case 0: return 1;
+ case 1: return (cm2[0] & (1<<3)) ? 0 : 1;
+ case 2: return (cm2[2] & (1<<0)) ? 1 : 0;
+ case 3: return (cm2[2] & (1<<1)) ? 1 : 0;
+ default:
+ return 0;
+ }
+}
+
+/* According to GSM 04.08 Chapter 10.5.2.29 */
+static inline int rach_max_trans_val2raw(int val) { return (val >> 1) & 3; }
+static inline int rach_max_trans_raw2val(int raw) {
+ const int tbl[4] = { 1, 2, 4, 7 };
+ return tbl[raw & 3];
+}
+
+#define ARFCN_PCS 0x8000
+#define ARFCN_UPLINK 0x4000
+#define ARFCN_FLAG_MASK 0xf000 /* Reserve the upper 5 bits for flags */
+
+enum gsm_band gsm_arfcn2band(uint16_t arfcn);
+
+/* Convert an ARFCN to the frequency in MHz * 10 */
+uint16_t gsm_arfcn2freq10(uint16_t arfcn, int uplink);
+
+/* Convert from frame number to GSM time */
+void gsm_fn2gsmtime(struct gsm_time *time, uint32_t fn);
+
+/* Convert from GSM time to frame number */
+uint32_t gsm_gsmtime2fn(struct gsm_time *time);
+
+/* GSM TS 03.03 Chapter 2.6 */
+enum gprs_tlli_type {
+ TLLI_LOCAL,
+ TLLI_FOREIGN,
+ TLLI_RANDOM,
+ TLLI_AUXILIARY,
+ TLLI_RESERVED,
+};
+
+/* TS 03.03 Chapter 2.6 */
+int gprs_tlli_type(uint32_t tlli);
+
+uint32_t gprs_tmsi2tlli(uint32_t p_tmsi, enum gprs_tlli_type type);
+
+#endif
diff --git a/include/osmocom/gsm/mncc.h b/include/osmocom/gsm/mncc.h
new file mode 100644
index 00000000..a094bb9b
--- /dev/null
+++ b/include/osmocom/gsm/mncc.h
@@ -0,0 +1,71 @@
+#ifndef _OSMOCORE_MNCC_H
+#define _OSMOCORE_MNCC_H
+
+#define GSM_MAX_FACILITY 128
+#define GSM_MAX_SSVERSION 128
+#define GSM_MAX_USERUSER 128
+
+/* Expanded fields from GSM TS 04.08, Table 10.5.102 */
+struct gsm_mncc_bearer_cap {
+ int transfer; /* Information Transfer Capability */
+ int mode; /* Transfer Mode */
+ int coding; /* Coding Standard */
+ int radio; /* Radio Channel Requirement */
+ int speech_ctm; /* CTM text telephony indication */
+ int speech_ver[8]; /* Speech version indication */
+};
+
+struct gsm_mncc_number {
+ int type;
+ int plan;
+ int present;
+ int screen;
+ char number[33];
+};
+
+struct gsm_mncc_cause {
+ int location;
+ int coding;
+ int rec;
+ int rec_val;
+ int value;
+ int diag_len;
+ char diag[32];
+};
+
+struct gsm_mncc_useruser {
+ int proto;
+ char info[GSM_MAX_USERUSER + 1]; /* + termination char */
+};
+
+struct gsm_mncc_progress {
+ int coding;
+ int location;
+ int descr;
+};
+
+struct gsm_mncc_facility {
+ int len;
+ char info[GSM_MAX_FACILITY];
+};
+
+struct gsm_mncc_ssversion {
+ int len;
+ char info[GSM_MAX_SSVERSION];
+};
+
+struct gsm_mncc_cccap {
+ int dtmf;
+ int pcp;
+};
+
+enum {
+ GSM_MNCC_BCAP_SPEECH = 0,
+ GSM_MNCC_BCAP_UNR_DIG = 1,
+ GSM_MNCC_BCAP_AUDIO = 2,
+ GSM_MNCC_BCAP_FAX_G3 = 3,
+ GSM_MNCC_BCAP_OTHER_ITC = 5,
+ GSM_MNCC_BCAP_RESERVED = 7,
+};
+
+#endif
diff --git a/include/osmocom/gsm/protocol/Makefile.am b/include/osmocom/gsm/protocol/Makefile.am
new file mode 100644
index 00000000..8483f10a
--- /dev/null
+++ b/include/osmocom/gsm/protocol/Makefile.am
@@ -0,0 +1,6 @@
+osmogsm_proto_HEADERS = gsm_03_41.h \
+ gsm_04_08.h gsm_04_11.h gsm_04_12.h gsm_04_80.h \
+ gsm_08_08.h gsm_08_58.h \
+ gsm_12_21.h
+
+osmogsm_protodir = $(includedir)/osmocom/gsm/protocol
diff --git a/include/osmocom/gsm/protocol/gsm_03_41.h b/include/osmocom/gsm/protocol/gsm_03_41.h
new file mode 100644
index 00000000..54365cbc
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_03_41.h
@@ -0,0 +1,51 @@
+#ifndef PROTO_GSM_03_41_H
+#define PROTO_GSM_03_41_H
+
+#include <stdint.h>
+
+/* GSM TS 03.41 definitions also TS 23.041*/
+
+/* Chapter 9.3.2 */
+struct gsm341_ms_message {
+ struct {
+ uint8_t code_hi:6;
+ uint8_t gs:2;
+ uint8_t update:4;
+ uint8_t code_lo:4;
+ } serial;
+ uint16_t msg_id;
+ struct {
+ uint8_t language:4;
+ uint8_t group:4;
+ } dcs;
+ struct {
+ uint8_t total:4;
+ uint8_t current:4;
+ } page;
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Chapter 9.4.1.3 */
+struct gsm341_etws_message {
+ struct {
+ uint8_t code_hi:4;
+ uint8_t popup:1;
+ uint8_t alert:1;
+ uint8_t gs:2;
+ uint8_t update:4;
+ uint8_t code_lo:4;
+ } serial;
+ uint16_t msg_id;
+ uint16_t warning_type;
+ uint8_t data[0];
+} __attribute__((packed));
+
+#define GSM341_MSG_CODE(ms) ((ms)->serial.code_lo | ((ms)->serial.code_hi << 4))
+
+/* Section 9.3.2.1 - Geographical Scope */
+#define GSM341_GS_CELL_WIDE_IMMED 0
+#define GSM341_GS_PLMN_WIDE 1
+#define GSM341_GS_LA_WIDE 2
+#define GSM341_GS_CELL_WIDE 3
+
+#endif /* PROTO_GSM_03_41_H */
diff --git a/include/osmocom/gsm/protocol/gsm_04_08.h b/include/osmocom/gsm/protocol/gsm_04_08.h
new file mode 100644
index 00000000..3ad7dfdc
--- /dev/null
+++ b/include/osmocom/gsm/protocol/gsm_04_08.h
@@ -0,0 +1,1262 @@
+#ifndef PROTO_GSM_04_08_H
+#define PROTO_GSM_04_08_H
+
+#include <stdint.h>
+
+/* GSM TS 04.08 definitions */
+struct gsm_lchan;
+
+/* Chapter 10.5.1.5 */
+struct gsm48_classmark1 {
+ uint8_t pwr_lev:3,
+ a5_1:1,
+ es_ind:1,
+ rev_lev:2,
+ spare:1;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.1.6 */
+struct gsm48_classmark2 {
+ uint8_t pwr_lev:3,
+ a5_1:1,
+ es_ind:1,
+ rev_lev:2,
+ spare:1;
+ uint8_t fc:1,
+ vgcs:1,
+ vbs:1,
+ sm_cap:1,
+ ss_scr:2,
+ ps_cap:1,
+ spare2:1;
+ uint8_t a5_2:1,
+ a5_3:1,
+ cmsp:1,
+ solsa:1,
+ spare3:1,
+ lcsva_cap:1,
+ spare4:1,
+ cm3:1;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.1b.3 */
+struct gsm48_range_1024 {
+ uint8_t w1_hi:2,
+ f0:1,
+ form_id:5;
+ uint8_t w1_lo;
+ uint8_t w2_hi;
+ uint8_t w3_hi:7,
+ w2_lo:1;
+ uint8_t w4_hi:6,
+ w3_lo:2;
+ uint8_t w5_hi:6,
+ w4_lo:2;
+ uint8_t w6_hi:6,
+ w5_lo:2;
+ uint8_t w7_hi:6,
+ w6_lo:2;
+ uint8_t w8_hi:6,
+ w7_lo:2;
+ uint8_t w9:7,
+ w8_lo:1;
+ uint8_t w11_hi:1,
+ w10:7;
+ uint8_t w12_hi:2,
+ w11_lo:6;
+ uint8_t w13_hi:3,
+ w12_lo:5;
+ uint8_t w14_hi:4,
+ w13_lo:4;
+ uint8_t w15_hi:5,
+ w14_lo:3;
+ uint8_t w16:6,
+ w15_lo:2;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.1b.4 */
+struct gsm48_range_512 {
+ uint8_t orig_arfcn_hi:1,
+ form_id:7;
+ uint8_t orig_arfcn_mid;
+ uint8_t w1_hi:7,
+ orig_arfcn_lo:1;
+ uint8_t w2_hi:6,
+ w1_lo:2;
+ uint8_t w3_hi:6,
+ w2_lo:2;
+ uint8_t w4_hi:6,
+ w3_lo:2;
+ uint8_t w5:7,
+ w4_lo:1;
+ uint8_t w7_hi:1,
+ w6:7;
+ uint8_t w8_hi:2,
+ w7_lo:6;
+ uint8_t w9_hi:4,
+ w8_lo:4;
+ uint8_t w10:6,
+ w9_lo:2;
+ uint8_t w12_hi:2,
+ w11:6;
+ uint8_t w13_hi:4,
+ w12_lo:4;
+ uint8_t w14:6,
+ w13_lo:2;
+ uint8_t w16_hi:2,
+ w15:6;
+ uint8_t w17:5,
+ w16_lo:3;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.1b.5 */
+struct gsm48_range_256 {
+ uint8_t orig_arfcn_hi:1,
+ form_id:7;
+ uint8_t orig_arfcn_mid;
+ uint8_t w1_hi:7,
+ orig_arfcn_lo:1;
+ uint8_t w2:7,
+ w1_lo:1;
+ uint8_t w4_hi:1,
+ w3:7;
+ uint8_t w5_hi:3,
+ w4_lo:5;
+ uint8_t w6_hi:5,
+ w5_lo:3;
+ uint8_t w8_hi:1,
+ w7:6,
+ w6_lo:1;
+ uint8_t w9_hi:4,
+ w8_lo:4;
+ uint8_t w11_hi:2,
+ w10:5,
+ w9_lo:1;
+ uint8_t w12:5,
+ w11_lo:3;
+ uint8_t w14_hi:3,
+ w13:5;
+ uint8_t w16_hi:1,
+ w15:5,
+ w14_lo:2;
+ uint8_t w18_hi:1,
+ w17:4,
+ w16_lo:3;
+ uint8_t w20_hi:1,
+ w19:4,
+ w18_lo:3;
+ uint8_t spare:1,
+ w21:4,
+ w20_lo:3;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.1b.6 */
+struct gsm48_range_128 {
+ uint8_t orig_arfcn_hi:1,
+ form_id:7;
+ uint8_t orig_arfcn_mid;
+ uint8_t w1:7,
+ orig_arfcn_lo:1;
+ uint8_t w3_hi:2,
+ w2:6;
+ uint8_t w4_hi:4,
+ w3_lo:4;
+ uint8_t w6_hi:2,
+ w5:5,
+ w4_lo:1;
+ uint8_t w7:5,
+ w6_lo:3;
+ uint8_t w9:4,
+ w8:4;
+ uint8_t w11:4,
+ w10:4;
+ uint8_t w13:4,
+ w12:4;
+ uint8_t w15:4,
+ w14:4;
+ uint8_t w18_hi:2,
+ w17:3,
+ w16:3;
+ uint8_t w21_hi:1,
+ w20:3,
+ w19:3,
+ w18_lo:1;
+ uint8_t w23:3,
+ w22:3,
+ w21_lo:2;
+ uint8_t w26_hi:2,
+ w25:3,
+ w24:3;
+ uint8_t spare:1,
+ w28:3,
+ w27:3,
+ w26_lo:1;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.1b.7 */
+struct gsm48_var_bit {
+ uint8_t orig_arfcn_hi:1,
+ form_id:7;
+ uint8_t orig_arfcn_mid;
+ uint8_t rrfcn1_7:7,
+ orig_arfcn_lo:1;
+ uint8_t rrfcn8_111[13];
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.5 */
+struct gsm48_chan_desc {
+ uint8_t chan_nr;
+ union {
+ struct {
+ uint8_t maio_high:4,
+ h:1,
+ tsc:3;
+ uint8_t hsn:6,
+ maio_low:2;
+ } h1;
+ struct {
+ uint8_t arfcn_high:2,
+ spare:2,
+ h:1,
+ tsc:3;
+ uint8_t arfcn_low;
+ } h0;
+ };
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.20 */
+struct gsm48_meas_res {
+ uint8_t rxlev_full:6,
+ dtx_used:1,
+ ba_used:1;
+ uint8_t rxlev_sub:6,
+ meas_valid:1,
+ spare:1;
+ uint8_t no_nc_n_hi:1,
+ rxqual_sub:3,
+ rxqual_full:3,
+ spare2:1;
+ uint8_t rxlev_nc1:6,
+ no_nc_n_lo:2;
+ uint8_t bsic_nc1_hi:3,
+ bcch_f_nc1:5;
+ uint8_t rxlev_nc2_hi:5,
+ bsic_nc1_lo:3;
+ uint8_t bsic_nc2_hi:2,
+ bcch_f_nc2:5,
+ rxlev_nc2_lo:1;
+ uint8_t rxlev_nc3_hi:4,
+ bsic_nc2_lo:4;
+ uint8_t bsic_nc3_hi:1,
+ bcch_f_nc3:5,
+ rxlev_nc3_lo:2;
+ uint8_t rxlev_nc4_hi:3,
+ bsic_nc3_lo:5;
+ uint8_t bcch_f_nc4:5,
+ rxlev_nc4_lo:3;
+ uint8_t rxlev_nc5_hi:2,
+ bsic_nc4:6;
+ uint8_t bcch_f_nc5_hi:4,
+ rxlev_nc5_lo:4;
+ uint8_t rxlev_nc6_hi:1,
+ bsic_nc5:6,
+ bcch_f_nc5_lo:1;
+ uint8_t bcch_f_nc6_hi:3,
+ rxlev_nc6_lo:5;
+ uint8_t bsic_nc6:6,
+ bcch_f_nc6_lo:2;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.21aa */
+struct gsm48_multi_rate_conf {
+ uint8_t smod : 2,
+ spare: 1,
+ icmi : 1,
+ nscb : 1,
+ ver : 3;
+ uint8_t m4_75 : 1,
+ m5_15 : 1,
+ m5_90 : 1,
+ m6_70 : 1,
+ m7_40 : 1,
+ m7_95 : 1,
+ m10_2 : 1,
+ m12_2 : 1;
+} __attribute__((packed));
+
+/* Chapter 10.5.2.28(a) */
+struct gsm48_power_cmd {
+ uint8_t power_level:5,
+ spare:2,
+ atc:1;
+} __attribute__((packed));
+
+/* Chapter 10.5.2.29 */
+struct gsm48_rach_control {
+ uint8_t re :1,
+ cell_bar :1,
+ tx_integer :4,
+ max_trans :2;
+ uint8_t t2;
+ uint8_t t3;
+} __attribute__ ((packed));
+
+
+/* Chapter 10.5.2.30 */
+struct gsm48_req_ref {
+ uint8_t ra;
+ uint8_t t3_high:3,
+ t1:5;
+ uint8_t t2:5,
+ t3_low:3;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.38 */
+struct gsm48_start_time {
+ uint8_t t3_high:3,
+ t1:5;
+ uint8_t t2:5,
+ t3_low:3;
+} __attribute__ ((packed));
+
+/* Chapter 10.5.2.39 */
+struct gsm48_sync_ind {
+ uint8_t si:2,
+ rot:1,
+ nci:1,
+ sync_ie:4;
+} __attribute__((packed));
+
+/*
+ * Chapter 9.1.5/9.1.6
+ *
+ * For 9.1.6 the chan_desc has the meaning of 10.5.2.5a
+ */
+struct gsm48_chan_mode_modify {
+ struct gsm48_chan_desc chan_desc;
+ uint8_t mode;
+} __attribute__ ((packed));
+
+enum gsm48_chan_mode {
+ GSM48_CMODE_SIGN = 0x00,
+ GSM48_CMODE_SPEECH_V1 = 0x01,
+ GSM48_CMODE_SPEECH_EFR = 0x21,
+ GSM48_CMODE_SPEECH_AMR = 0x41,
+ GSM48_CMODE_DATA_14k5 = 0x0f,
+ GSM48_CMODE_DATA_12k0 = 0x03,
+ GSM48_CMODE_DATA_6k0 = 0x0b,
+ GSM48_CMODE_DATA_3k6 = 0x23,
+};
+
+/* Chapter 9.1.2 */
+struct gsm48_ass_cmd {
+ /* Semantic is from 10.5.2.5a */
+ struct gsm48_chan_desc chan_desc;
+ uint8_t power_command;
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Chapter 9.1.13 */
+struct gsm48_frq_redef {
+ /* Semantic is from 10.5.2.5a */
+ struct gsm48_chan_desc chan_desc;
+ uint8_t mob_alloc_len;
+ uint8_t mob_alloc[0];
+} __attribute__((packed));
+
+/* Chapter 10.5.2.2 */
+struct gsm48_cell_desc {
+ uint8_t bcc:3,
+ ncc:3,
+ arfcn_hi:2;
+ uint8_t arfcn_lo;
+} __attribute__((packed));
+
+/* Chapter 9.1.15 */
+struct gsm48_ho_cmd {
+ struct gsm48_cell_desc cell_desc;
+ struct gsm48_chan_desc chan_desc;
+ uint8_t ho_ref;
+ uint8_t power_command;
+ uint8_t data[0];
+} __attribute__((packed));
+
+/* Chapter 9.1.18 */
+struct gsm48_imm_ass {
+ uint8_t l2_plen;
+ uint8_t proto_discr;
+ uint8_t msg_type;
+ uint8_t page_mode;
+ struct gsm48_chan_desc chan_desc;
+ struct gsm48_req_ref req_ref;
+ uint8_t timing_advance;
+ uint8_t mob_alloc_len;
+ uint8_t mob_alloc[0];
+} __attribute__ ((packed));
+
+/* Chapter 9.1.25 */
+struct gsm48_pag_resp {
+ uint8_t spare:4,
+ key_seq:4;
+ uint32_t classmark2;
+ uint8_t mi_len;
+ uint8_t mi[0];
+} __attribute__ ((packed));
+
+/* Chapter 10.5.1.3 */
+struct gsm48_loc_area_id {
+ uint8_t digits[3]; /* BCD! */
+ uint16_t lac;
+} __attribute__ ((packed));
+
+/* Section 9.2.2 */
+struct gsm48_auth_req {
+ uint8_t key_seq:4,
+ spare:4;
+ uint8_t rand[16];
+} __attribute__ ((packed));
+
+/* Section 9.2.3 */
+struct gsm48_auth_resp {
+ uint8_t sres[4];
+} __attribute__ ((packed));
+
+/* Section 9.2.15 */
+struct gsm48_loc_upd_req {
+ uint8_t type:4,
+ key_seq:4;
+ struct gsm48_loc_area_id lai;
+ struct gsm48_classmark1 classmark1;
+ uint8_t mi_len;
+ uint8_t mi[0];
+} __attribute__ ((packed));
+
+/* Section 10.1 */
+struct gsm48_hdr {
+ uint8_t proto_discr;
+ uint8_t msg_type;
+ uint8_t data[0];
+} __attribute__ ((packed));
+
+/* Section 9.1.3x System information Type header */
+struct gsm48_system_information_type_header {
+ uint8_t l2_plen;
+ uint8_t rr_protocol_discriminator :4,
+ skip_indicator:4;
+ uint8_t system_information;
+} __attribute__ ((packed));
+
+/* Section 10.5.2.4 Cell Selection Parameters */
+struct gsm48_cell_sel_par {
+ uint8_t ms_txpwr_max_ccch:5, /* GSM 05.08 MS-TXPWR-MAX-CCCH */
+ cell_resel_hyst:3; /* GSM 05.08 CELL-RESELECT-HYSTERESIS */
+ uint8_t rxlev_acc_min:6, /* GSM 05.08 RXLEV-ACCESS-MIN */
+ neci:1,
+ acs:1;
+} __attribute__ ((packed));
+
+/* Section 10.5.2.11 Control Channel Description , Figure 10.5.33 */
+struct gsm48_control_channel_descr {
+ uint8_t ccch_conf :3,
+ bs_ag_blks_res :3,
+ att :1,
+ spare1 :1;
+ uint8_t bs_pa_mfrms : 3,
+ spare2 :5;
+ uint8_t t3212;
+} __attribute__ ((packed));
+
+struct gsm48_cell_options {
+ uint8_t radio_link_timeout:4,
+ dtx:2,
+ pwrc:1,
+ spare:1;
+} __attribute__ ((packed));