FreeCalypso > hg > fc-tourmaline
comparison src/g23m-gsm/dl/dl_state.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:4e78acac3d88 | 1:fa8dc04885d8 |
---|---|
1 /* | |
2 +----------------------------------------------------------------------------- | |
3 | Project : GSM-PS | |
4 | Modul : DL_STATE | |
5 +----------------------------------------------------------------------------- | |
6 | Copyright 2002 Texas Instruments Berlin, AG | |
7 | All rights reserved. | |
8 | | |
9 | This file is confidential and a trade secret of Texas | |
10 | Instruments Berlin, AG | |
11 | The receipt of or possession of this file does not convey | |
12 | any rights to reproduce or disclose its contents or to | |
13 | manufacture, use, or sell anything it may describe, in | |
14 | whole, or in part, without the specific written consent of | |
15 | Texas Instruments Berlin, AG. | |
16 +----------------------------------------------------------------------------- | |
17 | Purpose : This Modul defines the state machine of the component DL | |
18 | (replaces the old channel dependent implementation) | |
19 +----------------------------------------------------------------------------- | |
20 */ | |
21 | |
22 #ifndef DL_STATE_C | |
23 #define DL_STATE_C | |
24 | |
25 #define ENTITY_DL | |
26 #define NEW_REJ_ACK /* Acknowledgement by valid reject frame | |
27 * in accordance with 3GPP 04.06, 5.5.3.1 | |
28 * "On receipt of a valid I frame or supervisory frame" | |
29 */ | |
30 | |
31 /*==== INCLUDES ===================================================*/ | |
32 | |
33 #include "typedefs.h" | |
34 #include <string.h> | |
35 #include "vsi.h" | |
36 #include "pconst.cdg" | |
37 #include "custom.h" | |
38 #include "gsm.h" | |
39 #include "mon_dl.h" | |
40 #include "prim.h" | |
41 #include "pei.h" | |
42 #include "tok.h" | |
43 #include "ccdapi.h" | |
44 #include "dl.h" | |
45 #include "dl_em.h" | |
46 #include "dl_trc.h" | |
47 | |
48 /*==== TYPEDEFS ===================================================*/ | |
49 typedef struct | |
50 { | |
51 UBYTE channel; | |
52 UBYTE sapi; | |
53 UBYTE state; | |
54 UBYTE T200_Stop; | |
55 UBYTE T200_Start; | |
56 UBYTE pf_bit_flag; | |
57 UBYTE dl_data_ind; | |
58 UBYTE mdl_error_ind; | |
59 T_CCH* pcch; | |
60 } T_CCH_INTERN; | |
61 #define T_CCH_INTERN_INIT {0,0,0,0,0,0,0} | |
62 | |
63 /*==== EXPORT =====================================================*/ | |
64 /*==== PRIVAT =====================================================*/ | |
65 static int frame_validation (UBYTE channel_type, UBYTE* frame); | |
66 | |
67 static int downlink_idle (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
68 static int downlink_contention_resolution (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
69 static int downlink_mfe (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
70 static int downlink_timer_recovery (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
71 static int downlink_awaiting_release (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
72 | |
73 static void downlink_mfe_information (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
74 static void downlink_mfe_supervisory (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
75 static void downlink_mfe_sabm (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
76 static void downlink_mfe_dm (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
77 static void downlink_mfe_tr_unnumbered (T_CCH_INTERN* pcch_i, UBYTE *frame, UBYTE state); | |
78 static void downlink_i_frame (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
79 static void downlink_tr_supervisory (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
80 static void downlink_tr_information (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
81 | |
82 static void invoke_retransmission (T_CCH_INTERN* pcch_i, UBYTE frame_nr); | |
83 static void enquiry_response (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
84 static void mdl_error_ind (UBYTE cause, UBYTE channel_type, UBYTE sapi); | |
85 static void nr_error_recovery (T_CCH_INTERN* pcch_i, UBYTE *frame); | |
86 static void concatenate (UBYTE ch_type, UBYTE sapi, UBYTE *frame); | |
87 static void free_sending_buffer (UBYTE ch_type, UBYTE sapi); | |
88 | |
89 static void repeat_sabm (UBYTE channel, UBYTE sapi); | |
90 static void delayed_release_ind(UBYTE channel); | |
91 | |
92 static int uplink_idle (UBYTE channel, UBYTE sapi); | |
93 static int uplink_awaiting_establishment (UBYTE channel, UBYTE sapi, UBYTE no_signalling_mode); | |
94 static int uplink_mfe (UBYTE channel, UBYTE sapi, UBYTE no_signalling_mode); | |
95 static int uplink_timer_recovery (UBYTE channel, UBYTE sapi, UBYTE no_signalling_mode); | |
96 | |
97 static void T200_expiry (UBYTE channel, UBYTE sapi); | |
98 | |
99 /*==== VARIABLES ==================================================*/ | |
100 | |
101 /*Removed the const from the definition,rework for issue 25370*/ | |
102 static UBYTE l2_empty_frame [25] = { | |
103 0x00, 0x00, /* the first two dummy bytes only for SACCH L1 header! */ | |
104 /* here begins the normal empty frame (SDCCH, FACCH) */ | |
105 0x01, /* address field: SAPI 0 */ | |
106 0x03, /* control field: UI frame */ | |
107 0x01, /* length field: length = 0 */ | |
108 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, | |
109 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, | |
110 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, | |
111 0x2b, 0x2b, 0x2b, 0x2b, 0x2b }; | |
112 #if 0 | |
113 static UBYTE l2_invalid_frame [25] = { | |
114 0x00, 0x00, /* the first two dummy bytes only for SACCH L1 header! */ | |
115 /* here begins the normal empty frame (SDCCH, FACCH) */ | |
116 0x1D, /* address field: SAPI 7 (unallocated SAPI; no action shall be taken on such frames) */ | |
117 0x03, /* control field: UI frame */ | |
118 0x01, /* length field: length = 0 */ | |
119 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, | |
120 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, | |
121 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, | |
122 0x2b, 0x2b, 0x2b, 0x2b, 0x2b }; | |
123 static UBYTE l2_invalid_frame_0 [25] = { | |
124 0x00, 0x00, /* the first two dummy bytes only for SACCH L1 header! */ | |
125 /* here begins the normal empty frame (SDCCH, FACCH) */ | |
126 0x00, /* address field: SAPI 0 */ | |
127 0x00, /* control field: UI frame */ | |
128 0x00, /* length field: length = 0 */ | |
129 0x00, 0x00, 0x00, 0x00, 0x00, | |
130 0x00, 0x00, 0x00, 0x00, 0x00, | |
131 0x00, 0x00, 0x00, 0x00, 0x00, | |
132 0x00, 0x00, 0x00, 0x00, 0x00 }; | |
133 #endif /* 0|1 */ | |
134 static T_CCH_INTERN cch_i; | |
135 | |
136 #if defined(CHECK_PCCHI) | |
137 #define CHECK_PCCH_I() if (check_pcch_i(pcch_i, __LINE__)()return; | |
138 #define CHECK_PCCH_Ir() if (check_pcch_i(pcch_i, __LINE__)()return -1; | |
139 #else | |
140 #define CHECK_PCCH_I() | |
141 #define CHECK_PCCH_Ir() | |
142 #endif /* CHECK_PCCHI */ | |
143 | |
144 /*==== FUNCTIONS ==================================================*/ | |
145 int dl_downlink (UBYTE error_flag, UBYTE channel_type, UBYTE* frame, ULONG fn) | |
146 { | |
147 UBYTE channel_state = STATE_INVALID; | |
148 UBYTE channel = NOT_PRESENT_8BIT; | |
149 UBYTE frame_sapi = PS_SAPI_0; /* to calm lint, will be new set for valid frames */ | |
150 static UBYTE invalid = 0; | |
151 int ret = -2; | |
152 int cause; | |
153 int l2_offset; | |
154 | |
155 GET_INSTANCE_DATA; | |
156 | |
157 TRACE_EVENT_WIN_P1 ("downlink(): dcch0_ch_type:%s", | |
158 CH_TYPE_NAME[dl_data->dcch0_ch_type]); | |
159 TRACE_EVENT_WIN_P6 ("DL: DCCH0=%s,%s vr=%u vs=%u va=%u T200=%u", | |
160 CH_TYPE_NAME[dl_data->cch[C_DCCH0].ch_type], | |
161 STATE_DCCH0_NAME[dl_data->state[C_DCCH0]], | |
162 dl_data->cch[C_DCCH0].vr, dl_data->cch[C_DCCH0].vs, dl_data->cch[C_DCCH0].va, | |
163 dl_data->cch[C_DCCH0].T200_counter); | |
164 TRACE_EVENT_WIN_P6 ("DL: DCCH3=%s,%s vr=%u vs=%u va=%u T200=%u", | |
165 CH_TYPE_NAME[dl_data->cch[C_DCCH3].ch_type], | |
166 STATE_DCCH3_NAME[dl_data->state[C_DCCH3]], | |
167 dl_data->cch[C_DCCH3].vr, dl_data->cch[C_DCCH3].vs, dl_data->cch[C_DCCH3].va, | |
168 dl_data->cch[C_DCCH3].T200_counter); | |
169 | |
170 if (channel_type EQ L2_CHANNEL_SACCH) | |
171 { | |
172 l2_offset = 2; /* with layer 1 header */ | |
173 } | |
174 else | |
175 { | |
176 l2_offset = 0; /* without layer 1 header */ | |
177 } | |
178 | |
179 #define RR_SHORT_PD_HANDLING | |
180 #if defined(RR_SHORT_PD_HANDLING) | |
181 /* Handling of unacknowledged UI frames with format type Bter */ | |
182 #if defined(RR_SHORT_PD_DETECT_KNOWN_MSG_ONLY) /* detection of known messages only */ | |
183 cause = 0; | |
184 switch (frame[l2_offset]) | |
185 { | |
186 case RR_SHORT_PD_SI10: | |
187 case RR_SHORT_PD_MEAS_INFO: | |
188 if (channel_type EQ L2_CHANNEL_SACCH) | |
189 cause = 1; | |
190 break; | |
191 case RR_SHORT_PD_NOTI_FACCH: | |
192 if ((channel_type EQ L2_CHANNEL_FACCH_F) OR | |
193 (channel_type EQ L2_CHANNEL_FACCH_H)) | |
194 cause = 1; | |
195 break; | |
196 case RR_SHORT_PD_UPLINK_FREE: | |
197 cause = 1; | |
198 break; | |
199 default: | |
200 break; | |
201 } | |
202 if (cause) | |
203 { | |
204 drr_dl_short_unitdata_ind (channel_type, error_flag, frame, | |
205 &frame[l2_offset], | |
206 (channel_type EQ L2_CHANNEL_SACCH) ? DL_N201_SACCH_Bter : DL_N201_DCCH_Bter, fn); | |
207 return 0; | |
208 } | |
209 #else /* detection of all possible messages with short L2 header and format Bter */ | |
210 TRACE_EVENT_WIN_P4 ("detection of format Bter: %02x&%02x=%02x ?= %02x", | |
211 frame[l2_offset], BTER_FORMAT_MASK, GET_BTER_FORMAT (&frame[l2_offset]), SHORT_L2_HEADER_TYPE_1); | |
212 if ((GET_BTER_FORMAT (&frame[l2_offset]) EQ SHORT_L2_HEADER_TYPE_1)) | |
213 { | |
214 drr_dl_short_unitdata_ind (channel_type, error_flag, frame, | |
215 &frame[l2_offset], | |
216 (UBYTE)((channel_type EQ L2_CHANNEL_SACCH) ? DL_N201_SACCH_Bter : DL_N201_DCCH_Bter), fn); | |
217 return 0; | |
218 } | |
219 #endif /* kind of Bter detection */ | |
220 #endif /* RR_SHORT_PD_HANDLING */ | |
221 | |
222 /* check frame */ | |
223 | |
224 if (error_flag EQ VALID_BLOCK) | |
225 { | |
226 frame_sapi = GET_SAPI (frame+l2_offset); | |
227 if ((frame_sapi NEQ PS_SAPI_0) AND (frame_sapi NEQ PS_SAPI_3)) | |
228 { | |
229 TRACE_EVENT_WIN_P1 ("downlink() returns -1 (wrong SAPI=%u)", frame_sapi); | |
230 return -1; | |
231 } | |
232 | |
233 cause = frame_validation (channel_type, frame+l2_offset); | |
234 if (cause >= 0) | |
235 { | |
236 TRACE_FUNCTION ("frame validation failed!"); | |
237 if (invalid EQ 0) | |
238 { | |
239 TRACE_ERROR ("invalid frame"); | |
240 invalid = 1; /* only one message per succession */ | |
241 } | |
242 mdl_error_ind ((UBYTE)cause, channel_type, frame_sapi); | |
243 return 0;/* ETSI GSM 04.06 Annex G.2 - G.4 */ | |
244 } | |
245 else | |
246 invalid = 0; | |
247 | |
248 #if defined(DL_2TO1) || defined(_SIMULATION_) | |
249 /* Handling of unacknowledged UI frames on SACCH with SAPI=0 (not format type Bter) */ | |
250 if ((channel_type EQ L2_CHANNEL_SACCH) AND | |
251 (frame_sapi EQ PS_SAPI_0) AND | |
252 (GET_FORMAT_TYPE(frame+l2_offset) EQ U_FORMAT) AND | |
253 (GET_U_TYPE(frame+l2_offset) EQ UI_FRAME) ) | |
254 { | |
255 drr_dl_unitdata_ind (error_flag, frame, frame+l2_offset+3, | |
256 (UBYTE)(GET_LENGTH_INDICATOR (frame+l2_offset)), fn); | |
257 return 0; | |
258 } | |
259 #endif /* DL_2TO1 || _SIMULATION_ */ | |
260 } | |
261 #if defined(DL_2TO1) | |
262 else if (channel_type EQ L2_CHANNEL_SACCH) | |
263 { /* | |
264 * Indicate invalid SACCH frame for decrement of radio link timeout counter. | |
265 * The invalid frame possible contains invalid headers, use length 0. | |
266 */ | |
267 drr_dl_unitdata_ind (error_flag, frame, frame+l2_offset+3, 0, fn); | |
268 } | |
269 #endif /* DL_2TO1 */ | |
270 | |
271 if (error_flag NEQ VALID_BLOCK) | |
272 { | |
273 TRACE_EVENT_WIN ("invalid frame->stop download handling"); | |
274 return 0; /* no further handling */ | |
275 } | |
276 | |
277 memset (&cch_i, 0, sizeof (T_CCH_INTERN)); | |
278 switch (channel_type) | |
279 { | |
280 case L2_CHANNEL_SDCCH: | |
281 if (frame_sapi EQ PS_SAPI_3) | |
282 { | |
283 channel = C_DCCH3; | |
284 break; | |
285 } | |
286 /*lint -fallthrough*/ | |
287 case L2_CHANNEL_FACCH_F: | |
288 case L2_CHANNEL_FACCH_H: | |
289 if (frame_sapi EQ PS_SAPI_0) | |
290 channel = C_DCCH0; | |
291 break; | |
292 case L2_CHANNEL_SACCH: | |
293 if (frame_sapi EQ PS_SAPI_3) | |
294 { /* SACCH with SAPI=3 only supported with associated TCH (FACCH) */ | |
295 if ((dl_data->cch[C_DCCH0].ch_type EQ L2_CHANNEL_FACCH_H) OR | |
296 (dl_data->cch[C_DCCH0].ch_type EQ L2_CHANNEL_FACCH_F)) | |
297 channel = C_DCCH3; | |
298 } | |
299 else | |
300 { | |
301 TRACE_EVENT_WIN ("No handling of SACCH with SAPI=0 here!"); | |
302 /* | |
303 * The SACCH with SAPI=0 is handled some lines before for DL_2TO1 and | |
304 * simulation. Handling of frames other than UI frames is not supported. | |
305 */ | |
306 } | |
307 break; | |
308 default: | |
309 break; | |
310 }/* endswitch channel_type */ | |
311 | |
312 if (channel EQ NOT_PRESENT_8BIT) | |
313 { | |
314 TRACE_EVENT_WIN ("downlink() returns -3"); | |
315 return -3; | |
316 } | |
317 else | |
318 { | |
319 | |
320 #if defined(DELAYED_SABM) | |
321 /* ignore downlinked frames before delayed SABM was sent */ | |
322 if ((channel EQ C_DCCH0) AND | |
323 (dl_data->dcch0_sabm_flag NEQ NOT_PRESENT_8BIT)) | |
324 { | |
325 DL_OFFLINE_TRACE (TRACE_DL_EVENT, channel, channel_type, "DL:pend.SABM->ignore"); | |
326 return 0; | |
327 } | |
328 #endif /* DELAYED_SABM */ | |
329 | |
330 cch_i.channel = channel; | |
331 cch_i.sapi = frame_sapi; | |
332 #if defined(_SIMULATION_) | |
333 if (channel_type EQ L2_CHANNEL_SACCH) | |
334 { | |
335 TRACE_EVENT_WIN_P1 ("SACCH: set SAPI=%u set during downlink", frame_sapi); | |
336 } | |
337 #endif /* _SIMULATION_ */ | |
338 | |
339 cch_i.state = channel_state = dl_data->state[channel]; | |
340 cch_i.pcch = &dl_data->cch[channel]; | |
341 /* | |
342 * The channel type pcch->ch_type is overwritten as input to the downlink | |
343 * sub functions. In case of DCCH0 this is temporary only and the channel | |
344 * type have to be re-assigned with the value of dl_data->dcch0_ch_type. | |
345 */ | |
346 cch_i.pcch->ch_type = channel_type; | |
347 if (cch_i.pcch->vtx NEQ EMPTY_CMD) | |
348 { /* save bit for the case of unsolicited frames */ | |
349 cch_i.pf_bit_flag = cch_i.pcch->f_bit; | |
350 } | |
351 TRACE_EVENT_WIN_P4 ("downlink() in:%s SAPI=%u st=%u vtx=%s", | |
352 CH_TYPE_NAME[channel_type], frame_sapi, channel_state, | |
353 VTX_NAME[cch_i.pcch->vtx]); | |
354 TRACE_EVENT_WIN_P9 ("vr=%u vs=%u va=%u rc=%u contres=%u reje=%u ackp=%u %c=%u", | |
355 cch_i.pcch->vr, cch_i.pcch->vs, cch_i.pcch->va, cch_i.pcch->rc, | |
356 cch_i.pcch->contention_resolution, cch_i.pcch->reject_exception, | |
357 cch_i.pcch->acknowledge_pending, | |
358 cch_i.pcch->time_flag ? 'T' : 't', cch_i.pcch->T200_counter); | |
359 } | |
360 | |
361 switch (channel_state) | |
362 { | |
363 case STATE_DISABLED: | |
364 case STATE_IDLE_DL: | |
365 ret = downlink_idle (&cch_i, frame+l2_offset); | |
366 break; | |
367 case STATE_CONTENTION_RESOLUTION: | |
368 ret = downlink_contention_resolution (&cch_i, frame+l2_offset); | |
369 break; | |
370 case STATE_MULTIPLE_FRAME_ESTABLISHED: | |
371 ret = downlink_mfe (&cch_i, frame+l2_offset); | |
372 break; | |
373 case STATE_TIMER_RECOVERY: | |
374 ret = downlink_timer_recovery (&cch_i, frame+l2_offset); | |
375 break; | |
376 case STATE_AWAITING_RELEASE: | |
377 ret = downlink_awaiting_release (&cch_i, frame+l2_offset); | |
378 break; | |
379 }/* endswitch channel_state */ | |
380 if (channel EQ C_DCCH0) | |
381 { /* | |
382 * Reconstruct the temporary overwritten pcch->ch_type with the value | |
383 * of dl_data->dcch0_ch_type. | |
384 */ | |
385 cch_i.pcch->ch_type = dl_data->dcch0_ch_type; | |
386 } | |
387 | |
388 | |
389 TRACE_EVENT_WIN_P5 ("%s SAPI=%u vtx=%s (%s#%u)", CH_TYPE_NAME[cch_i.pcch->ch_type], cch_i.sapi, | |
390 VTX_NAME[cch_i.pcch->vtx], | |
391 __FILE10__, __LINE__); | |
392 if (ret NEQ 0) | |
393 { | |
394 TRACE_EVENT_WIN_P1 ("downlink() returns %d", ret); | |
395 return ret; | |
396 } | |
397 | |
398 /* transfer states and flags to dl_data */ | |
399 dl_data->cch[channel].f_bit_flag = dl_data->cch[channel].f_bit = cch_i.pf_bit_flag; | |
400 if (cch_i.T200_Start) | |
401 { | |
402 dl_data->cch[channel].T200_counter = T200_STOPPED; | |
403 dl_data->cch[channel].time_flag = TRUE; | |
404 } | |
405 else if (cch_i.T200_Stop) | |
406 { | |
407 dl_data->cch[channel].T200_counter = T200_STOPPED; | |
408 dl_data->cch[channel].time_flag = FALSE; | |
409 } | |
410 | |
411 if (cch_i.dl_data_ind) | |
412 { | |
413 com_data_ind(channel_type, frame_sapi, fn); | |
414 } | |
415 | |
416 if (channel_state NEQ cch_i.state) | |
417 { | |
418 set_channel_state ( | |
419 (UBYTE)((frame_sapi EQ PS_SAPI_0) ? C_DCCH0 : C_DCCH3), cch_i.state); | |
420 } | |
421 | |
422 if (cch_i.mdl_error_ind) | |
423 { | |
424 mdl_error_ind ( cch_i.mdl_error_ind, channel_type, frame_sapi); | |
425 } | |
426 | |
427 | |
428 | |
429 TRACE_EVENT_WIN_P4 ("downlink() out:%s SAPI=%u st=%u vtx=%s", | |
430 CH_TYPE_NAME[channel_type], cch_i.sapi, cch_i.state, | |
431 VTX_NAME[cch_i.pcch->vtx]); | |
432 TRACE_EVENT_WIN_P9 ("vr=%u vs=%u va=%u rc=%u contres=%u reje=%u ackp=%u %c=%u", | |
433 cch_i.pcch->vr, cch_i.pcch->vs, cch_i.pcch->va, cch_i.pcch->rc, | |
434 cch_i.pcch->contention_resolution, cch_i.pcch->reject_exception, | |
435 cch_i.pcch->acknowledge_pending, | |
436 cch_i.pcch->time_flag ? 'T' : 't', cch_i.pcch->T200_counter); | |
437 TRACE_EVENT_WIN_P4 ("T200=%s %s %s %s", | |
438 cch_i.T200_Start ? "Start" : cch_i.T200_Stop ? "Stop" : "...", | |
439 cch_i.pf_bit_flag ? "P/F" : "", | |
440 cch_i.dl_data_ind ? "DATA_IND" : "", cch_i.mdl_error_ind ? "ERROR_IND" : ""); | |
441 TRACE_EVENT_WIN_P1 ("downlink() returns %d", ret); | |
442 | |
443 return ret; | |
444 }/* endfunc downlink */ | |
445 | |
446 LOCAL int frame_validation (UBYTE channel_type, UBYTE* frame) | |
447 { | |
448 UBYTE frame_length; | |
449 BOOL frame_m_bit; | |
450 UBYTE N201; | |
451 | |
452 if (!GET_EA (frame)) | |
453 return FRAME_NOT_IMPLEMENTED; /* ETSI GSM 04.06 Annex G.2.3 */ | |
454 | |
455 if (!GET_EL (frame)) | |
456 return FRAME_NOT_IMPLEMENTED; /* ETSI GSM 04.06 Annex G.4.1 */ | |
457 | |
458 frame_length = GET_LENGTH_INDICATOR (frame); | |
459 frame_m_bit = GET_M_BIT (frame); | |
460 | |
461 /* get the maximal number of octets */ | |
462 switch (channel_type) | |
463 { | |
464 case L2_CHANNEL_SDCCH: | |
465 N201 = N201_SDCCH; | |
466 break; | |
467 case L2_CHANNEL_SACCH: | |
468 N201 = N201_SACCH; | |
469 break; | |
470 default:/* CH_TYPE_FACCH_FR, L2_CHANNEL_FACCH_H */ | |
471 N201 = N201_FACCH; | |
472 break; | |
473 } | |
474 | |
475 switch (GET_FORMAT_TYPE (frame)) | |
476 { | |
477 case I_FORMAT: /* I format */ | |
478 case I1_FORMAT: | |
479 if ((frame_length > N201) OR (frame_length EQ 0)) | |
480 return I_FRAME_WITH_INCORRECT_LENGTH; /* ETSI GSM 04.06 Annex G.4.2 */ | |
481 if ((frame_length < N201) AND (frame_m_bit EQ 1)) | |
482 return I_FRAME_WITH_INCORRECT_USE_OF_M_BIT; /* ETSI GSM 04.06 Annex G.4.2 */ | |
483 break; | |
484 case S_FORMAT: /* S format */ | |
485 if (frame_length OR frame_m_bit) | |
486 return S_FRAME_WITH_INCORRECT_PARAMETERS; /* ETSI GSM 04.06 Annex G.4.3 */ | |
487 if ((frame[1] & 0x0f) EQ 0x0d) | |
488 return FRAME_NOT_IMPLEMENTED; /* ETSI GSM 04.06 Annex G.3.1 */ | |
489 break; | |
490 case U_FORMAT: /* U format */ | |
491 switch (GET_U_TYPE (frame)) | |
492 { | |
493 case DM_FRAME: | |
494 case DISC_FRAME: | |
495 if (frame_length OR frame_m_bit) | |
496 return U_FRAME_WITH_INCORRECT_PARAMETERS; /* ETSI GSM 04.06 Annex G.4.4 */ | |
497 break; | |
498 case UA_FRAME: | |
499 case SABM_FRAME: | |
500 case UI_FRAME: | |
501 if ((frame_length > N201) OR (frame_m_bit)) | |
502 return U_FRAME_WITH_INCORRECT_PARAMETERS; /* ETSI GSM 04.06 Annex G.4.5 */ | |
503 break; | |
504 default: | |
505 return FRAME_NOT_IMPLEMENTED; /* ETSI GSM 04.06 Annex G.3.2 */ | |
506 /*break;*/ | |
507 }/* endswitch U frame_type */ | |
508 break; | |
509 }/* endswitch frame_format */ | |
510 | |
511 /* | |
512 * ETSI GSM 04.06 Annex G.2.1, G.2.2 will be check in the following functions | |
513 */ | |
514 | |
515 return -1; /* frame is valid */ | |
516 }/* endfunc frame_validation */ | |
517 | |
518 static int downlink_idle( T_CCH_INTERN* pcch_i, UBYTE *frame) | |
519 { | |
520 /* | |
521 * According to 3GPP TS 04.05, 5.4.5 Idle state: | |
522 * While in the idle state: | |
523 * - the receipt of a DISC command shall result in the transmission of a | |
524 * DM response with the F bit set to the value of the received P bit; | |
525 * - the receipt of an I frame or supervisory frame with the P bit set to "1" | |
526 * shall result in the transmission of a DM response with the F bit set to | |
527 * "1" (as defined in subclause 5.2.2); | |
528 * - the content of any received I frame shall be discarded; | |
529 * - on receipt of an SABM command, the procedures defined in subclause 5.4.1 | |
530 * shall be followed; | |
531 * - on receipt of UI commands, the procedures defined in subclause 5.3 shall | |
532 * be followed; | |
533 * - all other frame types shall be discarded. | |
534 */ | |
535 T_CCH* pcch; | |
536 | |
537 CHECK_PCCH_Ir(); | |
538 pcch = pcch_i->pcch; | |
539 | |
540 TRACE_FUNCTION ("downlink_idle()"); | |
541 | |
542 switch (GET_FORMAT_TYPE (frame)) | |
543 { | |
544 case S_FORMAT: /* S frame */ | |
545 if (GET_S_TYPE (frame) NEQ RR_CMD) | |
546 break; | |
547 /*lint -fallthrough*/ | |
548 case I_FORMAT: /* I frame */ | |
549 case I1_FORMAT: | |
550 if (GET_P_BIT (frame)) | |
551 { | |
552 pcch->vtx = DM_CMD; | |
553 pcch_i->pf_bit_flag = TRUE; | |
554 } | |
555 break; | |
556 case U_FORMAT: /* U frame */ | |
557 if (GET_CR (frame)) | |
558 { /* command */ | |
559 switch (GET_U_TYPE (frame)) | |
560 { | |
561 case SABM_FRAME: | |
562 if (!GET_LENGTH_INDICATOR (frame) AND pcch_i->sapi EQ PS_SAPI_3) | |
563 { /* | |
564 * Mobile Terminated Establishment, but only for SAPI=3! | |
565 * | |
566 * According to 3GPP TS 04.06, 5.4.1 Establishment of multiple frame | |
567 * operation, 5.4.1.1 General, Note: | |
568 * For SAPI 0 the data link is always established by the MS. | |
569 */ | |
570 com_restore_queue ( pcch_i->sapi, NULL); | |
571 pcch->vtx = UA_CMD; | |
572 pcch_i->pf_bit_flag = GET_P_BIT (frame); | |
573 pcch->va = 0; | |
574 pcch->vr = 0; | |
575 pcch->vs = 0; | |
576 pcch->rc = 0; | |
577 } | |
578 break; | |
579 case DISC_FRAME: | |
580 pcch->vtx = DM_CMD; | |
581 pcch_i->pf_bit_flag = GET_P_BIT (frame); | |
582 break; | |
583 case UI_FRAME: | |
584 /* drr_dl_unitdata_ind() was called in the main downlink function */ | |
585 break; | |
586 default: | |
587 break; | |
588 } | |
589 } | |
590 break; | |
591 default: | |
592 break; | |
593 } | |
594 | |
595 return 0; | |
596 }/* endfunc downlink_idle */ | |
597 | |
598 static int downlink_contention_resolution(T_CCH_INTERN* pcch_i, UBYTE *frame) | |
599 { | |
600 GET_INSTANCE_DATA; | |
601 UBYTE frame_type; | |
602 UBYTE frame_format; | |
603 UBYTE frame_cr; | |
604 | |
605 UBYTE establish_cnf = FALSE; | |
606 UBYTE release_ind = FALSE; | |
607 UBYTE release_ind_cs = NOT_PRESENT_8BIT; | |
608 | |
609 T_CCH* pcch; | |
610 | |
611 CHECK_PCCH_Ir(); | |
612 pcch = pcch_i->pcch; | |
613 | |
614 TRACE_FUNCTION ("downlink_contention_resolution()"); | |
615 | |
616 frame_format = GET_FORMAT_TYPE (frame); | |
617 if (frame_format EQ U_FORMAT) | |
618 { /* U frame */ | |
619 frame_cr = GET_CR (frame); | |
620 frame_type = GET_U_TYPE (frame); | |
621 if (frame_cr) | |
622 { /* command */ | |
623 switch (frame_type) | |
624 { | |
625 case SABM_FRAME: | |
626 if (pcch_i->sapi EQ PS_SAPI_3) | |
627 { /* DCCH3 */ | |
628 /* | |
629 * According to 3GPP TS 04.06, 5.4.6.1: | |
630 * SAPI = 3, Collision of unnumbered commands and responses. | |
631 * Collision situations (Identical transmitted and received commands) | |
632 * shall be resolved in the following way: If the transmitted and | |
633 * received unnumbered commands (SABM or DISC) are the same, the data | |
634 * link layer entities shall send the UA response at the earliest | |
635 * possible opportunity. The indicated state shall be entered after | |
636 * receiving the UA response. The data link layer entities shall each | |
637 * notify its respective layer 3 entity by means of the appropriate | |
638 * confirm primitive, i.e. DL-ESTABLISH-CONFIRM or DL-RELEASE-CONFIRM. | |
639 */ | |
640 if (!GET_LENGTH_INDICATOR (frame)) | |
641 { | |
642 com_clear_queue (PS_SAPI_3); | |
643 /* establish_cnf = TRUE; cnf will be sent at uplink opportunity */ | |
644 | |
645 pcch_i->pf_bit_flag = GET_P_BIT (frame); | |
646 pcch->vtx = UA_CMD; | |
647 pcch->va = 0; | |
648 pcch->vr = 0; | |
649 pcch->vs = 0; | |
650 pcch->rc = 0; | |
651 pcch_i->T200_Stop = TRUE; | |
652 } | |
653 else | |
654 { | |
655 /* no contention resolution procedure with SAPI=3! */ | |
656 } | |
657 } | |
658 else | |
659 {/* DCCH0 */ | |
660 /* | |
661 * According to 3GPP TS 04.06, 5.4.1.1 General: | |
662 * NOTE: SAPI=0 the data link is always established by the MS! | |
663 * | |
664 * According to 3GPP TS 04.06, 5.4.1.4 Contention resolution | |
665 * establishment procedure: | |
666 * All frames other than unnumbered frame formats received for the | |
667 * SAPI in use during the establishment procedures shall be ignored. | |
668 * The reception of unnumbered frames other than UA is treated as | |
669 * specified for the normal establishment case. | |
670 * NOTE 4: In fact, there are no foreseen cases in which the network | |
671 * will send SABM, DISC or DM, but for sake of completeness | |
672 * these occurrences are specified and must be treated. | |
673 */ | |
674 establish_cnf = TRUE;/* Treated as normal establishment case */ | |
675 pcch_i->pf_bit_flag = GET_P_BIT (frame); | |
676 pcch->vtx = UA_CMD; | |
677 pcch->va = 0; | |
678 pcch->vr = 0; | |
679 pcch->vs = 0; | |
680 pcch->rc = 0; | |
681 pcch_i->T200_Stop = TRUE; | |
682 } | |
683 break; | |
684 | |
685 case DISC_FRAME: | |
686 { | |
687 release_ind = TRUE; | |
688 | |
689 pcch_i->pf_bit_flag = GET_P_BIT (frame); | |
690 pcch->vtx = DM_CMD; | |
691 } | |
692 break; | |
693 | |
694 default: | |
695 break; | |
696 }/* endswitch command frame_type */ | |
697 } | |
698 else | |
699 { /* response */ | |
700 switch (frame_type) | |
701 { | |
702 case DM_FRAME: | |
703 /* | |
704 * PATCH LE 14.09.99 | |
705 * Ignore DM(F=0) frames | |
706 */ | |
707 if (GET_P_BIT (frame)) | |
708 { | |
709 release_ind = TRUE; | |
710 } | |
711 break; | |
712 | |
713 case UA_FRAME: | |
714 if (pcch_i->sapi EQ PS_SAPI_0) | |
715 { | |
716 if (pcch->contention_resolution) | |
717 { | |
718 if (com_compare_L3_msg (dl_data->dcch0_queue.switch_buffer, frame)) | |
719 { | |
720 establish_cnf = TRUE; | |
721 COM_FREE_QUEUE_BUFFER(&dl_data->dcch0_queue, INDEX_SWITCH_BUFFER); | |
722 } | |
723 else | |
724 { | |
725 release_ind = TRUE; | |
726 release_ind_cs = CAUSE_DL_INFO_FIELD_MISMATCH; | |
727 } | |
728 } | |
729 else | |
730 { | |
731 if (!GET_LENGTH_INDICATOR (frame)) | |
732 { | |
733 establish_cnf = TRUE; | |
734 } | |
735 else | |
736 { | |
737 release_ind = TRUE; | |
738 } | |
739 } | |
740 }/* endif PS_SAPI_0 */ | |
741 else if (pcch_i->sapi EQ PS_SAPI_3) | |
742 { | |
743 if (!GET_LENGTH_INDICATOR (frame) OR (pcch->ch_type EQ L2_CHANNEL_SACCH)) | |
744 { | |
745 establish_cnf = TRUE; | |
746 } | |
747 else | |
748 { | |
749 release_ind = TRUE; | |
750 } | |
751 | |
752 }/* endif PS_SAPI_3 */ | |
753 | |
754 if (establish_cnf AND (pcch_i->sapi EQ PS_SAPI_0)) | |
755 { | |
756 dcch3_enable(pcch->ch_type); | |
757 } | |
758 | |
759 break;/* endbreak UA_FRAME */ | |
760 | |
761 default: | |
762 break; | |
763 }/* endswitch response frame_type */ | |
764 }/* endifelse command/response */ | |
765 | |
766 if (establish_cnf) | |
767 { | |
768 drr_dl_establish_cnf (pcch->ch_type, pcch_i->sapi); | |
769 pcch->va = 0; | |
770 pcch->vr = 0; | |
771 pcch->vs = 0; | |
772 pcch_i->T200_Stop = TRUE; | |
773 pcch_i->state = STATE_MULTIPLE_FRAME_ESTABLISHED; | |
774 } | |
775 else if (release_ind) | |
776 { | |
777 if (pcch_i->sapi EQ PS_SAPI_0) | |
778 { | |
779 if (pcch->contention_resolution) | |
780 { | |
781 pcch->contention_resolution = FALSE; | |
782 COM_FREE_QUEUE_BUFFER(&dl_data->dcch0_queue, INDEX_SWITCH_BUFFER); | |
783 } | |
784 } | |
785 | |
786 drr_dl_release_ind (pcch->ch_type, pcch_i->sapi, release_ind_cs, FALSE); | |
787 pcch_i->T200_Stop = TRUE; | |
788 pcch_i->state = STATE_IDLE_DL; | |
789 } | |
790 | |
791 }/* endif frame_format == 3 (only unnumbered frames) */ | |
792 | |
793 return 0; | |
794 }/* endfunc downlink_contention_resolution */ | |
795 | |
796 static int downlink_mfe(T_CCH_INTERN* pcch_i, UBYTE *frame) | |
797 { | |
798 TRACE_EVENT_WIN ("downlink_mfe()"); | |
799 | |
800 switch (GET_FORMAT_TYPE (frame)) | |
801 { | |
802 case I_FORMAT:/* I frame */ | |
803 case I1_FORMAT: | |
804 downlink_mfe_information (pcch_i, frame); | |
805 break; | |
806 case S_FORMAT: /* S frame */ | |
807 downlink_mfe_supervisory (pcch_i, frame); | |
808 break; | |
809 case U_FORMAT: /* U frame */ | |
810 downlink_mfe_tr_unnumbered (pcch_i, frame, | |
811 STATE_MULTIPLE_FRAME_ESTABLISHED); | |
812 break; | |
813 default: | |
814 TRACE_EVENT_WIN ("invalid/unknown frame"); | |
815 break; | |
816 } | |
817 | |
818 return 0; | |
819 }/* endfunc downlink_mfe */ | |
820 | |
821 static void downlink_mfe_supervisory (T_CCH_INTERN* pcch_i, UBYTE *frame) | |
822 { | |
823 UBYTE frame_cr; | |
824 UBYTE frame_pollbit; | |
825 UBYTE frame_nr; | |
826 UBYTE frame_type; | |
827 T_CCH* pcch; | |
828 | |
829 CHECK_PCCH_I(); | |
830 pcch = pcch_i->pcch; | |
831 | |
832 TRACE_EVENT_WIN ("downlink_mfe_supervisory()"); | |
833 | |
834 frame_type = GET_S_TYPE (frame); | |
835 | |
836 /* | |
837 * Ignore RNR frame without notification | |
838 * (ETSI GSM 04.06, section 6. | |
839 * "Special protocol operation on SAPI=0 and SAPI=3", page 53) | |
840 */ | |
841 if (frame_type EQ RNR_FRAME) | |
842 return; | |
843 | |
844 frame_cr = GET_CR (frame); | |
845 frame_pollbit = GET_P_BIT (frame); | |
846 frame_nr = GET_RECEIVE_NUMBER (frame); | |
847 | |
848 /* in accordance with CCITT Q.921 figure B.7 (sheet 5 to 7 of 10) */ | |
849 if (frame_pollbit) | |
850 { | |
851 if (frame_cr) | |
852 { | |
853 enquiry_response (pcch_i, frame); | |
854 } | |
855 else | |
856 { | |
857 mdl_error_ind (UNSOLICITED_SUPERVISORY_RESPONSE, pcch->ch_type, pcch_i->sapi);/* 3GPP TS 04.06, 5.4.2.2 */ | |
858 } | |
859 } | |
860 | |
861 if (com_check_nr (pcch->va, pcch->vs, frame_nr)) | |
862 { | |
863 /* | |
864 * N(R) check is successfull | |
865 * in accordance with CCITT Q.921 figure B.7 (sheet 6 and 7 of 10) | |
866 */ | |
867 | |
868 switch (frame_type) | |
869 { | |
870 case RR_FRAME: | |
871 if (frame_nr EQ pcch->vs) | |
872 { | |
873 /* T200 handling under ETSI GSM 04.06 section 5.5.3.1 */ | |
874 if (((8 + frame_nr - pcch->va ) & 7) > 0 /*frame_nr > pcch->va*/) | |
875 pcch_i->T200_Stop = TRUE; | |
876 | |
877 pcch->va = frame_nr; | |
878 | |
879 free_sending_buffer (pcch->ch_type, pcch_i->sapi); | |
880 } | |
881 else | |
882 { | |
883 if (frame_nr NEQ pcch->va) | |
884 { | |
885 pcch->va = frame_nr; | |
886 pcch_i->T200_Start = TRUE; | |
887 } | |
888 } | |
889 break; | |
890 case REJ_FRAME: | |
891 /* | |
892 * in accordance with ETSI GSM 04.06; chapter 5.5.4.1 i) | |
893 * | |
894 * clear existing peer receiver busy condition (not applicable in GSM) | |
895 */ | |
896 | |
897 /* reset timer T200 */ | |
898 pcch_i->T200_Stop = TRUE; | |
899 /* | |
900 * If REJ command with P bit set to 1, | |
901 * transmit an appropiate supervisory response frame with F bit set to 1 | |
902 */ | |
903 if (frame_pollbit AND frame_cr) | |
904 enquiry_response (pcch_i, frame); | |
905 /* transmit the corresponding I frame asap */ | |
906 invoke_retransmission (pcch_i, frame_nr); | |
907 | |
908 | |
909 /* | |
910 * set its send state variable V(S) and its acknowledge state | |
911 * variable V(A) to the value of the N(R) contained in the REJ frame | |
912 * control field | |
913 */ | |
914 pcch->vs = pcch->va = frame_nr; | |
915 | |
916 /* | |
917 * if it was an REJ response frame with the F bit set to 1, notify | |
918 * a protocol violation to layer 3 (cause=unsolicited supervisory frame) | |
919 * | |
920 * fulfilled at the beginning of this function! | |
921 */ | |
922 break; | |
923 case RNR_FRAME: | |
924 /* | |
925 * Ignore frame without notification | |
926 * (ETSI GSM 04.06, section 6. | |
927 * "Special protocol operation on SAPI=0 and SAPI=3", page 53) | |
928 */ | |
929 break; | |
930 default: | |
931 TRACE_EVENT_WIN ("invalid S frame"); /* GSM 04.06 Annex G.3.1 */ | |
932 mdl_error_ind (FRAME_NOT_IMPLEMENTED, pcch->ch_type, pcch_i->sapi); | |
933 break; | |
934 } | |
935 | |
936 } | |
937 else | |
938 { | |
939 nr_error_recovery (pcch_i, frame); | |
940 } | |
941 }/* endfunc downlink_mfe_supervisory */ | |
942 | |
943 | |
944 static void downlink_mfe_sabm (T_CCH_INTERN* pcch_i, UBYTE *frame) | |
945 { | |
946 TRACE_EVENT_WIN ("downlink_mfe_sabm()"); | |
947 | |
948 if (!GET_LENGTH_INDICATOR (frame)) | |
949 { | |
950 T_CCH* pcch; | |
951 | |
952 CHECK_PCCH_I(); | |
953 pcch = pcch_i->pcch; | |
954 | |
955 if (pcch_i->sapi EQ PS_SAPI_0) | |
956 { | |
957 /* SACCH0: only unacknowledge mode available -> ignore SABM */ | |
958 if (pcch->ch_type EQ L2_CHANNEL_SACCH) | |
959 return; | |
960 /* | |
961 * SDCCH0, FACCH: can not be a normal establishment procedure | |
962 * because for SAPI=0 the data link is always established by the MS. | |
963 * Therefore only the V state variables and any exception states | |
964 * will be reseted. | |
965 */ | |
966 } | |
967 else if (pcch_i->sapi EQ PS_SAPI_3) | |
968 { /* | |
969 * SDCCH3, SACCH: normal establishment procedure, | |
970 * might be a re-establishment according to GSM 04.06, 5.4.1.2 | |
971 */ | |
972 com_clear_queue (PS_SAPI_3); | |
973 } | |
974 | |
975 /* respond with an unnumbered acknowledgement */ | |
976 pcch->vtx = UA_CMD; | |
977 /* with the F bit set to the same value as the P bit */ | |
978 pcch_i->pf_bit_flag = GET_P_BIT (frame); | |
979 /* reset timer T200 */ | |
980 pcch_i->T200_Stop = TRUE; | |
981 /* reset all state variables (internal sequence counter) */ | |
982 pcch->va = 0; | |
983 pcch->vr = 0; | |
984 pcch->vs = 0; | |
985 /* reset the retransmission counter */ | |
986 pcch->rc = 0; | |
987 /* clear all exception conditions */ | |
988 pcch->reject_exception = FALSE; | |
989 pcch->acknowledge_pending = FALSE; | |
990 /* enter the multiple-frame-established state */ | |
991 pcch_i->state = STATE_MULTIPLE_FRAME_ESTABLISHED; | |
992 } | |
993 else | |
994 { | |
995 /* | |
996 * frame_length NEQ 0 is only possible in contention resolution establishment | |
997 * initiated by mobile! | |
998 */ | |
999 mdl_error_ind (U_FRAME_WITH_INCORRECT_PARAMETERS, pcch_i->pcch->ch_type, pcch_i->sapi);/* according to GSM 04.06, 5.4.2.1 */ | |
1000 } | |
1001 }/* endfunc mfe_sabm */ | |
1002 | |
1003 static void downlink_mfe_dm (T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1004 { | |
1005 T_CCH* pcch; | |
1006 | |
1007 CHECK_PCCH_I(); | |
1008 pcch = pcch_i->pcch; | |
1009 | |
1010 if (!GET_P_BIT (frame)) | |
1011 { /* release after unsolicited DM response during connection */ | |
1012 | |
1013 /* New! Called now by mdl_error_ind() from caller of this function | |
1014 * drr_dl_release_ind (dl_data, pcch->ch_type, pcch_i->sapi, NOT_PRESENT_8BIT); | |
1015 */ | |
1016 | |
1017 if ((pcch->ch_type EQ L2_CHANNEL_SDCCH) AND (pcch_i->sapi EQ PS_SAPI_3)) | |
1018 { | |
1019 pcch_i->T200_Stop = TRUE; | |
1020 com_clear_queue (PS_SAPI_3); | |
1021 } | |
1022 } | |
1023 }/* endfunc mfe_dm */ | |
1024 | |
1025 static void downlink_mfe_tr_unnumbered (T_CCH_INTERN* pcch_i, | |
1026 UBYTE *frame, UBYTE state) | |
1027 { | |
1028 UBYTE frame_type; | |
1029 T_CCH* pcch; | |
1030 | |
1031 TRACE_EVENT_WIN ("downlink_mfe_tr_unnumbered()"); | |
1032 | |
1033 CHECK_PCCH_I(); | |
1034 pcch = pcch_i->pcch; | |
1035 | |
1036 frame_type = GET_U_TYPE (frame); | |
1037 if (GET_CR (frame)) | |
1038 { /* command */ | |
1039 switch (frame_type) | |
1040 { | |
1041 case SABM_FRAME: | |
1042 downlink_mfe_sabm (pcch_i, frame); | |
1043 break; | |
1044 case UI_FRAME: | |
1045 /* drr_dl_unitdata_ind() was called in the main downlink function */ | |
1046 break; | |
1047 case DISC_FRAME: | |
1048 pcch->vtx = UA_CMD; | |
1049 pcch_i->T200_Stop = TRUE; | |
1050 pcch_i->state = STATE_AWAITING_RELEASE; | |
1051 #if !defined(LATE_LEAVING_DEDICATED) | |
1052 com_leave_dedicated (pcch->ch_type); | |
1053 #endif /* LATE_LEAVING_DEDICATED */ | |
1054 if (pcch_i->sapi EQ PS_SAPI_0) | |
1055 { | |
1056 dcch3_enable(pcch->ch_type); | |
1057 } | |
1058 break; | |
1059 default: | |
1060 /* GSM 04.06 Annex G.2.2, G.3.2 */ | |
1061 TRACE_EVENT_WIN_P1 ("invalid command U frame (%02x)", frame_type); | |
1062 break; | |
1063 } | |
1064 } | |
1065 else | |
1066 { /* response */ | |
1067 switch (frame_type) | |
1068 { | |
1069 case DM_FRAME: | |
1070 /* fulfill the actions required by 3GPP TS 4.06 section 5.4.2.2, table 7 */ | |
1071 if (!GET_P_BIT(frame)) | |
1072 { | |
1073 mdl_error_ind (UNSOLICITED_DM_RESPONSE_ABNORMAL_REL, pcch->ch_type, pcch_i->sapi); | |
1074 } | |
1075 else if (state EQ STATE_MULTIPLE_FRAME_ESTABLISHED) | |
1076 { | |
1077 mdl_error_ind (UNSOLICITED_DM_RESPONSE, pcch->ch_type, pcch_i->sapi); | |
1078 } | |
1079 | |
1080 downlink_mfe_dm (pcch_i, frame); | |
1081 break; | |
1082 case UA_FRAME: | |
1083 mdl_error_ind (UNSOLICITED_UA_RESPONSE, pcch->ch_type, pcch_i->sapi); | |
1084 break; | |
1085 default: | |
1086 /* GSM 04.06 Annex G.2.2, G.3.2 */ | |
1087 TRACE_EVENT_WIN_P1 ("invalid response U frame (%02x)", frame_type); | |
1088 break; | |
1089 } | |
1090 } | |
1091 }/* endfunc downlink_mfe_unnumbered */ | |
1092 | |
1093 static void downlink_i_frame (T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1094 { | |
1095 /* | |
1096 * in accordance with CCITT Q.921 figure B.7 (sheet 8 of 10) | |
1097 * in accordance with CCITT Q.921 figure B.8 (sheet 7 of 9) | |
1098 * according to GSM 04.06 (same as CCITT Q.921!) | |
1099 */ | |
1100 | |
1101 UBYTE frame_pollbit; | |
1102 T_CCH* pcch; | |
1103 | |
1104 CHECK_PCCH_I(); | |
1105 pcch = pcch_i->pcch; | |
1106 | |
1107 frame_pollbit = GET_P_BIT (frame); | |
1108 | |
1109 if (GET_SEND_NUMBER (frame) EQ pcch->vr) | |
1110 { | |
1111 pcch->vr++; | |
1112 pcch->vr &= 7; | |
1113 pcch->reject_exception = FALSE; | |
1114 concatenate (pcch->ch_type, pcch_i->sapi, frame); | |
1115 if (!GET_M_BIT (frame)) | |
1116 pcch_i->dl_data_ind = TRUE;/* send DL-DATA indication */ | |
1117 | |
1118 if (frame_pollbit) | |
1119 { | |
1120 pcch_i->pf_bit_flag = TRUE; | |
1121 pcch->vtx = RR_RSP; | |
1122 pcch->acknowledge_pending = FALSE; | |
1123 } | |
1124 else if (pcch->acknowledge_pending EQ FALSE) | |
1125 { | |
1126 #if defined(IFRAME_AS_RR) | |
1127 pcch->vtx = RR_CMD; | |
1128 #else | |
1129 pcch->vtx = RR_RSP; | |
1130 #endif /* IFRAME_AS_RR */ | |
1131 } | |
1132 }/* endif ns == vr */ | |
1133 else | |
1134 { | |
1135 if (pcch->reject_exception) | |
1136 { | |
1137 if (frame_pollbit) | |
1138 { | |
1139 pcch_i->pf_bit_flag = TRUE; | |
1140 /*pcch->vtx = RR_RSP; */ | |
1141 pcch->vtx = REJ_CMD; | |
1142 pcch->acknowledge_pending = FALSE; | |
1143 } | |
1144 } | |
1145 else | |
1146 { | |
1147 pcch->reject_exception = TRUE; | |
1148 pcch_i->pf_bit_flag = frame_pollbit; | |
1149 pcch->vtx = REJ_CMD; | |
1150 pcch->acknowledge_pending = FALSE; | |
1151 } | |
1152 if (pcch->vtx EQ REJ_CMD) | |
1153 { | |
1154 TRACE_EVENT_WIN_P1 ("->REJ_CMD pf=%u", pcch_i->pf_bit_flag); | |
1155 } | |
1156 }/* endelse ns != vr */ | |
1157 }/* endfunc downlink_i_frame */ | |
1158 | |
1159 static void downlink_mfe_information ( T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1160 { | |
1161 UBYTE frame_nr; | |
1162 T_CCH* pcch; | |
1163 | |
1164 CHECK_PCCH_I(); | |
1165 pcch = pcch_i->pcch; | |
1166 | |
1167 TRACE_EVENT_WIN ("downlink_mfe_information()"); | |
1168 | |
1169 if (!GET_CR (frame)) | |
1170 { /* GSM 04.06 Annex G.2.2 */ | |
1171 TRACE_EVENT_WIN ("invalid I response (C=0)"); | |
1172 return; | |
1173 } | |
1174 | |
1175 frame_nr = GET_RECEIVE_NUMBER (frame); | |
1176 | |
1177 /* in accordance with CCITT Q.921 figure B.7 (sheet 8 of 10) */ | |
1178 downlink_i_frame (pcch_i, frame); | |
1179 | |
1180 /* in accordance with CCITT Q.921 figure B.7 (sheet 9 of 10) */ | |
1181 if (com_check_nr (pcch->va, pcch->vs, frame_nr)) | |
1182 { /* N(R) check is successfull */ | |
1183 if (frame_nr EQ pcch->vs) | |
1184 { | |
1185 | |
1186 /* T200 handling under ETSI GSM 04.06 section 5.5.3.1 */ | |
1187 if (((8 + frame_nr - pcch->va ) & 7) > 0 /*frame_nr > pcch->va*/) | |
1188 pcch_i->T200_Stop = TRUE; | |
1189 | |
1190 pcch->va = frame_nr; | |
1191 free_sending_buffer (pcch->ch_type, pcch_i->sapi); | |
1192 } | |
1193 else if (frame_nr NEQ pcch->va) | |
1194 { | |
1195 pcch->va = frame_nr; | |
1196 pcch_i->T200_Start = TRUE; | |
1197 } | |
1198 } | |
1199 else | |
1200 { | |
1201 nr_error_recovery (pcch_i, frame); | |
1202 }/* endifelse com_check_nr */ | |
1203 }/* endfunc downlink_mfe_information */ | |
1204 | |
1205 static int downlink_timer_recovery(T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1206 { | |
1207 TRACE_EVENT_WIN ("downlink_timer_recovery()"); | |
1208 | |
1209 switch (GET_FORMAT_TYPE (frame)) | |
1210 { | |
1211 case I_FORMAT: | |
1212 case I1_FORMAT: /* I frame */ | |
1213 downlink_tr_information (pcch_i, frame); | |
1214 break; | |
1215 case S_FORMAT: /* S frame */ | |
1216 downlink_tr_supervisory (pcch_i, frame); | |
1217 break; | |
1218 case U_FORMAT: /* U frame */ | |
1219 downlink_mfe_tr_unnumbered (pcch_i, frame, STATE_TIMER_RECOVERY); | |
1220 break; | |
1221 default: | |
1222 TRACE_EVENT_WIN ("invalid/unknown frame"); | |
1223 break; | |
1224 } | |
1225 | |
1226 return 0; | |
1227 }/* endfunc downlink_tr */ | |
1228 | |
1229 static void downlink_tr_supervisory (T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1230 { | |
1231 UBYTE frame_cr; | |
1232 UBYTE frame_pollbit; | |
1233 UBYTE frame_nr; | |
1234 T_CCH* pcch; | |
1235 | |
1236 CHECK_PCCH_I(); | |
1237 pcch = pcch_i->pcch; | |
1238 | |
1239 TRACE_EVENT_WIN ("downlink_tr_supervisory()"); | |
1240 | |
1241 frame_cr = GET_CR (frame); | |
1242 frame_pollbit = GET_P_BIT (frame); | |
1243 frame_nr = GET_RECEIVE_NUMBER (frame); | |
1244 | |
1245 switch (GET_S_TYPE (frame)) | |
1246 { | |
1247 case RR_FRAME: | |
1248 /* | |
1249 * in accordance with CCITT Q.921 figure B.8 (sheet 5 and 6 of 9) and | |
1250 * 3GPP 04.06, 5.5.3.1 "On receipt of a valid I frame or supervisory frame" | |
1251 * and 5.5.7 "Waiting acknowledgement". | |
1252 */ | |
1253 if (frame_pollbit AND frame_cr) | |
1254 { | |
1255 enquiry_response (pcch_i, frame); | |
1256 } | |
1257 | |
1258 if (com_check_nr (pcch->va, pcch->vs, frame_nr)) | |
1259 { | |
1260 /* N(R) check is successfull */ | |
1261 | |
1262 TRACE_EVENT_WIN_P5 ("V(A)=%d =< N(R)=%d =< V(S)=%d check is successfull, pf=%u cr=%u", | |
1263 pcch->va, frame_nr, pcch->vs, frame_pollbit, frame_cr); | |
1264 | |
1265 pcch->va = frame_nr; | |
1266 | |
1267 if (frame_pollbit AND !frame_cr) | |
1268 { /* | |
1269 * 3GPP 04.06, 5.5.7: | |
1270 * The timer recovery state is only cleared if the DL receives a valid | |
1271 * supervisory frame response with the F bit set to 1. | |
1272 */ | |
1273 pcch_i->T200_Stop = TRUE; | |
1274 pcch_i->state = STATE_MULTIPLE_FRAME_ESTABLISHED; | |
1275 /* acknowledgement according to GSM 04.06, 5.5.3.1*/ | |
1276 free_sending_buffer (pcch->ch_type, pcch_i->sapi); | |
1277 } | |
1278 else | |
1279 { | |
1280 invoke_retransmission (pcch_i, frame_nr); | |
1281 } | |
1282 } | |
1283 else | |
1284 { | |
1285 nr_error_recovery (pcch_i, frame); | |
1286 }/* endifelse com_check_nr */ | |
1287 break; | |
1288 | |
1289 case REJ_FRAME: | |
1290 #if defined(NEW_REJ_ACK) | |
1291 /* | |
1292 * in accordance with | |
1293 * 3GPP 04.06, 5.5.3.1 "On receipt of a valid I frame or supervisory frame" | |
1294 */ | |
1295 if (com_check_nr (pcch->va, pcch->vs, frame_nr)) | |
1296 { | |
1297 /* N(R) check is successfull */ | |
1298 | |
1299 TRACE_EVENT_WIN_P5 ("V(A)=%d =< N(R)=%d =< V(S)=%d check is successfull, pf=%u cr=%u", | |
1300 pcch->va, frame_nr, pcch->vs, frame_pollbit, frame_cr); | |
1301 | |
1302 /* acknowledgement according to GSM 04.06, 5.5.3.1*/ | |
1303 free_sending_buffer (pcch->ch_type, pcch_i->sapi); | |
1304 | |
1305 pcch->va = frame_nr; | |
1306 } | |
1307 #endif /* NEW_REJ_ACK */ | |
1308 | |
1309 /* | |
1310 * in accordance with GSM 04.06; chapter 5.5.4.1 | |
1311 * Receipt of a valid REJ frame [ii) and iii)] | |
1312 * | |
1313 * clear existing peer receiver busy condition (not applicable in GSM) | |
1314 */ | |
1315 | |
1316 if (frame_pollbit AND !frame_cr) | |
1317 {/* REJ response with F bit set to 1 */ | |
1318 /* clear the timer recovery state */ | |
1319 pcch_i->state = STATE_MULTIPLE_FRAME_ESTABLISHED; | |
1320 | |
1321 /* reset timer T200 */ | |
1322 pcch_i->T200_Stop = TRUE; | |
1323 | |
1324 #if defined(NEW_REJ_ACK) | |
1325 /* transmit the corresponding I frame asap */ | |
1326 if (pcch->va NEQ frame_nr) | |
1327 { | |
1328 TRACE_EVENT_WIN_P2 ("REJ: V(A)=%d != N(R)=%d => invoke retransmission", | |
1329 pcch->va, frame_nr); | |
1330 | |
1331 invoke_retransmission (pcch_i, frame_nr); | |
1332 } | |
1333 #else /* NEW_REJ_ACK */ | |
1334 /* transmit the corresponding I frame asap */ | |
1335 invoke_retransmission (pcch_i, frame_nr); | |
1336 #endif /* NEW_REJ_ACK */ | |
1337 | |
1338 | |
1339 /* | |
1340 * set its send state variable V(S) and its acknowledge state | |
1341 * variable V(A) to the value of the N(R) contained in the REJ frame | |
1342 * control field | |
1343 */ | |
1344 pcch->vs = pcch->va = frame_nr; | |
1345 } | |
1346 else | |
1347 { | |
1348 /* | |
1349 * set its its acknowledge state variable V(A) to the value | |
1350 * of the N(R) contained in the REJ frame control field | |
1351 */ | |
1352 pcch->va = frame_nr; | |
1353 | |
1354 /* | |
1355 * if REJ command with P bit set to 1, | |
1356 * transmit an appropiate supervisory response frame with F bit set to 1 | |
1357 */ | |
1358 if (frame_pollbit AND frame_cr) | |
1359 { | |
1360 enquiry_response (pcch_i, frame); | |
1361 } | |
1362 } | |
1363 break; | |
1364 | |
1365 case RNR_FRAME: | |
1366 /* | |
1367 * ignore RNR frame without notification | |
1368 * (ETSI GSM 04.06, section 6. | |
1369 * "Special protocol operation on SAPI=0 and SAPI=3", page 53) | |
1370 */ | |
1371 default: | |
1372 /* frame not implemented, */ | |
1373 TRACE_EVENT_WIN ("invalid S frame"); /* GSM 04.06 Annex G.3.1 */ | |
1374 return; | |
1375 }/* endswitch frame_type */ | |
1376 | |
1377 | |
1378 }/* endfunc downlink_tr_supervisory */ | |
1379 | |
1380 static void downlink_tr_information ( T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1381 { | |
1382 T_CCH* pcch; | |
1383 UBYTE frame_nr; | |
1384 | |
1385 CHECK_PCCH_I(); | |
1386 pcch = pcch_i->pcch; | |
1387 | |
1388 TRACE_EVENT_WIN ("downlink_tr_information()"); | |
1389 | |
1390 if (!GET_CR (frame)) | |
1391 { /* GSM 04.06 Annex G.2.2 */ | |
1392 TRACE_EVENT_WIN ("invalid I response (C=0)"); | |
1393 return; | |
1394 } | |
1395 | |
1396 /* in accordance with CCITT Q.921 figure B.8 (sheet 7 of 9) */ | |
1397 downlink_i_frame (pcch_i, frame); | |
1398 | |
1399 /* | |
1400 * in accordance with CCITT Q.921 figure B.8 (sheet 8 of 9) and | |
1401 * 3GPP 04.06, 5.5.3.1 "On receipt of a valid I frame or supervisory frame" | |
1402 * and 5.5.7 "Waiting acknowledgement". | |
1403 */ | |
1404 frame_nr = GET_RECEIVE_NUMBER (frame); | |
1405 if (com_check_nr (pcch->va, pcch->vs, frame_nr)) | |
1406 pcch->va = frame_nr;/* N(R) check is successfull */ | |
1407 else | |
1408 nr_error_recovery (pcch_i, frame); | |
1409 }/* endfunc downlink_tr_information */ | |
1410 | |
1411 static int downlink_awaiting_release(T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1412 { | |
1413 T_CCH* pcch; | |
1414 | |
1415 CHECK_PCCH_Ir(); | |
1416 pcch = pcch_i->pcch; | |
1417 | |
1418 TRACE_FUNCTION ("downlink_awaiting_release()"); | |
1419 | |
1420 if (GET_FORMAT_TYPE (frame) EQ U_FORMAT) | |
1421 { /* U frame */ | |
1422 if (GET_CR (frame)) | |
1423 { /* command */ | |
1424 switch (GET_U_TYPE (frame)) | |
1425 { | |
1426 case SABM_FRAME: | |
1427 if (pcch_i->sapi EQ PS_SAPI_0) | |
1428 { | |
1429 pcch->vtx = DM_CMD; | |
1430 pcch_i->pf_bit_flag = GET_P_BIT (frame); | |
1431 pcch_i->T200_Stop = TRUE; | |
1432 pcch_i->state = STATE_IDLE_DL; | |
1433 drr_dl_release_cnf (pcch->ch_type, PS_SAPI_0, FALSE); | |
1434 } | |
1435 break; | |
1436 case UI_FRAME: | |
1437 /* drr_dl_unitdata_ind() was called in the main downlink function */ | |
1438 break; | |
1439 case DISC_FRAME: | |
1440 pcch->vtx = UA_CMD; | |
1441 pcch_i->T200_Stop = TRUE; | |
1442 #if !defined(LATE_LEAVING_DEDICATED) | |
1443 com_leave_dedicated (pcch->ch_type); | |
1444 #endif /* LATE_LEAVING_DEDICATED */ | |
1445 break; | |
1446 default: | |
1447 /* GSM 04.06 Annex G.2.2, G.3.2 */ | |
1448 TRACE_EVENT_WIN_P1 ("invalid command U frame (%02x)", GET_U_TYPE (frame)); | |
1449 break; | |
1450 } | |
1451 } | |
1452 else | |
1453 { /* response */ | |
1454 switch (GET_U_TYPE (frame)) | |
1455 { | |
1456 case DM_FRAME: | |
1457 /* | |
1458 * PATCH LE 14.09.99 | |
1459 * Ignore DM(F=0) frames | |
1460 */ | |
1461 if (!GET_P_BIT (frame)) | |
1462 break; | |
1463 | |
1464 /* the same as UA_FRAME */ | |
1465 /*lint -fallthrough*/ | |
1466 | |
1467 case UA_FRAME: | |
1468 pcch_i->T200_Stop = TRUE; | |
1469 #if defined(LATE_LEAVING_DEDICATED) | |
1470 com_leave_dedicated (pcch->ch_type); | |
1471 #endif /* LATE_LEAVING_DEDICATED */ | |
1472 pcch_i->state = STATE_IDLE_DL; | |
1473 drr_dl_release_cnf (pcch->ch_type, pcch_i->sapi, TRUE); | |
1474 break; | |
1475 | |
1476 default: | |
1477 TRACE_EVENT_WIN_P1 ("invalid response U frame (%02x)", GET_U_TYPE (frame)); | |
1478 break; | |
1479 } | |
1480 } | |
1481 } | |
1482 return 0; | |
1483 }/* endfunc downlink_awaiting_release */ | |
1484 | |
1485 static void invoke_retransmission (T_CCH_INTERN* pcch_i, UBYTE frame_nr) | |
1486 { | |
1487 T_CCH* pcch; | |
1488 | |
1489 CHECK_PCCH_I(); | |
1490 pcch = pcch_i->pcch; | |
1491 | |
1492 if (pcch->vs NEQ frame_nr) | |
1493 { /* decrement V(S) and recover queue for retransmission */ | |
1494 TRACE_EVENT_WIN ("invoke retransmission"); | |
1495 | |
1496 pcch->vs--; | |
1497 pcch->vs &= 7; | |
1498 com_recover_queue (pcch_i->sapi); | |
1499 } | |
1500 }/* endfunc invoke_retransmission */ | |
1501 | |
1502 | |
1503 static void enquiry_response (T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1504 { | |
1505 T_CCH* pcch; | |
1506 | |
1507 CHECK_PCCH_I(); | |
1508 pcch = pcch_i->pcch; | |
1509 | |
1510 TRACE_EVENT_WIN ("enquiry_response()"); | |
1511 /* | |
1512 * in accordance with ETSI GSM 04.06, 5.5.3.2 Receiving supervisory | |
1513 * commands with the P bit set to "1" and ETSI GSM 04.06, 5.5.4.1 iii | |
1514 */ | |
1515 | |
1516 pcch_i->pf_bit_flag = TRUE; | |
1517 pcch->acknowledge_pending = FALSE; | |
1518 pcch->vtx = RR_RSP; | |
1519 }/* endfunc enquiry_response */ | |
1520 | |
1521 #if defined(_SIMULATION_) | |
1522 LOCAL const char * const _str_error_ind_cause[] = | |
1523 { | |
1524 "T200_EXPIRED_N200_PLUS_1_TIMES, \"T200 expired (N200 + 1 times)\"", | |
1525 "CS_REEST_REQ, \"re-establishment request\"", | |
1526 "UNSOLICITED_UA_RESPONSE, \"unsolicited UA response\"", | |
1527 "UNSOLICITED_DM_RESPONSE, \"unsolicited DM response\"", | |
1528 "UNSOLICITED_DM_RESPONSE_ABNORMAL_REL, \"unsolicited DM response, multiple frame established state\"", | |
1529 "UNSOLICITED_SUPERVISORY_RESPONSE, \"unsolicited supervisory response\"", | |
1530 "SEQUENCE_ERROR, \"sequence error\"", | |
1531 "U_FRAME_WITH_INCORRECT_PARAMETERS, \"U frame with incorrect parameters\"", | |
1532 "S_FRAME_WITH_INCORRECT_PARAMETERS, \"S frame with incorrect parameters\"", | |
1533 "I_FRAME_WITH_INCORRECT_USE_OF_M_BIT, \"I frame with incorrect use of M bit\"", | |
1534 "I_FRAME_WITH_INCORRECT_LENGTH, \"I frame with incorrect length\"", | |
1535 "FRAME_NOT_IMPLEMENTED, \"frame not implemented\"", | |
1536 }; | |
1537 #endif /* _SIMULATION_ */ | |
1538 | |
1539 static void mdl_error_ind (UBYTE cause, | |
1540 UBYTE channel_type, UBYTE sapi) | |
1541 { | |
1542 TRACE_EVENT_WIN_P2 ("mdl_error_ind(%u %s)", cause, _str_error_ind_cause[cause]); | |
1543 switch(cause) | |
1544 { | |
1545 case T200_EXPIRED_N200_PLUS_1_TIMES: | |
1546 case UNSOLICITED_DM_RESPONSE: | |
1547 case UNSOLICITED_DM_RESPONSE_ABNORMAL_REL: | |
1548 case SEQUENCE_ERROR: | |
1549 drr_error_ind (channel_type, sapi); | |
1550 break; | |
1551 default: | |
1552 break; | |
1553 } | |
1554 }/* endfunc mdl_error_ind */ | |
1555 | |
1556 static void nr_error_recovery (T_CCH_INTERN* pcch_i, UBYTE *frame) | |
1557 { | |
1558 | |
1559 T_CCH* pcch; | |
1560 | |
1561 CHECK_PCCH_I(); | |
1562 pcch = pcch_i->pcch; | |
1563 | |
1564 TRACE_EVENT_WIN ("nr_error_recovery()"); | |
1565 DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, pcch->ch_type, "N(R) sequence error"); | |
1566 | |
1567 switch (pcch->ch_type) | |
1568 { | |
1569 case L2_CHANNEL_SDCCH: | |
1570 if (pcch_i->sapi EQ PS_SAPI_3) | |
1571 break; | |
1572 /*lint -fallthrough*/ | |
1573 case L2_CHANNEL_SACCH: | |
1574 case L2_CHANNEL_FACCH_F: | |
1575 case L2_CHANNEL_FACCH_H: | |
1576 if ((GET_P_BIT (frame) EQ 1) AND !GET_M_BIT (frame)) | |
1577 pcch_i->dl_data_ind = TRUE; /* indicate a complete message to layer 3 */ | |
1578 else | |
1579 pcch_i->dl_data_ind = FALSE;/* no indication if P bit set to "0" or message is incomplete */ | |
1580 | |
1581 /* | |
1582 * GSM 04.06, 5.7.4 The data link shall remain in current state | |
1583 * until it´s release by layer 3 ??? | |
1584 */ | |
1585 pcch_i->mdl_error_ind = SEQUENCE_ERROR; /* send mdl error ind after sequence error */ | |
1586 | |
1587 DL_EM_CHANNEL_FAILURE; | |
1588 | |
1589 break; | |
1590 } | |
1591 pcch->vtx = EMPTY_CMD;/* no answer after N(R) sequence error */ | |
1592 }/* endfunc nr_error_recovery */ | |
1593 | |
1594 | |
1595 static void concatenate (UBYTE ch_type, UBYTE sapi,UBYTE *frame) | |
1596 { | |
1597 GET_INSTANCE_DATA; | |
1598 switch (ch_type) | |
1599 { | |
1600 case L2_CHANNEL_SDCCH: | |
1601 if (sapi EQ PS_SAPI_0) | |
1602 com_concatenate (&dl_data->dcch0_in_msg, frame); | |
1603 else if (sapi EQ PS_SAPI_3) | |
1604 com_concatenate (&dl_data->dcch3_in_msg, frame); | |
1605 break; | |
1606 case L2_CHANNEL_SACCH: | |
1607 if (sapi EQ PS_SAPI_3) | |
1608 { | |
1609 com_concatenate (&dl_data->dcch3_in_msg, frame); | |
1610 } | |
1611 break; | |
1612 case L2_CHANNEL_FACCH_F: | |
1613 case L2_CHANNEL_FACCH_H: | |
1614 if (sapi EQ PS_SAPI_0) | |
1615 { | |
1616 com_concatenate (&dl_data->dcch0_in_msg, frame); | |
1617 } | |
1618 break; | |
1619 default: | |
1620 break; | |
1621 } | |
1622 }/* endfunc concatenate */ | |
1623 | |
1624 /* | |
1625 +--------------------------------------------------------------------+ | |
1626 | PROJECT : GSM-PS (6147) MODULE : DL_COM | | |
1627 | STATE : code ROUTINE : free_sending_buffer | | |
1628 +--------------------------------------------------------------------+ | |
1629 | |
1630 PURPOSE : After confirmation of an I frame the sending buffer is | |
1631 released if it was the last segment. This avoids | |
1632 resending of I frames after resumption. | |
1633 | |
1634 */ | |
1635 static void free_sending_buffer ( UBYTE ch_type, UBYTE sapi) | |
1636 { | |
1637 GET_INSTANCE_DATA; | |
1638 T_QUEUE *queue = NULL; | |
1639 | |
1640 TRACE_EVENT_WIN_P2 ("free_sending_buffer():%s SAPI=%u", CH_TYPE_NAME[ch_type], sapi); | |
1641 | |
1642 switch (ch_type) | |
1643 { | |
1644 case L2_CHANNEL_SDCCH: | |
1645 if (sapi EQ PS_SAPI_0) | |
1646 queue = &dl_data->dcch0_queue; | |
1647 else if (sapi EQ PS_SAPI_3) | |
1648 queue = &dl_data->dcch3_queue; | |
1649 break; | |
1650 case L2_CHANNEL_SACCH: | |
1651 if (sapi EQ PS_SAPI_3) | |
1652 queue = &dl_data->dcch3_queue; | |
1653 break; | |
1654 case L2_CHANNEL_FACCH_F: | |
1655 case L2_CHANNEL_FACCH_H: | |
1656 if (sapi EQ PS_SAPI_0) | |
1657 queue = &dl_data->dcch0_queue; | |
1658 break; | |
1659 default: | |
1660 break; | |
1661 } | |
1662 | |
1663 if (queue) | |
1664 { | |
1665 if (queue->switch_buffer) | |
1666 { | |
1667 TRACE_EVENT_WIN_P3 ("CNF on %s SAPI=%u %s (switch_buffer)", | |
1668 CH_TYPE_NAME[queue->switch_buffer->ch_type], | |
1669 queue->switch_buffer->sapi, | |
1670 queue->switch_buffer->cnf ? "CNF required" : ""); | |
1671 | |
1672 com_l3trace (TRACE_UPLINK, queue->switch_buffer->ch_type, (UBYTE *)queue->switch_buffer); | |
1673 COM_FREE_QUEUE_BUFFER ( queue, INDEX_SWITCH_BUFFER); | |
1674 } | |
1675 else if (queue->sending_buffer) | |
1676 { | |
1677 TRACE_EVENT_WIN_P4 ("CNF on %s SAPI=%u %s (sending_buffer) act_length=%u", | |
1678 CH_TYPE_NAME[queue->sending_buffer->ch_type], | |
1679 queue->sending_buffer->sapi, | |
1680 queue->sending_buffer->cnf ? "CNF required" : "", | |
1681 queue->act_length); | |
1682 | |
1683 if (queue->act_length EQ 0) | |
1684 { /* entire message has been sent */ | |
1685 com_l3trace (TRACE_UPLINK, queue->sending_buffer->ch_type, (UBYTE *)queue->sending_buffer); | |
1686 | |
1687 if (queue->sending_buffer->cnf) | |
1688 { | |
1689 drr_dl_data_cnf (sapi); | |
1690 } | |
1691 else | |
1692 { | |
1693 COM_FREE_QUEUE_BUFFER (queue, INDEX_SENDING_BUFFER); | |
1694 } | |
1695 } | |
1696 } | |
1697 else | |
1698 { | |
1699 TRACE_EVENT_WIN_P2 ("%s SAPI=%u: sending_buffer and switch_buffer=NULL !!!", | |
1700 CH_TYPE_NAME[ch_type], sapi); | |
1701 } | |
1702 } | |
1703 }/* endfunc concatenate */ | |
1704 | |
1705 static void T200_expiry ( UBYTE channel, UBYTE sapi) | |
1706 { | |
1707 GET_INSTANCE_DATA; | |
1708 UBYTE old_state; | |
1709 UBYTE new_state; | |
1710 T_CCH * pcch = &dl_data->cch[channel]; | |
1711 UBYTE N200_counter; | |
1712 | |
1713 TRACE_FUNCTION ("T200_expiry()"); | |
1714 | |
1715 switch (pcch->ch_type) | |
1716 { | |
1717 case L2_CHANNEL_SACCH: | |
1718 N200_counter = SACCH_N200; | |
1719 break; | |
1720 case L2_CHANNEL_SDCCH: | |
1721 N200_counter = SDCCH_N200; | |
1722 break; | |
1723 case L2_CHANNEL_FACCH_F: | |
1724 N200_counter = FACCH_N200_FR; | |
1725 break; | |
1726 case L2_CHANNEL_FACCH_H: | |
1727 N200_counter = FACCH_N200_HR; | |
1728 break; | |
1729 default: | |
1730 N200_counter = NOT_PRESENT_8BIT; | |
1731 break; | |
1732 } | |
1733 | |
1734 new_state = old_state = dl_data->state[channel]; | |
1735 switch (old_state) | |
1736 { | |
1737 case STATE_CONTENTION_RESOLUTION: | |
1738 repeat_sabm (channel, sapi); | |
1739 break; | |
1740 | |
1741 case STATE_MULTIPLE_FRAME_ESTABLISHED: | |
1742 pcch->rc = 1; | |
1743 pcch->p_bit_flag= 1; | |
1744 pcch->time_flag = TRUE; | |
1745 new_state = STATE_TIMER_RECOVERY; | |
1746 break; | |
1747 | |
1748 case STATE_TIMER_RECOVERY: | |
1749 if (N200_counter EQ NOT_PRESENT_8BIT) | |
1750 break; /* invalid channel */ | |
1751 | |
1752 if (pcch->rc >= N200_counter) | |
1753 { /* release connection due to T200 expired N200 plus 1 times */ | |
1754 | |
1755 TRACE_EVENT_WIN_P1 ("T200 expired, N200=%u", N200_counter); | |
1756 | |
1757 /* New! Called now by mdl_error_ind(). | |
1758 * drr_dl_release_ind (dl_data, pcch->ch_type, sapi, NOT_PRESENT_8BIT); | |
1759 */ | |
1760 mdl_error_ind (T200_EXPIRED_N200_PLUS_1_TIMES, pcch->ch_type, sapi); | |
1761 | |
1762 if (sapi EQ PS_SAPI_0) | |
1763 { | |
1764 dcch3_init_dl_data(); | |
1765 pcch->T200_counter = 0; | |
1766 pcch->time_flag = FALSE; | |
1767 pcch->contention_resolution = FALSE; | |
1768 pcch->vtx = EMPTY_CMD; | |
1769 new_state = STATE_IDLE_DL; | |
1770 } | |
1771 } | |
1772 else | |
1773 { | |
1774 pcch->rc++; | |
1775 pcch->p_bit_flag = 1; | |
1776 pcch->time_flag = TRUE; | |
1777 } | |
1778 break; | |
1779 | |
1780 case STATE_AWAITING_RELEASE: | |
1781 if (pcch->rc >= N200_ESTABLISHMENT) | |
1782 { | |
1783 TRACE_EVENT_WIN_P1 ("T200 expired, N200=%u", N200_ESTABLISHMENT); | |
1784 drr_dl_release_cnf (pcch->ch_type, sapi, TRUE); | |
1785 new_state = STATE_IDLE_DL; | |
1786 | |
1787 } | |
1788 else | |
1789 { | |
1790 pcch->rc++; | |
1791 pcch->vtx = DISC_CMD; | |
1792 pcch->time_flag = TRUE; | |
1793 } | |
1794 break; | |
1795 | |
1796 default: | |
1797 break; | |
1798 }/* endswitch old_state */ | |
1799 | |
1800 if (new_state NEQ old_state) | |
1801 { | |
1802 set_channel_state (channel, new_state); | |
1803 } | |
1804 | |
1805 }/* endfunc T200_expiry */ | |
1806 | |
1807 /* | |
1808 +--------------------------------------------------------------------+ | |
1809 | PROJECT : GSM-PS (6147) MODULE : state | | |
1810 | STATE : code ROUTINE : repeat_sabm | | |
1811 +--------------------------------------------------------------------+ | |
1812 | |
1813 PURPOSE : Repeat if possible the SABM command. | |
1814 | |
1815 */ | |
1816 | |
1817 static void repeat_sabm (UBYTE channel, UBYTE sapi) | |
1818 { | |
1819 GET_INSTANCE_DATA; | |
1820 T_CCH* pcch = &dl_data->cch[channel]; | |
1821 | |
1822 TRACE_FUNCTION ("repeat_sabm()"); | |
1823 | |
1824 if (pcch->rc >= N200_ESTABLISHMENT) | |
1825 { | |
1826 if (sapi EQ PS_SAPI_0) | |
1827 pcch->contention_resolution = FALSE; | |
1828 | |
1829 DL_OFFLINE_TRACE (TRACE_DL_EVENT, channel, pcch->ch_type, ">N200_EST"); | |
1830 SYST_TRACE_P ((SYST, "DL: >N200 of SABM")); | |
1831 TRACE_ERROR ("DL: >N200 of SABM"); | |
1832 | |
1833 DL_EM_CHANNEL_ESTABLISHMENT_FAILED; | |
1834 | |
1835 mdl_error_ind(T200_EXPIRED_N200_PLUS_1_TIMES, pcch->ch_type, sapi); | |
1836 set_channel_state (channel, STATE_IDLE_DL); | |
1837 /* New! Called now by mdl_error_ind(). | |
1838 * drr_dl_release_ind (dl_data, pcch->ch_type, sapi, NOT_PRESENT_8BIT); | |
1839 */ | |
1840 } | |
1841 else | |
1842 { | |
1843 pcch->rc++; | |
1844 pcch->vtx = SABM_CMD; | |
1845 pcch->time_flag = TRUE; | |
1846 TRACE_EVENT_P1 ("DL: T200 %u. repeat of SABM", pcch->rc); | |
1847 } | |
1848 }/* endfunc repeat_sabm */ | |
1849 | |
1850 GLOBAL void set_channel_state (UBYTE channel, UBYTE state) | |
1851 { | |
1852 GET_INSTANCE_DATA; | |
1853 if (dl_data->state[channel] NEQ state) | |
1854 { | |
1855 #ifdef TRACE_STATE | |
1856 vsi_o_state_ttrace ("STATE_%s:%s -> %s", PROCESS_NAME[channel], | |
1857 channel EQ C_DCCH3 ? STATE_DCCH3_NAME[dl_data->state[channel]]: | |
1858 STATE_DCCH0_NAME[dl_data->state[channel]], | |
1859 channel EQ C_DCCH3 ? STATE_DCCH3_NAME[state] : | |
1860 STATE_DCCH0_NAME[state]); | |
1861 #endif /* TRACE_STATE */ | |
1862 dl_data->state[channel] = state; | |
1863 DL_OFFLINE_TRACE (TRACE_CHSTATE, channel, dl_data->cch[channel].ch_type, NULL); | |
1864 } | |
1865 }/* endfunc set_channel_state */ | |
1866 | |
1867 static void set_T200_counter (T_CCH* pcch, UBYTE sapi) | |
1868 { | |
1869 switch (pcch->ch_type) | |
1870 { | |
1871 case L2_CHANNEL_SACCH: | |
1872 pcch->T200_counter = sapi EQ PS_SAPI_0 ? | |
1873 T200_SDCCH_SAPI_0_CNT : T200_SACCH_SAPI_3_CNT; | |
1874 break; | |
1875 default: | |
1876 TRACE_EVENT_WIN_P1 ("set_T200_counter: unknown ch_type=%u -> use SDCCH", pcch->ch_type); | |
1877 /*lint -fallthrough*/ | |
1878 case L2_CHANNEL_SDCCH: | |
1879 pcch->T200_counter = sapi EQ PS_SAPI_0 ? | |
1880 T200_SDCCH_SAPI_0_CNT : T200_SDCCH_SAPI_3_CNT; | |
1881 break; | |
1882 case L2_CHANNEL_FACCH_F: | |
1883 pcch->T200_counter = T200_FACCH_SAPI_0_CNT_FR; | |
1884 break; | |
1885 case L2_CHANNEL_FACCH_H: | |
1886 pcch->T200_counter = T200_FACCH_SAPI_0_CNT_HR; | |
1887 break; | |
1888 }/* endswitch ch_type */ | |
1889 pcch->time_flag = FALSE; | |
1890 | |
1891 TRACE_EVENT_WIN_P3 ("set_T200_counter: %s, SAPI=%u: %u", | |
1892 CH_TYPE_NAME[pcch->ch_type], sapi, pcch->T200_counter); | |
1893 }/* endfunc set_T200_counter */ | |
1894 | |
1895 #if defined(DELAYED_RELEASE_IND) | |
1896 static void delayed_release_ind( UBYTE channel) | |
1897 { | |
1898 GET_INSTANCE_DATA; | |
1899 /* delay DL RELEASE IND to RR for FTA 25.2.3 *********** */ | |
1900 if (dl_data->release_ind_ch_type NEQ NOT_PRESENT_8BIT) | |
1901 { | |
1902 if (dl_data->release_ind_delay > 0) | |
1903 dl_data->release_ind_delay--; | |
1904 | |
1905 if (dl_data->release_ind_delay EQ 0) | |
1906 { | |
1907 DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, | |
1908 dl_data->release_ind_ch_type, "UL:send delayed REL IND"); | |
1909 drr_dl_release_ind (dl_data->release_ind_ch_type, | |
1910 dl_data->release_ind_sapi, NOT_PRESENT_8BIT, TRUE); | |
1911 } | |
1912 else | |
1913 { | |
1914 DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, | |
1915 dl_data->release_ind_ch_type, "UL:pend. delay REL IND"); | |
1916 } | |
1917 | |
1918 } | |
1919 } | |
1920 | |
1921 #endif /* DELAYED_RELEASE_IND */ | |
1922 | |
1923 T_RADIO_FRAME* dl_uplink(UBYTE channel, UBYTE sapi, | |
1924 UBYTE no_signalling_mode, BOOL recursive) | |
1925 { | |
1926 GET_INSTANCE_DATA; | |
1927 T_CCH* pcch = &dl_data->cch[channel]; | |
1928 T_RADIO_FRAME* p_l2_frame = &dl_data->l2_frame; | |
1929 int send = UPLINK_NULL; | |
1930 | |
1931 TRACE_EVENT_WIN_P3 ("uplink(): %s dcch0_ch_type:%s dedi=%u", | |
1932 CH_TYPE_NAME[pcch->ch_type], CH_TYPE_NAME[dl_data->dcch0_ch_type], dl_data->RR_dedicated); | |
1933 TRACE_EVENT_WIN_P6 ("UL: DCCH0=%s,%s vr=%u vs=%u va=%u T200=%u", | |
1934 CH_TYPE_NAME[dl_data->cch[C_DCCH0].ch_type], | |
1935 STATE_DCCH0_NAME[dl_data->state[C_DCCH0]], | |
1936 dl_data->cch[C_DCCH0].vr, dl_data->cch[C_DCCH0].vs, dl_data->cch[C_DCCH0].va, | |
1937 dl_data->cch[C_DCCH0].T200_counter); | |
1938 TRACE_EVENT_WIN_P6 ("UL: DCCH3=%s,%s vr=%u vs=%u va=%u T200=%u", | |
1939 CH_TYPE_NAME[dl_data->cch[C_DCCH3].ch_type], | |
1940 STATE_DCCH3_NAME[dl_data->state[C_DCCH3]], | |
1941 dl_data->cch[C_DCCH3].vr, dl_data->cch[C_DCCH3].vs, dl_data->cch[C_DCCH3].va, | |
1942 dl_data->cch[C_DCCH3].T200_counter); | |
1943 | |
1944 | |
1945 /* check SACCH SAPI and channel */ | |
1946 if (pcch->ch_type EQ L2_CHANNEL_SACCH) | |
1947 { | |
1948 if (!dl_data->RR_dedicated) | |
1949 { | |
1950 sapi = PS_SAPI_0; | |
1951 send = UPLINK_EMPTY; | |
1952 TRACE_EVENT_WIN ("SACCH without dedicated channel: change SAPI->0, UPLINK_EMPTY"); | |
1953 } | |
1954 else if (dl_data->state[C_DCCH0] EQ STATE_SUSPENDED) | |
1955 { | |
1956 sapi = PS_SAPI_0; | |
1957 send = UPLINK_REPORT; | |
1958 TRACE_EVENT_WIN ("SACCH during suspended dedicated channel: change SAPI->0, UPLINK_REPORT"); | |
1959 } | |
1960 else if (sapi EQ PS_SAPI_3) | |
1961 { | |
1962 if ((dl_data->state[C_DCCH0] <= STATE_IDLE_DL) | |
1963 OR | |
1964 (dl_data->dcch0_ch_type EQ L2_CHANNEL_SDCCH) | |
1965 OR | |
1966 ((dl_data->cch[C_DCCH3].vtx EQ EMPTY_CMD) AND | |
1967 (!com_queue_awaiting_transmission (PS_SAPI_3)) AND | |
1968 (dl_data->state[C_DCCH3] NEQ STATE_AWAITING_ESTABLISHMENT) | |
1969 ) ) | |
1970 { | |
1971 sapi = PS_SAPI_0; | |
1972 TRACE_EVENT_WIN ("SACCH with SAPI=3 only together with FACCH and frame is awaiting tx: change SAPI->0"); | |
1973 } | |
1974 else | |
1975 { | |
1976 channel = C_DCCH3; | |
1977 pcch = &dl_data->cch[channel]; | |
1978 TRACE_EVENT_WIN ("SACCH with SAPI=3 together with FACCH: change channel->C_DCCH3"); | |
1979 } | |
1980 } | |
1981 } | |
1982 else if ((dl_data->RR_dedicated) AND | |
1983 (dl_data->dcch0_ch_type NEQ pcch->ch_type)) | |
1984 { | |
1985 TRACE_EVENT_WIN_P2 ("dcch0_ch_type (%s) NEQ %s -> unexpected,unsolicited,invalid channel => UPLINK_EMPTY", | |
1986 CH_TYPE_NAME[dl_data->dcch0_ch_type], | |
1987 CH_TYPE_NAME[dl_data->cch[C_DCCH0].ch_type]); | |
1988 send = UPLINK_EMPTY; | |
1989 } | |
1990 | |
1991 /* decrease T200 counter ************************************ */ | |
1992 if (channel EQ C_DCCH3) | |
1993 { | |
1994 if (dl_data->cch[C_DCCH3].T200_counter >= T200_ACTIVE) | |
1995 { | |
1996 dl_data->cch[C_DCCH3].T200_counter--; | |
1997 TRACE_EVENT_WIN_P2 ("T200(SAPI_0)=%u T200(SAPI_3)=%u*", | |
1998 dl_data->cch[C_DCCH0].T200_counter, dl_data->cch[C_DCCH3].T200_counter); | |
1999 /*DL_OFFLINE_TRACE (TRACE_DL_EVENT, channel, pcch->ch_type, "dec T200(SAPI_3)");*/ | |
2000 } | |
2001 } | |
2002 else | |
2003 { | |
2004 if (pcch->ch_type NEQ L2_CHANNEL_SACCH) /* no T200 for SACCH with SAPI=0 */ | |
2005 { | |
2006 if (dl_data->cch[C_DCCH0].T200_counter >= T200_ACTIVE) | |
2007 { | |
2008 dl_data->cch[C_DCCH0].T200_counter--; | |
2009 TRACE_EVENT_WIN_P2 ("T200(SAPI_0)=%u* T200(SAPI_3)=%u", | |
2010 dl_data->cch[C_DCCH0].T200_counter, dl_data->cch[C_DCCH3].T200_counter); | |
2011 /*DL_OFFLINE_TRACE (TRACE_DL_EVENT, channel, pcch->ch_type, "dec T200(SAPI_0)");*/ | |
2012 } | |
2013 } | |
2014 } | |
2015 | |
2016 /* check activity of DL ************************************* */ | |
2017 if (dl_data->dl_active AND dl_data->state[channel] EQ STATE_MULTIPLE_FRAME_ESTABLISHED) | |
2018 { | |
2019 TRACE_EVENT_WIN_P1 ("uplink(): %s dl_active", PROCESS_NAME[channel]); | |
2020 DL_OFFLINE_TRACE (TRACE_DL_EVENT, channel, pcch->ch_type, "UL:&dl_active"); | |
2021 | |
2022 /* signalling only */ | |
2023 send = UPLINK_EMPTY; | |
2024 }/* endif dl_active */ | |
2025 | |
2026 #if defined(DELAYED_SABM) | |
2027 /* delay uplink SABM to PL for FTA 26.6.6.1 and 25.2.3 *********** */ | |
2028 if ((channel EQ C_DCCH0) AND (dl_data->dcch0_sabm_flag NEQ NOT_PRESENT_8BIT)) | |
2029 { | |
2030 dcch0_delay_sabm (pcch); | |
2031 if (dl_data->dcch0_sabm_flag NEQ NOT_PRESENT_8BIT) | |
2032 send = UPLINK_EMPTY; /* send dummy only */ | |
2033 } | |
2034 #endif /* DELAYED_SABM */ | |
2035 | |
2036 | |
2037 #if defined(DELAYED_RELEASE_IND) | |
2038 delayed_release_ind (channel); | |
2039 #endif /* DELAYED_RELEASE_IND */ | |
2040 | |
2041 if ((send EQ UPLINK_NULL) OR (send EQ UPLINK_EMPTY)) | |
2042 { /* After a L3 release at the last downlink DL should send a DISC */ | |
2043 TRACE_EVENT_WIN_P6 ("uplink():%s %s SAPI=%u vtx=%s %s (#%u)", | |
2044 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi, | |
2045 VTX_NAME[pcch->vtx], SEND_NAME[send], __LINE__); | |
2046 switch (channel) | |
2047 { | |
2048 case C_DCCH0: | |
2049 send = dcch0_check_disc (send); | |
2050 break; | |
2051 case C_DCCH3: | |
2052 send = dcch3_check_disc (send); | |
2053 break; | |
2054 default: | |
2055 break; | |
2056 } | |
2057 TRACE_EVENT_WIN_P6 ("uplink():%s %s SAPI=%u vtx=%s %s (#%u)", | |
2058 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi, | |
2059 VTX_NAME[pcch->vtx], SEND_NAME[send], __LINE__); | |
2060 } | |
2061 | |
2062 if (send EQ UPLINK_NULL) | |
2063 { | |
2064 TRACE_EVENT_WIN_P5 ("uplink():%s %s SAPI=%u vtx=%s %s", | |
2065 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi, | |
2066 VTX_NAME[pcch->vtx], recursive ? "RECURSIVE" : ""); | |
2067 | |
2068 TRACE_EVENT_WIN_P8 ("UL: DCCH%u=%s,%s vr=%u vs=%u va=%u T200=%u (#%u)", | |
2069 sapi, CH_TYPE_NAME[dl_data->cch[channel].ch_type], | |
2070 STATE_DCCH3_NAME[dl_data->state[channel]], | |
2071 dl_data->cch[channel].vr, dl_data->cch[channel].vs, dl_data->cch[channel].va, | |
2072 dl_data->cch[channel].T200_counter, __LINE__); | |
2073 | |
2074 /* check timer T200 expiry ****************************** */ | |
2075 if ((channel EQ C_DCCH0) AND | |
2076 (dl_data->cch[C_DCCH0].T200_counter EQ T200_EXPIRED)) | |
2077 T200_expiry (C_DCCH0, PS_SAPI_0); | |
2078 if ((channel EQ C_DCCH3) AND | |
2079 (dl_data->cch[C_DCCH3].T200_counter EQ T200_EXPIRED)) | |
2080 T200_expiry (C_DCCH3, PS_SAPI_3); | |
2081 | |
2082 TRACE_EVENT_WIN_P8 ("UL: DCCH%u=%s,%s vr=%u vs=%u va=%u T200=%u (#%u)", | |
2083 sapi, CH_TYPE_NAME[dl_data->cch[channel].ch_type], | |
2084 STATE_DCCH3_NAME[dl_data->state[channel]], | |
2085 dl_data->cch[channel].vr, dl_data->cch[channel].vs, dl_data->cch[channel].va, | |
2086 dl_data->cch[channel].T200_counter, __LINE__); | |
2087 | |
2088 /* state machine **************************************** */ | |
2089 switch (dl_data->state[channel]) | |
2090 { | |
2091 case STATE_IDLE_DL: | |
2092 if (pcch->vtx EQ EMPTY_CMD AND !dl_data->RR_dedicated) | |
2093 break; | |
2094 send = uplink_idle (channel, sapi); | |
2095 break; | |
2096 case STATE_CONTENTION_RESOLUTION: /* the same as STATE_AWAITING_ESTABLISHMENT */ | |
2097 send = uplink_awaiting_establishment (channel, sapi, no_signalling_mode); | |
2098 break; | |
2099 case STATE_MULTIPLE_FRAME_ESTABLISHED: | |
2100 send = uplink_mfe (channel, sapi, no_signalling_mode); | |
2101 break; | |
2102 case STATE_TIMER_RECOVERY: | |
2103 send = uplink_timer_recovery (channel, sapi, no_signalling_mode); | |
2104 break; | |
2105 case STATE_AWAITING_RELEASE: | |
2106 send = uplink_awaiting_release ( channel, sapi); | |
2107 break; | |
2108 case STATE_SUSPENDED: /* only DCCH0 */ | |
2109 send = UPLINK_NULL; | |
2110 break; | |
2111 case STATE_DISABLED: /* only SABM/UA or SACCH and SDCCH (SAPI 3) */ | |
2112 if (channel EQ C_DCCH3) | |
2113 { | |
2114 if (pcch->vtx EQ UA_CMD) | |
2115 { | |
2116 send = uplink_idle (channel, sapi); | |
2117 } | |
2118 else | |
2119 { | |
2120 send = UPLINK_EMPTY; | |
2121 } | |
2122 } | |
2123 break; | |
2124 }/* endswitch channel_state */ | |
2125 | |
2126 }/* endif send == NULL */ | |
2127 | |
2128 TRACE_EVENT_WIN_P8 ("UL: DCCH%u=%s,%s vr=%u vs=%u va=%u T200=%u (#%u)", | |
2129 sapi, CH_TYPE_NAME[dl_data->cch[channel].ch_type], | |
2130 STATE_DCCH3_NAME[dl_data->state[channel]], | |
2131 dl_data->cch[channel].vr, dl_data->cch[channel].vs, dl_data->cch[channel].va, | |
2132 dl_data->cch[channel].T200_counter, __LINE__); | |
2133 | |
2134 if (pcch->ch_type EQ L2_CHANNEL_SACCH) | |
2135 { /* | |
2136 * According to 3GPP TS 04.05, 4.2.2 Priority: | |
2137 * The priority arrangement on the SACCH must ensure that if a SAPI = 3 | |
2138 * frame is awaiting transmission, two SAPI = 0 frames are not sent in | |
2139 * consecutive SACCH frames. In addition, for the mobile to network | |
2140 * direction it must also be ensured that any SAPI = 3 frame is followed | |
2141 * by at least one SAPI = 0 frame. | |
2142 */ | |
2143 | |
2144 TRACE_EVENT_WIN_P3 ("sacch_last_uplink_sapi=%u SAPI=%u send=%s", | |
2145 dl_data->sacch_last_uplink_sapi, sapi, SEND_NAME[send]); | |
2146 | |
2147 if ((dl_data->sacch_last_uplink_sapi EQ PS_SAPI_3) OR | |
2148 ((sapi EQ PS_SAPI_3 ) AND (send EQ UPLINK_EMPTY))) | |
2149 {/* last uplinked SACCH frame was one with SAPI=3 | |
2150 * or | |
2151 * no SACCH SAPI=3 frame is awaiting transmission | |
2152 * -> uplink of a SACCH SAPI=0 frame | |
2153 */ | |
2154 sapi = PS_SAPI_0; | |
2155 } | |
2156 | |
2157 if (send EQ UPLINK_EMPTY) | |
2158 { | |
2159 sapi = PS_SAPI_0; | |
2160 } | |
2161 | |
2162 if ((sapi EQ PS_SAPI_0) AND (dl_data->state[C_DCCH0] >= STATE_SUSPENDED)) | |
2163 { /* | |
2164 * uplink measurement reports only if SAPI=0 is suspended, | |
2165 * on contention resolution procedure, established or awaiting release | |
2166 */ | |
2167 send = UPLINK_REPORT; | |
2168 TRACE_EVENT_WIN ("uplink(): SACCH REPORT now"); | |
2169 } | |
2170 | |
2171 TRACE_EVENT_WIN_P2 ("sacch_last_uplink_sapi:=%u->%u", dl_data->sacch_last_uplink_sapi, sapi); | |
2172 dl_data->sacch_last_uplink_sapi = sapi; | |
2173 } | |
2174 else if ((pcch->ch_type EQ L2_CHANNEL_SDCCH) AND (channel NEQ C_DCCH3)) | |
2175 { /* | |
2176 * According to 3GPP TS 04.05, 4.2.2 Priority: | |
2177 * The priority between data links on SDCCH shall be as follows: | |
2178 * Highest priority : SAPI = 0, Lowest priority : SAPI = 3. | |
2179 */ | |
2180 if ((sapi EQ PS_SAPI_0) AND (send <= UPLINK_EMPTY)) | |
2181 { /* special case: nothing is awaiting transmission for SAPI=0 */ | |
2182 if ((dl_data->cch[C_DCCH3].vtx NEQ EMPTY_CMD) OR | |
2183 com_queue_awaiting_transmission(PS_SAPI_3) OR | |
2184 (dl_data->cch[C_DCCH3].T200_counter NEQ T200_STOPPED)) | |
2185 {/* something is awaiting transmission for SAPI=3 */ | |
2186 if (dl_data->state[C_DCCH0] >= STATE_CONTENTION_RESOLUTION) | |
2187 { /* | |
2188 * uplink SAPI=3 only if SAPI=0 is on contention resolution procedure | |
2189 * or established or awaiting release | |
2190 */ | |
2191 send = UPLINK_DCCH3; | |
2192 } | |
2193 } | |
2194 | |
2195 } | |
2196 } | |
2197 else | |
2198 { | |
2199 /* no special treatment of FACCH */ | |
2200 } | |
2201 | |
2202 /* return uplink frame buffer pointer dependent on the value of send */ | |
2203 TRACE_EVENT_WIN_P4 ("%s on %s SAPI=%u RR_dedicated=%u", | |
2204 SEND_NAME[send], CH_TYPE_NAME[pcch->ch_type], sapi, dl_data->RR_dedicated); | |
2205 | |
2206 switch (send) | |
2207 { | |
2208 case UPLINK_NORMAL: | |
2209 break; | |
2210 | |
2211 case UPLINK_UA: | |
2212 case UPLINK_UA_F: | |
2213 com_build_UA_response (pcch->ch_type, sapi, (UBYTE)((send EQ UPLINK_UA_F) ? 1 : 0)); | |
2214 break; | |
2215 | |
2216 case UPLINK_IFRAME: | |
2217 case UPLINK_IFRAME_P: | |
2218 { | |
2219 UBYTE m_bit; | |
2220 UBYTE p_bit = (send EQ UPLINK_IFRAME_P) ? 1 : 0; | |
2221 T_QUEUE *queue; | |
2222 | |
2223 if (pcch->ch_type EQ L2_CHANNEL_SACCH) | |
2224 { | |
2225 sapi = PS_SAPI_3; /* acknowledged mode only for SAPI=3 */ | |
2226 TRACE_EVENT_WIN ("SACCH with I frame: acknowledged mode only for SAPI=3"); | |
2227 } | |
2228 | |
2229 if (sapi EQ PS_SAPI_0) | |
2230 queue = &dl_data->dcch0_queue; | |
2231 else | |
2232 queue = &dl_data->dcch3_queue; | |
2233 | |
2234 if (send EQ UPLINK_IFRAME) | |
2235 { | |
2236 com_read_queue (pcch->ch_type, sapi, &m_bit); | |
2237 } | |
2238 else | |
2239 {/* TIMER_RECOVERY state -> repetition of the last frame */ | |
2240 pcch->vs--; | |
2241 pcch->vs &= 7; | |
2242 pcch->p_bit_flag = 0; | |
2243 m_bit = queue->m_bit; /* remember last m bit */ | |
2244 TRACE_EVENT_WIN_P2 ("TIMER_RECOVERY state: decrement vs to %u, remember m=%u", pcch->vs, m_bit); | |
2245 } | |
2246 | |
2247 | |
2248 com_build_I_command (pcch->ch_type, sapi, pcch->vs, pcch->vr, | |
2249 p_bit, m_bit, queue); | |
2250 pcch->vs++; | |
2251 pcch->vs &= 7; | |
2252 TRACE_EVENT_WIN_P4 ("%s SAPI=%u new vs=%u (pcch=%08x)", | |
2253 CH_TYPE_NAME[pcch->ch_type], sapi, pcch->vs, pcch); | |
2254 } | |
2255 set_T200_counter (pcch, sapi); | |
2256 break; | |
2257 | |
2258 case UPLINK_RR: | |
2259 case UPLINK_RR_F: | |
2260 if (pcch->ch_type EQ L2_CHANNEL_SACCH) | |
2261 {/* | |
2262 * There are some tests at the start of dl_uplink() to determine the right | |
2263 * SAPI value for SACCH. But the resulting value may be wrong because of | |
2264 * the priority arrangement according to 3GPP TS 04.05, section 4.2.2. | |
2265 * In case the MS has to uplink a RR frame it is clear that | |
2266 * L2 is in acknowledged mode and this can be done only with | |
2267 * a SAPI value of 3 for SACCH. | |
2268 */ | |
2269 sapi = PS_SAPI_3; /* acknowledged mode only for SAPI=3 */ | |
2270 TRACE_EVENT_WIN ("SACCH with supervisory frame: acknowledged mode only for SAPI=3"); | |
2271 } | |
2272 com_build_RR_response (pcch->ch_type, sapi, pcch->vr, | |
2273 (UBYTE)((send EQ UPLINK_RR_F) ? 1 : 0)); | |
2274 break; | |
2275 | |
2276 case UPLINK_REJ: | |
2277 case UPLINK_REJ_F: | |
2278 if (pcch->ch_type EQ L2_CHANNEL_SACCH) | |
2279 {/* | |
2280 * There are some tests at the start of dl_uplink() to determine the right | |
2281 * SAPI value for SACCH. But the resulting value may be wrong because of | |
2282 * the priority arrangement according to 3GPP TS 04.05, section 4.2.2. | |
2283 * In case the MS has to uplink a REJ frame it is clear that | |
2284 * L2 is in acknowledged mode and this can be done only with | |
2285 * a SAPI value of 3 for SACCH. | |
2286 */ | |
2287 sapi = PS_SAPI_3; /* acknowledged mode only for SAPI=3 */ | |
2288 TRACE_EVENT_WIN ("SACCH with supervisory frame: acknowledged mode only for SAPI=3"); | |
2289 } | |
2290 com_build_REJ_response (pcch->ch_type, sapi, pcch->vr, | |
2291 (UBYTE)((send EQ UPLINK_REJ_F) ? 1 : 0)); | |
2292 break; | |
2293 | |
2294 case UPLINK_REPORT: | |
2295 if (dl_data->RR_dedicated) | |
2296 {/* measurement report only in RR dedicated mode */ | |
2297 sacch0_send_data (); | |
2298 com_l3trace (TRACE_UACK_UP, pcch->ch_type, (UBYTE *)p_l2_frame+5); | |
2299 | |
2300 | |
2301 /* no deleting of vtx!!! */ | |
2302 return p_l2_frame; | |
2303 /* break; not necessary */ | |
2304 }/* endif measurement report only in RR dedicated mode */ | |
2305 | |
2306 /* else go through to UPLINK_EMPTY */ | |
2307 /*lint -fallthrough*/ | |
2308 | |
2309 default: | |
2310 possible_reset_dcch0_ch_type(); | |
2311 | |
2312 /* check RR message with short PD, short L2 header type 1, format Bter */ | |
2313 if ((dl_data->state[C_DCCH0] >= STATE_SUSPENDED) AND | |
2314 dl_data->rr_short_pd_buffer.l_buf AND | |
2315 (dl_data->rr_short_pd_ch_type EQ pcch->ch_type)) | |
2316 { /* RR message with short PD, short L2 header type 1, format Bter */ | |
2317 com_build_UI_Bter (pcch->ch_type); | |
2318 return p_l2_frame; | |
2319 } | |
2320 | |
2321 if (((pcch->ch_type EQ L2_CHANNEL_FACCH_F) OR | |
2322 (pcch->ch_type EQ L2_CHANNEL_FACCH_H)) | |
2323 AND | |
2324 ((no_signalling_mode NEQ SIG_ONLY) | |
2325 #if defined(DELAYED_SABM) | |
2326 OR | |
2327 /* suppress UI frames if delayed SABM is pending | |
2328 * (independent from signalling mode) */ | |
2329 (dl_data->dcch0_sabm_flag NEQ NOT_PRESENT_8BIT) | |
2330 #endif /* DELAYED_SABM */ | |
2331 #if defined(DELAYED_RELEASE_IND) | |
2332 OR | |
2333 (dl_data->release_ind_ch_type NEQ NOT_PRESENT_8BIT) | |
2334 #endif /* DELAYED_RELEASE_IND */ | |
2335 )) | |
2336 { | |
2337 TRACE_EVENT_WIN ("UPLINK_NULL return"); | |
2338 return NULL; | |
2339 } | |
2340 /* break; not necessary */ | |
2341 | |
2342 { | |
2343 T_RADIO_FRAME* empty_frame; | |
2344 | |
2345 TRACE_EVENT_WIN ("UPLINK_EMPTY return"); | |
2346 /* The use of one byte array instead of two T_RADIO_FRAME structures | |
2347 * saves 21 byte. Casting is in this case the better way then two calls | |
2348 * of memcpy. | |
2349 */ | |
2350 if (pcch->ch_type EQ L2_CHANNEL_SACCH) | |
2351 empty_frame = (T_RADIO_FRAME*)(&l2_empty_frame[0]); | |
2352 else | |
2353 empty_frame = (T_RADIO_FRAME*)(&l2_empty_frame[2]); | |
2354 | |
2355 ATRC (empty_frame, 23); | |
2356 | |
2357 return empty_frame; | |
2358 } | |
2359 /* break; not necessary */ | |
2360 | |
2361 case UPLINK_DCCH3: | |
2362 return dl_uplink (C_DCCH3, PS_SAPI_3, no_signalling_mode, TRUE); | |
2363 /* break; not necessary */ | |
2364 }/* endswitch send */ | |
2365 | |
2366 | |
2367 /* | |
2368 * UPLINK_NORMAL, UPLINK_IFRAME (_P), UPLINK_UA (_F), | |
2369 * UPLINK_RR (_F), UPLINK_REJ (_F) | |
2370 */ | |
2371 TRACE_EVENT_WIN_P5 ("%s SAPI=%u delete vtx=%s ->EMPTY_CMD (%s#%u)", | |
2372 CH_TYPE_NAME[pcch->ch_type], sapi, VTX_NAME[pcch->vtx], __FILE10__, __LINE__); | |
2373 pcch->vtx = EMPTY_CMD; | |
2374 | |
2375 possible_reset_dcch0_ch_type(); | |
2376 | |
2377 return p_l2_frame; | |
2378 }/* endfunc dl_uplink */ | |
2379 | |
2380 static int uplink_idle (UBYTE channel, UBYTE sapi) | |
2381 { | |
2382 GET_INSTANCE_DATA; | |
2383 T_CCH* pcch = &dl_data->cch[channel]; | |
2384 int ret = UPLINK_NORMAL; | |
2385 int ua_response = FALSE; | |
2386 | |
2387 TRACE_EVENT_WIN_P3 ("uplink_idle(): %s %s SAPI=%d", | |
2388 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi); | |
2389 | |
2390 switch (channel) | |
2391 { | |
2392 case C_DCCH0: | |
2393 switch (pcch->vtx) | |
2394 { | |
2395 case UA_CMD: | |
2396 ret = pcch->f_bit ? UPLINK_UA_F : UPLINK_UA; | |
2397 break; | |
2398 case DM_CMD: | |
2399 com_build_DM_response (pcch->ch_type, sapi, pcch->f_bit); | |
2400 break; | |
2401 default: | |
2402 ret = UPLINK_EMPTY;/* no SAPI=3 frame if DCCH0 is idle */ | |
2403 break; | |
2404 } | |
2405 break; | |
2406 | |
2407 case C_DCCH3: | |
2408 switch (pcch->vtx) | |
2409 { | |
2410 case UA_CMD: | |
2411 ua_response = TRUE; | |
2412 ret = pcch->f_bit ? UPLINK_UA_F : UPLINK_UA; | |
2413 break; | |
2414 case DM_CMD: | |
2415 com_build_DM_response (pcch->ch_type, PS_SAPI_3, 1); | |
2416 ret = UPLINK_NORMAL; | |
2417 break; | |
2418 default: | |
2419 ret = UPLINK_EMPTY; | |
2420 break; | |
2421 } | |
2422 break; | |
2423 }/* endswitch channel */ | |
2424 | |
2425 if (ua_response AND (ret EQ UPLINK_UA_F)) | |
2426 { | |
2427 drr_dl_establish_ind (pcch->ch_type, sapi, | |
2428 (UBYTE)(com_queue_awaiting_transmission (sapi) ? DL_UNSERVED : DL_ALL_DONE)); | |
2429 set_channel_state (channel, STATE_MULTIPLE_FRAME_ESTABLISHED); | |
2430 } | |
2431 | |
2432 return ret; | |
2433 }/* endfunc uplink_idle */ | |
2434 | |
2435 static int uplink_awaiting_establishment (UBYTE channel, UBYTE sapi, | |
2436 UBYTE no_signalling_mode) | |
2437 { | |
2438 GET_INSTANCE_DATA; | |
2439 T_CCH* pcch = &dl_data->cch[channel]; | |
2440 int ret = UPLINK_NORMAL; | |
2441 int ua_response = FALSE; | |
2442 int sabm_command = 0; | |
2443 | |
2444 TRACE_EVENT_WIN_P3 ("uplink_awaiting_establishment(): %s %s SAPI=%d", | |
2445 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi); | |
2446 | |
2447 if (pcch->time_flag) | |
2448 set_T200_counter (pcch, sapi); | |
2449 | |
2450 switch (channel) | |
2451 { | |
2452 case C_DCCH0: | |
2453 if (pcch->vtx EQ SABM_CMD) | |
2454 { | |
2455 if (pcch->contention_resolution) | |
2456 sabm_command = 2; /* com_build_SABM with L3 */ | |
2457 else | |
2458 sabm_command = 1; /* com_build_SABM without L3 */ | |
2459 } | |
2460 else | |
2461 { | |
2462 ret = UPLINK_EMPTY;/* no SAPI=0 frame is waiting transmission */ | |
2463 } | |
2464 break; | |
2465 | |
2466 case C_DCCH3: | |
2467 switch (pcch->vtx) | |
2468 { | |
2469 case SABM_CMD: | |
2470 sabm_command = 1; /* com_build_SABM without L3 */ | |
2471 break; | |
2472 case UA_CMD: | |
2473 ua_response = TRUE; | |
2474 break; | |
2475 case DM_CMD: | |
2476 com_build_DM_response (pcch->ch_type, sapi, pcch->f_bit); | |
2477 break; | |
2478 default: | |
2479 ret = UPLINK_EMPTY; | |
2480 break; | |
2481 } | |
2482 | |
2483 break; | |
2484 } | |
2485 | |
2486 if (ua_response) | |
2487 { | |
2488 drr_dl_establish_cnf (pcch->ch_type, sapi); | |
2489 set_channel_state (channel, STATE_MULTIPLE_FRAME_ESTABLISHED); | |
2490 | |
2491 ret = pcch->f_bit ? UPLINK_UA_F : UPLINK_UA; | |
2492 } | |
2493 else if (sabm_command) | |
2494 { | |
2495 com_build_SABM(pcch->ch_type, sapi, sabm_command EQ 2); | |
2496 } | |
2497 | |
2498 return ret; | |
2499 }/* endfunc uplink_awaiting_establishment */ | |
2500 | |
2501 static int uplink_mfe (UBYTE channel, UBYTE sapi, UBYTE no_signalling_mode) | |
2502 { | |
2503 GET_INSTANCE_DATA; | |
2504 T_CCH* pcch = &dl_data->cch[channel]; | |
2505 int ret = UPLINK_NORMAL; | |
2506 | |
2507 TRACE_EVENT_WIN_P6 ("uplink_mfe(): %s:%s SAPI=%d vtx=%s (vs=%u va+1=%u)", | |
2508 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi, | |
2509 VTX_NAME[pcch->vtx], pcch->vs, (pcch->va + 1)&7 ); | |
2510 | |
2511 if (pcch->time_flag) | |
2512 set_T200_counter (pcch, sapi); | |
2513 | |
2514 switch (pcch->vtx) | |
2515 { | |
2516 case RR_CMD: | |
2517 if (pcch->f_bit_flag) | |
2518 { | |
2519 ret = UPLINK_RR_F; | |
2520 pcch->f_bit_flag = 0; | |
2521 } | |
2522 else | |
2523 { | |
2524 if (!com_queue_awaiting_transmission (sapi)) | |
2525 ret = UPLINK_RR; | |
2526 else | |
2527 { | |
2528 if (pcch->vs EQ ((pcch->va + 1)&7)) | |
2529 ret = UPLINK_RR; | |
2530 else | |
2531 ret = UPLINK_IFRAME; | |
2532 } | |
2533 } | |
2534 break; | |
2535 | |
2536 case UA_CMD: | |
2537 ret = pcch->f_bit ? UPLINK_UA_F : UPLINK_UA; | |
2538 break; | |
2539 | |
2540 case RR_RSP: | |
2541 ret = pcch->f_bit ? UPLINK_RR_F : UPLINK_RR; | |
2542 pcch->f_bit_flag = 0; | |
2543 break; | |
2544 | |
2545 case REJ_CMD: | |
2546 ret = pcch->f_bit ? UPLINK_REJ_F : UPLINK_REJ; | |
2547 pcch->f_bit_flag = 0; | |
2548 break; | |
2549 | |
2550 default: /* vtx = ELSE */ | |
2551 switch (channel) | |
2552 { | |
2553 case C_DCCH0: | |
2554 if (com_queue_awaiting_transmission (PS_SAPI_0) | |
2555 AND | |
2556 (pcch->vs NEQ ((pcch->va + 1)&7))) | |
2557 ret = UPLINK_IFRAME; | |
2558 else | |
2559 { | |
2560 ret = UPLINK_EMPTY;/* no SAPI=0 frame is waiting transmission */ | |
2561 } | |
2562 break; | |
2563 | |
2564 case C_DCCH3: | |
2565 if (com_queue_awaiting_transmission (PS_SAPI_3)) | |
2566 { | |
2567 if (pcch->vs EQ ((pcch->va + 1)&7)) | |
2568 ret = UPLINK_EMPTY; | |
2569 else | |
2570 ret = UPLINK_IFRAME; | |
2571 } | |
2572 else | |
2573 { | |
2574 ret = dcch3_check_disc (UPLINK_EMPTY);/* no SAPI=3 frame is waiting transmission */ | |
2575 } | |
2576 break; | |
2577 }/* endswitch channel */ | |
2578 break; | |
2579 }/* endswitch vtx */ | |
2580 | |
2581 | |
2582 return ret; | |
2583 }/* endfunc uplink_mfe */ | |
2584 | |
2585 static int uplink_timer_recovery (UBYTE channel, UBYTE sapi, UBYTE no_signalling_mode) | |
2586 { | |
2587 GET_INSTANCE_DATA; | |
2588 T_CCH* pcch = &dl_data->cch[channel]; | |
2589 int ret = UPLINK_NORMAL; | |
2590 | |
2591 TRACE_EVENT_WIN_P3 ("uplink_timer_recovery(): %s %s SAPI=%d", | |
2592 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi); | |
2593 | |
2594 if (pcch->time_flag) | |
2595 set_T200_counter (pcch, sapi); | |
2596 | |
2597 switch (pcch->vtx) | |
2598 { | |
2599 case RR_CMD: | |
2600 if (pcch->f_bit_flag) | |
2601 { | |
2602 ret = UPLINK_RR_F; | |
2603 pcch->f_bit_flag = 0; | |
2604 } | |
2605 else | |
2606 { | |
2607 if (pcch->p_bit_flag) | |
2608 ret = UPLINK_IFRAME_P; | |
2609 else | |
2610 ret = UPLINK_RR; | |
2611 } | |
2612 break; | |
2613 | |
2614 case UA_CMD: | |
2615 ret = pcch->f_bit ? UPLINK_UA_F : UPLINK_UA; | |
2616 break; | |
2617 | |
2618 case RR_RSP: | |
2619 ret = pcch->f_bit ? UPLINK_RR_F : UPLINK_RR; | |
2620 pcch->f_bit_flag = 0; | |
2621 break; | |
2622 | |
2623 case REJ_CMD: | |
2624 ret = pcch->f_bit ? UPLINK_REJ_F : UPLINK_REJ; | |
2625 pcch->f_bit_flag = 0; | |
2626 break; | |
2627 | |
2628 default: /* vtx = ELSE */ | |
2629 TRACE_EVENT_WIN_P3 ("%s SAPI=%u vtx=%s", | |
2630 CH_TYPE_NAME[pcch->ch_type], sapi, VTX_NAME[pcch->vtx]); | |
2631 | |
2632 if (pcch->p_bit_flag) | |
2633 ret = UPLINK_IFRAME_P; | |
2634 else | |
2635 switch (channel) | |
2636 { | |
2637 case C_DCCH0: | |
2638 ret = UPLINK_EMPTY;/* no SAPI=0 frame is waiting transmission */ | |
2639 break; | |
2640 | |
2641 case C_DCCH3: | |
2642 ret = dcch3_check_disc (UPLINK_EMPTY);/* no SAPI=3 frame is waiting transmission */ | |
2643 break; | |
2644 } | |
2645 break; | |
2646 } | |
2647 | |
2648 #if 0 /* decrement first short before sending the frame */ | |
2649 if (ret EQ UPLINK_IFRAME_P) | |
2650 { | |
2651 pcch->vs--; | |
2652 pcch->vs &= 7; | |
2653 pcch->p_bit_flag = 0; | |
2654 } | |
2655 #endif /* 0 */ | |
2656 return ret; | |
2657 }/* endfunc uplink_timer_recovery */ | |
2658 | |
2659 GLOBAL int uplink_awaiting_release (UBYTE channel, UBYTE sapi) | |
2660 { | |
2661 GET_INSTANCE_DATA; | |
2662 T_CCH* pcch = &dl_data->cch[channel]; | |
2663 int ret = UPLINK_NORMAL; | |
2664 | |
2665 TRACE_EVENT_WIN_P3 ("uplink_awaiting_release(): %s %s SAPI=%d", | |
2666 PROCESS_NAME[channel], CH_TYPE_NAME[pcch->ch_type], sapi); | |
2667 | |
2668 if (pcch->time_flag) | |
2669 set_T200_counter (pcch, sapi); | |
2670 | |
2671 switch (pcch->vtx) | |
2672 { | |
2673 case DISC_CMD: | |
2674 /* DL_OFFLINE_TRACE (TRACE_DL_EVENT, channel, pcch->ch_type, "UL:Send DISC"); */ | |
2675 com_build_DISC_command (pcch->ch_type, sapi, 1); | |
2676 break; | |
2677 case UA_CMD: | |
2678 set_channel_state (channel, STATE_IDLE_DL); | |
2679 | |
2680 #if defined(DELAYED_RELEASE_IND) | |
2681 switch (pcch->ch_type) | |
2682 { | |
2683 #if defined(DL_FACCH_RELEASE_DELAY_VALUE) && (DL_FACCH_RELEASE_DELAY_VALUE > 0) | |
2684 case L2_CHANNEL_FACCH_F: | |
2685 case L2_CHANNEL_FACCH_H: | |
2686 /* delay DL RELEASE IND to RR for testcase 25.2.3 */ | |
2687 dl_data->release_ind_ch_type = pcch->ch_type; | |
2688 dl_data->release_ind_sapi = sapi; | |
2689 if (dl_data->release_ind_delay EQ 0) | |
2690 { | |
2691 dl_data->release_ind_delay = DL_FACCH_RELEASE_DELAY_VALUE; | |
2692 DL_OFFLINE_TRACE (TRACE_DL_EVENT, C_DCCH0, pcch->ch_type, "delay REL IND on FACCH"); | |
2693 } | |
2694 break; | |
2695 #endif /* DL_FACCH_RELEASE_DELAY_VALUE */ | |
2696 #if defined(DL_SDCCH_RELEASE_DELAY_VALUE) && (DL_SDCCH_RELEASE_DELAY_VALUE > 0) | |
2697 case L2_CHANNEL_SDCCH: | |
2698 /* delay DL RELEASE IND to RR for testcase 25.2.3 */ | |
2699 dl_data->release_ind_ch_type = pcch->ch_type; | |
2700 dl_data->release_ind_sapi = sapi; | |
2701 if (dl_data->release_ind_delay EQ 0) | |
2702 { | |
2703 dl_data->release_ind_delay = DL_SDCCH_RELEASE_DELAY_VALUE; | |
2704 DL_OFFLINE_TRACE (TRACE_DL_EVENT, channel, pcch->ch_type, "delay REL IND on SDCCH"); | |
2705 } | |
2706 break; | |
2707 #endif /* DL_SDCCH_RELEASE_DELAY_VALUE */ | |
2708 default: | |
2709 drr_dl_release_ind (pcch->ch_type, sapi, NOT_PRESENT_8BIT, TRUE); | |
2710 break; | |
2711 } | |
2712 #else /* DELAYED_RELEASE_IND */ | |
2713 drr_dl_release_ind (pcch->ch_type, sapi, NOT_PRESENT_8BIT, TRUE); | |
2714 #endif /* DELAYED_RELEASE_IND */ | |
2715 | |
2716 #if defined(LATE_LEAVING_DEDICATED) | |
2717 com_leave_dedicated (pcch->ch_type); | |
2718 #endif /* LATE_LEAVING_DEDICATED */ | |
2719 ret = UPLINK_UA_F; | |
2720 break; | |
2721 | |
2722 default: | |
2723 switch (pcch->ch_type) | |
2724 { | |
2725 case L2_CHANNEL_SACCH: | |
2726 if (channel EQ C_DCCH0) | |
2727 ret = UPLINK_REPORT; | |
2728 break; | |
2729 default: | |
2730 if (channel EQ C_DCCH0) | |
2731 { | |
2732 pcch = &dl_data->cch[C_DCCH3]; | |
2733 if (pcch->time_flag) | |
2734 set_T200_counter (pcch, PS_SAPI_3); | |
2735 } | |
2736 ret = UPLINK_EMPTY; | |
2737 break; | |
2738 }/* endswitch channel */ | |
2739 }/* endswitch vtx */ | |
2740 | |
2741 return ret; | |
2742 }/* endfunc uplink_awaiting_release */ | |
2743 | |
2744 #if defined(CHECK_PCCHI) | |
2745 static void check_pcch_i (T_CCH_INTERN* pcch_i, int line) | |
2746 { | |
2747 char buf[23]; | |
2748 int ret = 0; | |
2749 | |
2750 if (pcch_i EQ NULL) | |
2751 ret = -1; | |
2752 else if (pcch_i->pcch EQ NULL) | |
2753 ret = -2; | |
2754 | |
2755 if (ret) | |
2756 { | |
2757 sprintf (buf, "#%d pcch=NULL %d", line, -ret); | |
2758 DL_OFFLINE_TRACE (TRACE_DL_EVENT, TRACE_CH_UNKNOWN, 0,buf); | |
2759 } | |
2760 | |
2761 return ret; | |
2762 }/* endfunc check_pcch_i */ | |
2763 #endif /* CHECK_PCCHI */ | |
2764 | |
2765 #endif /* DL_C */ |