aboutsummaryrefslogtreecommitdiffstats
path: root/src/gprs_rlcmac.h
blob: ed0850bb926363145f38d3a1a330e9d3e7b4af45 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
/* gprs_rlcmac.h
 *
 * Copyright (C) 2012 Ivan Klyuchnikov
 *
 * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
 */
 
#ifndef GPRS_RLCMAC_H
#define GPRS_RLCMAC_H

#include <bitvector.h>
#include <gsm_rlcmac.h>
#include <gsm_timer.h>

extern "C" {
#include <osmocom/core/linuxlist.h>
#include <osmocom/core/timer.h>
}

#define LLC_MAX_LEN 1543
#define UL_RLC_DATA_BLOCK_LEN 23

enum gprs_rlcmac_tbf_stage {
	TBF_ESTABLISH,
	TBF_DATA_TRANSFER,
	TBF_RELEASE
};

enum gprs_rlcmac_tbf_state {
	WAIT_ESTABLISH,
	CCCH_ESTABLISH,
	PACCH_ESTABLISH,
	FINISH_ESTABLISH,
	WAIT_DATA_TRANSFER,
	DATA_TRANSFER,
	FINISH_DATA_TRANSFER,
	RELEASE
};

enum gprs_rlcmac_tbf_direction {
	GPRS_RLCMAC_DL_TBF,
	GPRS_RLCMAC_UL_TBF
};

struct tbf_llc_pdu {
	struct llist_head list;
	uint8_t num;
	uint8_t data[LLC_MAX_LEN];
	uint16_t len;
};

struct gprs_rlcmac_tbf {
	struct llist_head list;
	enum gprs_rlcmac_tbf_state state;
	enum gprs_rlcmac_tbf_stage stage;
	enum gprs_rlcmac_tbf_direction direction;
	struct gprs_rlcmac_tbf *next_tbf;
	uint8_t tfi;
	uint32_t tlli;
	
	struct llist_head llc_pdus;
	struct tbf_llc_pdu llc_pdu;
	uint8_t llc_pdu_list_len;
	uint8_t rlc_data[LLC_MAX_LEN];
	uint16_t data_index;
	uint8_t bsn;
	uint8_t trx, ts, tsc;
	uint16_t arfcn, ta;
	
	struct osmo_timer_list	timer;
	unsigned int T; /* Txxxx number */
	unsigned int num_T_exp; /* number of consecutive T expirations */
	
	struct osmo_gsm_timer_list	gsm_timer;
	unsigned int fT; /* fTxxxx number */
	unsigned int num_fT_exp; /* number of consecutive fT expirations */
};

/* TS 44.060 Section 10.4.7 Table 10.4.7.1: Payload Type field */
enum gprs_rlcmac_block_type {
	GPRS_RLCMAC_DATA_BLOCK = 0x0,
	GPRS_RLCMAC_CONTROL_BLOCK = 0x1, 
	GPRS_RLCMAC_CONTROL_BLOCK_OPT = 0x2,
	GPRS_RLCMAC_RESERVED = 0x3
};

extern struct llist_head gprs_rlcmac_tbfs;

int select_pdch(uint8_t *_trx, uint8_t *_ts);

int tfi_alloc();

static struct gprs_rlcmac_tbf *tbf_by_tfi(uint8_t tfi, gprs_rlcmac_tbf_direction dir);

static struct gprs_rlcmac_tbf *tbf_by_tlli(uint32_t tlli, gprs_rlcmac_tbf_direction dir);

static void tbf_free(struct gprs_rlcmac_tbf *tbf);

static struct tbf_llc_pdu *tbf_llc_pdu_by_num(struct llist_head llc_pdus, uint8_t num);

int tbf_add_llc_pdu(struct gprs_rlcmac_tbf *tbf, uint8_t *data, uint16_t llc_pdu_len);

struct gprs_rlcmac_tbf *tbf_alloc(gprs_rlcmac_tbf_direction dir, uint32_t tlli = 0);

int tbf_ul_establish(struct gprs_rlcmac_tbf *tbf, uint8_t ra, uint32_t Fn, uint16_t qta);

int tbf_dl_establish(struct gprs_rlcmac_tbf *tbf);

int tbf_ul_data_transfer(struct gprs_rlcmac_tbf *tbf, RlcMacUplinkDataBlock_t * ul_data_block);

int tbf_dl_data_transfer(struct gprs_rlcmac_tbf *tbf, uint8_t *llc_pdu = NULL, uint16_t llc_pdu_len = 0);

int tbf_ul_release(struct gprs_rlcmac_tbf *tbf);

int tbf_dl_release(struct gprs_rlcmac_tbf *tbf);

static void tbf_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int T, unsigned int seconds);

static void tbf_gsm_timer_start(struct gprs_rlcmac_tbf *tbf, unsigned int fT, int frames);

int write_immediate_assignment(bitvec * dest, uint8_t downlink, uint8_t ra, uint32_t fn, uint8_t ta, uint16_t arfcn, uint8_t ts, uint8_t tsc, uint8_t tfi, uint32_t tlli = 0);

void gprs_rlcmac_tx_ul_ack(uint8_t tfi, uint32_t tlli, uint8_t ti, uint8_t bsn);

void gprs_rlcmac_data_block_parse(gprs_rlcmac_tbf* tbf, RlcMacUplinkDataBlock_t * ul_data_block);

int gprs_rlcmac_rcv_data_block(bitvec *rlc_block);

int gprs_rlcmac_rcv_control_block(bitvec *rlc_block);

void gprs_rlcmac_rcv_block(bitvec *rlc_block);

void gprs_rlcmac_rcv_rts_block(uint8_t trx, uint8_t ts, uint16_t arfcn, 
        uint32_t fn, uint8_t block_nr);

int gprs_rlcmac_rcv_rach(uint8_t ra, uint32_t Fn, int16_t qta);

int gprs_rlcmac_tx_llc_pdus(struct gprs_rlcmac_tbf *tbf);

void gprs_rlcmac_tx_ul_ud(gprs_rlcmac_tbf *tbf);

void gprs_rlcmac_downlink_assignment(gprs_rlcmac_tbf *tbf);

void gprs_rlcmac_packet_downlink_assignment(gprs_rlcmac_tbf *tbf);

void gprs_rlcmac_paging_request(uint8_t *ptmsi, uint16_t ptmsi_len);
#endif // GPRS_RLCMAC_H