add GPRS/EGPRS MAC + RLC layer DIAG related definitions
diff --git a/src/gprs_mac.c b/src/gprs_mac.c
new file mode 100644
index 0000000..b2073be
--- /dev/null
+++ b/src/gprs_mac.c
@@ -0,0 +1,86 @@
+#include <osmocom/core/utils.h>
+
+#include "gprs_mac.h"
+
+struct value_string gprs_mac_mode_vals[] = {
+	{ NULL_MODE,	"NULL" },
+	{ IDLE_MODE,	"IDLE" },
+	{ TRANSFER_MODE, "TRANSFER" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_mac_null_substate_vals[] = {
+	{ NULL_INACTIVE, 		"INACTIVE" },
+	{ NULL_GPRS_51_ACTIVE,		"GPRS_51_ACTIVE" },
+	{ NULL_SUSPENDED,		"SUSPENDED" },
+	{ NULL_SUSPEND_RESEL,		"SUSPEND_RESEL" },
+	{ NULL_UPLINK_TBF_ESTAB,	"UL_TBF_EST" },
+	{ NULL_UPLINK_SB_ESTAB,		"UL_SB_EST" },
+	{ NULL_DOWNLINK_SB_ESTAB,	"DL_SB_EST" },
+	{ NULL_UPLINK_TBF_ACCESS,	"UL_TBF_ACCESS" },
+	{ NULL_DL_TBF_EST,		"DL_TBF_EST" },
+	{ NULL_DTM_CONNECT_PENDING,	"DTM_CONN_PEND" },
+	{ NULL_DTM_GTTP_UL_CON,		"DTM_GTTP_UL_ON" },
+	{ NULL_RESET,			"RESET" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_mac_idle_substate_vals[] = {
+	{ IDLE_PASSIVE,			"PASSIVE" },
+	{ IDLE_UL_PACKET_ACCESS,	"PACKET_ACCESS" },
+	{ IDLE_UL_ACCESS_QUEUED,	"ACCESS_QUEUED" },
+	{ IDLE_UL_ACCESS_REJECT,	"ACCESS_REJECT" },
+	{ IDLE_UL_1PHASE_ASS,		"1PHASE_ASS" },
+	{ IDLE_UL_2PHASE_ASS,		"2PHASE_ASS" },
+	{ IDLE_UL_1PHASE_CONT_RES,	"1PHASE_CONT_RES" },
+	{ IDLE_DL_ASS,			"DL_ASS" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_mac_transfer_substate_vals[] = {
+	{ TRANSFER_INACTIVE,		"INACTIVE" },
+	{ TRANSFER_DL,			"DL" },
+	{ TRANSFER_DL_REASSIGN,		"DL_REASSIGN" },
+	{ TRANSFER_DL_WITH_DYNAMIC_ALLOC, "DL_WITH_DYNAMIC_ALLOC" },
+	{ TRANSFER_DL_REASSIGN_DYNAMIC_ALLOC, "DL_REASSIGN_DYNAMIC_ALLOC" },
+	{ TRANSFER_UL_DYNAMIC,		"UL_DYNAMIC" },
+	{ TRANSFER_UL_DYNAMIC_REALLOC,	"UL_DYNAMIC_REALLOC" },
+	{ TRANSFER_UL_DYNAMIC_DL_ASSIGN, "UL_DYNAMIC_DL_ASSIGN" },
+	{ TRANSFER_UL_DYNAMIC_REALLOC_DL_ASSIGN, "UL_DYNAMIC_REALLOC_DL_ASSIGN" },
+	{ TRANSFER_CONCURRENT_DYNAMIC_TRANSFER, "CONCURRENT_DYNAMIC_TRANSFER" },
+	{ TRANSFER_CONCURRENT_DYNAMIC_DL_REASSIGN, "CONCURRENT_DYNAMIC_DL_REASSIGN" },
+	{ TRANSFER_CONCURRENT_DYNAMIC_REALLOC,	"CONCURRENT_DYNAMIC_REALLOC" },
+	{ TRANSFER_CONCURRENT_DL_REASSIGN_DYNAMIC_REALLOC, "CONCURRENT_DL_REASSIGN_DYNAMIC_REALLOC" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_mac_chan_type_vals[] = {
+	{ PRACH_11BIT_CHANNEL,	"PRACH_11BIT_CHANNEL" },
+	{ PRACH_8BIT_CHANNEL,	"PRACH_8BIT_CHANNEL" },
+	{ PACCH_RRBP_CHANNEL,	"PACCH_RRBP_CHANNEL" },
+	{ UL_PACCH_CHANNEL, 	"UL_PACCH_CHANNEL" },
+	{ PCCCH_CHANNEL,	"PCCCH_CHANNEL" },
+	{ PBCCH_CHANNEL,	"PBCCH_CHANNEL" },
+	{ DL_PACCH_CHANNEL,	"DL_PACCH_CHANNEL" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_mac_msg_type_vals[] = {
+	{ PACKET_CELL_CHANGE_FAILURE,		"PACKET_CELL_CHANGE_FAILURE" },
+	{ PACKET_CONTROL_ACKNOWLEDGE,		"PACKET_CONTROL_ACKNOWLEDGE" },
+	{ PACKET_DOWNLINK_ACK_NACK,		"PACKET_DOWNLINK_ACK_NACK" },
+	{ PACKET_UPLK_DUMMY_CNTRL_BLK,		"PACKET_UPLK_DUMMY_CNTRL_BLK" },
+	{ PACKET_MEASUREMENT_REPORT,		"PACKET_MEASUREMENT_REPORT" },
+	{ PACKET_RESOURCE_REQUEST,		"PACKET_RESOURCE_REQUEST" },
+	{ PACKET_MOBILE_TBF_STATUS,		"PACKET_MOBILE_TBF_STATUS" },
+	{ PACKET_PSI_STATUS,			"PACKET_PSI_STATUS" },
+	{ EGPRS_PACKET_DOWNLINK_ACK_NACK,	"EGPRS_PACKET_DOWNLINK_ACK_NACK" },
+	{ PACKET_PAUSE,				"PACKET_PAUSE" },
+	{ PACKET_ENHANCED_MEASUREMENT_REPORT,	"PACKET_ENHANCED_MEASUREMENT_REPORT" },
+	{ ADDITIONAL_MS_RAC,			"ADDITIONAL_MS_RAC" },
+	{ PACKET_CELL_CHANGE_NOTIFICATION,	"PACKET_CELL_CHANGE_NOTIFICATION" },
+	{ PACKET_SI_STATUS,			"PACKET_SI_STATUS" },
+	{ PACKET_CS_REQUEST,			"PACKET_CS_REQUEST" },
+	{ PACKET_CHANNEL_REQUEST,		"PACKET_CHANNEL_REQUEST" },
+	{ 0, NULL }
+};
diff --git a/src/gprs_mac.h b/src/gprs_mac.h
new file mode 100644
index 0000000..3149351
--- /dev/null
+++ b/src/gprs_mac.h
@@ -0,0 +1,147 @@
+#include <stdint.h>
+
+enum gprs_mac_mode {
+	NULL_MODE,
+	IDLE_MODE,
+	TRANSFER_MODE,
+};
+
+enum gprs_mac_null_substates {
+	NULL_INACTIVE,
+	NULL_GPRS_51_ACTIVE,
+	NULL_SUSPENDED,
+	NULL_SUSPEND_RESEL,
+	NULL_UPLINK_TBF_ESTAB,
+	NULL_UPLINK_SB_ESTAB,
+	NULL_DOWNLINK_SB_ESTAB,
+	NULL_UPLINK_TBF_ACCESS,
+	NULL_DL_TBF_EST,
+	NULL_DTM_CONNECT_PENDING,
+	NULL_DTM_GTTP_UL_CON,
+	NULL_RESET,
+};
+
+enum gprs_mac_idle_substates {
+	IDLE_PASSIVE,
+	IDLE_UL_PACKET_ACCESS,
+	IDLE_UL_ACCESS_QUEUED,
+	IDLE_UL_ACCESS_REJECT,
+	IDLE_UL_1PHASE_ASS,
+	IDLE_UL_2PHASE_ASS,
+	IDLE_UL_1PHASE_CONT_RES,
+	IDLE_DL_ASS,
+};
+
+enum gprs_mac_transfer_substates {
+	TRANSFER_INACTIVE,
+	TRANSFER_DL,
+	TRANSFER_DL_REASSIGN,
+	TRANSFER_DL_WITH_DYNAMIC_ALLOC,
+	TRANSFER_DL_REASSIGN_DYNAMIC_ALLOC,
+	TRANSFER_UL_DYNAMIC,
+	TRANSFER_UL_DYNAMIC_REALLOC,
+	TRANSFER_UL_DYNAMIC_DL_ASSIGN,
+	TRANSFER_UL_DYNAMIC_REALLOC_DL_ASSIGN,
+	TRANSFER_CONCURRENT_DYNAMIC_TRANSFER,
+	TRANSFER_CONCURRENT_DYNAMIC_DL_REASSIGN,
+	TRANSFER_CONCURRENT_DYNAMIC_REALLOC,
+	TRANSFER_CONCURRENT_DL_REASSIGN_DYNAMIC_REALLOC,
+};
+
+/* LOG_GPRS_MAC_STATE_C */
+struct gprs_mac_state_change {
+	uint8_t mac_mode;
+	uint8_t mac_null_fsm_state;
+	uint8_t mac_idle_fsm_state;
+	uint8_t mac_transfer_fsm_state;
+} __attribute__((packed));
+
+/* LOG_GPRS_MAC_SIGNALLING_MESSAGE_C */
+struct gprs_mac_signalling_msg {
+	uint8_t chan_type;
+	uint8_t msg_type;
+	uint8_t msg_len;
+	uint8_t msg[0];
+} __attribute__((packed));
+
+/* LOG_GPRS_MAC_DL_TBF_ESTABLISH_C */
+struct gprs_mac_dl_tbf_est {
+	uint8_t dl_tfi;
+	uint8_t rlc_mode;
+	uint8_t dl_ts_bmap;
+	uint8_t is_egprs_tbf;
+	uint16_t egprs_win_size;
+	uint8_t egprs_link_qual_mode;
+	uint8_t bep_period2;
+} __attribute__((packed));
+
+/* LOG_GPRS_MAC_UL_TBF_ESTABLISH_C */
+struct gprs_mcc_ul_tbf_est {
+	uint8_t tbf_req_cause;
+	uint8_t acc_granted;
+	uint8_t radio_prio;
+	uint8_t peak_tput;
+	uint8_t ul_tfi;
+	uint8_t rlc_mode;
+	uint8_t ul_ts_bmap;
+
+	uint8_t is_egprs_tbf;
+	uint16_t egprs_win_size;
+	uint8_t resegment;
+	uint8_t bep_period2;
+} __attribute__ ((packed));
+
+/* LOG_EGPRS_MAC_DL_ACKNACK_C */
+struct gprs_mac_dl_acknack {
+	uint8_t is_egprs;
+	uint8_t dl_acknack[0];
+} __attribute__ ((packed));
+
+/* LOG_EGPRS_MAC_UL_ACKNACK_C */
+struct gprs_mac_ul_acknack {
+	uint8_t ul_acknack[0];
+} __attribute__ ((packed));
+
+/* identical for LOG_GPRS_MAC_UL_TBF_RELEASE_C and
+ * LOG_GPRS_MAC_DL_TBF_RELEASE_C */
+struct gprs_mac_tbf_release {
+	uint8_t tfi;
+	uint8_t fail_cause;
+} __attribute__ ((packed));
+
+
+/* EVENT_GPRS_MAC_MSG_RECEIVED / EVENT_GPRS_MAC_MSG_SENT */
+enum gprs_mac_chan_type {
+	PRACH_11BIT_CHANNEL	= 0x01,
+	PRACH_8BIT_CHANNEL	= 0x02,
+	PACCH_RRBP_CHANNEL	= 0x03,
+	UL_PACCH_CHANNEL	= 0x04,
+	PCCCH_CHANNEL		= 0x81,
+	PBCCH_CHANNEL		= 0x82,
+	DL_PACCH_CHANNEL	= 0x83,
+};
+
+enum gprs_mac_msg_type {
+	PACKET_CELL_CHANGE_FAILURE		= 0x00,
+	PACKET_CONTROL_ACKNOWLEDGE		= 0x01,
+	PACKET_DOWNLINK_ACK_NACK		= 0x02,
+	PACKET_UPLK_DUMMY_CNTRL_BLK		= 0x03,
+	PACKET_MEASUREMENT_REPORT		= 0x04,
+	PACKET_RESOURCE_REQUEST			= 0x05,
+	PACKET_MOBILE_TBF_STATUS		= 0x06,
+	PACKET_PSI_STATUS			= 0x07,
+	EGPRS_PACKET_DOWNLINK_ACK_NACK		= 0x08,
+	PACKET_PAUSE				= 0x09,
+	PACKET_ENHANCED_MEASUREMENT_REPORT	= 0x0a,
+	ADDITIONAL_MS_RAC			= 0x0b,
+	PACKET_CELL_CHANGE_NOTIFICATION		= 0x0c,
+	PACKET_SI_STATUS			= 0x0d,
+	PACKET_CS_REQUEST			= 0x0e,
+	PACKET_CHANNEL_REQUEST			= 0x20,
+};
+
+struct evt_gprs_mac_msg {
+	uint8_t msg_type;
+	uint8_t prot_disc;
+	uint8_t chan_type;
+} __attribute__ ((packed));
diff --git a/src/gprs_rlc.c b/src/gprs_rlc.c
new file mode 100644
index 0000000..31e7128
--- /dev/null
+++ b/src/gprs_rlc.c
@@ -0,0 +1,40 @@
+#include <osmocom/core/utils.h>
+
+#include "gprs_rlc.h"
+
+struct value_string gprs_rlc_ul_state_vals[] = {
+	{ US_NULL,		"US_NULL" },
+	{ US_AWAIT_ASS,		"US_AWAIT_ASS" },
+	{ US_ACK_XFER,		"US_AWAIT_XFER" },
+	{ US_GTTP_XFER,		"US_GTTP_XFER" },
+	{ US_UNACK_XFER,	"US_UNACK_XFER" },
+	{ US_TEST_MODE,		"US_TEST_MODE" },
+	{ US_AWAIT_RECOVERY,	"US_AWAIT_RECOVERY" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_rlc_ul_substate_vals[] = {
+	{ RALS_NULL,		"RALS_NULL" },
+	{ RALS_AWAIT_TX_COMPLETE, "RALS_AWAIT_TX_COMPLETE" },
+	{ RALS_CURRENT_PDU_TX_COMPLETED, "RALS_CURRENT_PDU_TX_COMPLETED" },
+	{ RALS_COMPLETE,	"RALS_COMPLETE" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_rlc_dl_state_vals[] = {
+	{ DS_NULL,		"DS_NULL" },
+	{ DS_RX_ACK,		"DS_RX_ACK" },
+	{ DS_RX_UNACK,		"DS_RX_UNACK" },
+	{ DS_RX_ACK_PENDING_RELEASE, "DS_RX_ACK_PENDING_RELEASE" },
+	{ DS_RX_UNACK_PENDING_RELEASE, "DS_RX_UNACK_PENDING_RELEASE" },
+	{ DS_TEST_MODE,		"DS_TEST_MODE" },
+	{ 0, NULL }
+};
+
+struct value_string gprs_rlc_hdr_type_vals[] = {
+	{ GPRS_HEADER_TYPE,	"GPRS" },
+	{ EGPRS_HEADER_TYPE_1,	"EGPRS T1" },
+	{ EGPRS_HEADER_TYPE_2,	"EGPRS T2" },
+	{ EGPRS_HEADER_TYPE_3,	"EGPRS T3" },
+	{ 0, NULL }
+};
diff --git a/src/gprs_rlc.h b/src/gprs_rlc.h
new file mode 100644
index 0000000..545eaef
--- /dev/null
+++ b/src/gprs_rlc.h
@@ -0,0 +1,137 @@
+#include <stdint.h>
+
+/* LOG_GPRS_RLC_UL_ABNRML_RLS_COUNTS_C */
+struct gprs_rlc_ul_abnrml_rls_counts {
+	uint16_t access_reject_cnt;
+	uint16_t arc_retry_cnt;
+	uint16_t arc_wo_retry_cnt;
+	uint16_t arc_sys_info_cnt;
+} __attribute__ ((packed));
+
+/* LOG_GPRS_RLC_UL_EVENT_COUNTS_C */
+struct gprs_rlc_ul_event_counts {
+	uint16_t llc_event_cnt;
+	uint16_t mac_event_cnt;
+	uint16_t pl1_event_cnt;
+	uint16_t tmr_event_cnt;
+} __attribute__ ((packed));
+
+/* LOG_GPRS_RLC_UL_STATS_C */
+enum gprs_rlc_ul_state {
+	US_NULL,
+	US_AWAIT_ASS,
+	US_ACK_XFER,
+	US_GTTP_XFER, // optional
+	US_UNACK_XFER,
+	US_TEST_MODE,
+	US_AWAIT_RECOVERY,
+};
+
+enum gprs_rlc_ul_substate {
+	RALS_NULL,
+	RALS_AWAIT_TX_COMPLETE,
+	RALS_CURRENT_PDU_TX_COMPLETED,
+	RALS_COMPLETE,
+};
+
+enum gprs_rlc_dl_state {
+	DS_NULL,
+	DS_RX_ACK,
+	DS_RX_UNACK,
+	DS_RX_ACK_PENDING_RELEASE,
+	DS_RX_UNACK_PENDING_RELEASE,
+	DS_TEST_MODE,
+};
+
+struct gprs_rlc_ul_stats {
+	uint8_t	rlc_ul_state;
+	uint8_t rlc_ul_substate;
+	uint32_t ack_tx_pdu_cnt;
+	uint32_t ack_tx_oct_cnt;
+	uint32_t unack_tx_pdu_cnt;
+	uint32_t unack_tx_oct_cnt;
+	uint16_t coding_sch_changes;
+	uint8_t ul_seq_va;
+	uint8_t ul_seq_vs;
+	uint8_t ul_seq_nseg;
+	uint8_t ul_seq_vsf;
+	uint8_t ul_seq_pack_vsf;
+	uint8_t ul_seq_nack_vsf;
+	int8_t ul_n3102;
+	int8_t ul_n3104;
+	uint32_t ul_gen_p_cnt_a;
+	uint32_t ul_gen_p_cnt_b;
+	uint32_t ul_gen_p_cnt_c;
+} __attribute__ ((packed));
+
+/* LOG_GPRS_RLC_DL_STATS_C */
+struct gprs_rlc_dl_stats {
+	uint8_t	rlc_dl_state;
+	uint32_t ack_rx_pdu_cnt;
+	uint32_t ack_rx_oct_cnt;
+	uint32_t unack_rx_pdu_cnt;
+	uint32_t unack_pdu_filled_cnt;
+	uint32_t unack_rx_oct_cnt;
+	uint32_t unack_oct_filled_cnt;
+	uint32_t ack_nack_req_cnt;
+	uint8_t dl_seq_vq;
+	uint8_t dl_seq_vr;
+	uint8_t dl_seq_ssn;
+	uint32_t dl_gen_p_cnt_a;
+	uint32_t dl_gen_p_cnt_b;
+	uint32_t dl_gen_p_cnt_c;
+} __attribute__ ((packed));
+
+/* LOG_GPRS_RLC_UL_ACKNACK_PARAMS_VER2_C */
+struct gprs_rlc_ul_acknack_params_v2 {
+	uint8_t ul_tfi;
+	uint8_t fai;
+	uint8_t ssn;
+	uint8_t cs;
+	uint8_t cv;
+	uint8_t va;
+	uint8_t vs;
+	uint8_t si;
+	uint32_t hu32;
+	uint32_t lu32;
+} __attribute__ ((packed));
+
+/* LOG_GPRS_RLC_DL_ACKNACK_PARAMS_VER2_C */
+struct gprs_rlc_dl_acknack_params_v2 {
+	uint8_t dl_tfi;
+	uint8_t fai;
+	uint8_t ssn;
+	uint8_t vq;
+	uint32_t hu32;
+	uint32_t lu32;
+	uint8_t cs;
+} __attribute__ ((packed));
+
+/* LOG_GPRS_RLC_UL_RELEASE_IND_C + LOG_GPRS_RLC_DL_RELEASE_IND_C */
+struct gprs_rlc_release_ind {
+	uint8_t tfi;
+	uint8_t cause;
+} __attribute__ ((packed));
+
+enum gprs_rlc_hdr_type {
+	GPRS_HEADER_TYPE,
+	EGPRS_HEADER_TYPE_1,
+	EGPRS_HEADER_TYPE_2,
+	EGPRS_HEADER_TYPE_3
+};
+
+/* LOG_EGPRS_RLC_DL_HEADER_C */
+struct gprs_rlc_dl_header {
+	uint8_t type;
+	uint8_t ul_hdr[5];
+	uint8_t crc_status;
+	uint8_t ts;
+	uint32_t fn;
+	uint8_t dl_payload[6];
+} __attribute__ ((packed));
+
+/* LOG_EGPRS_RLC_UL_HEADER_C */
+struct gprs_rlc_ul_header {
+	uint8_t type;
+	uint8_t ul_hdr[6];
+} __attribute__ ((packed));