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