FreeCalypso > hg > fc-tourmaline
comparison src/g23m-gsm/cc/cc_act.c @ 1:fa8dc04885d8
src/g23m-*: import from Magnetite
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Fri, 16 Oct 2020 06:25:50 +0000 |
parents | |
children |
comparison
equal
deleted
inserted
replaced
0:4e78acac3d88 | 1:fa8dc04885d8 |
---|---|
1 /* | |
2 +----------------------------------------------------------------------------- | |
3 | Project : GSM-PS (6147) | |
4 | Modul : CC_ACT | |
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 primitive processing functions | |
18 | of the SDL process Call Control for the call active | |
19 | phase of the component CC of the mobile station | |
20 +----------------------------------------------------------------------------- | |
21 */ | |
22 | |
23 #ifndef CC_ACT_C | |
24 #define CC_ACT_C | |
25 | |
26 #define ENTITY_CC | |
27 /*==== INCLUDES ===================================================*/ | |
28 | |
29 #include <string.h> | |
30 #include "typedefs.h" | |
31 #include "pcm.h" | |
32 #include "vsi.h" | |
33 #include "custom.h" | |
34 #include "gsm.h" | |
35 #include "message.h" | |
36 #include "ccdapi.h" | |
37 #include "prim.h" | |
38 #include "cnf_cc.h" | |
39 #include "mon_cc.h" | |
40 #include "pei.h" | |
41 #include "tok.h" | |
42 #include "cc.h" | |
43 #include "cc_em.h" | |
44 | |
45 /*==== EXPORT =====================================================*/ | |
46 | |
47 /*==== PROTOTYPES =================================================*/ | |
48 LOCAL void cc_mncc_hold_retrieve_req (T_PRIM * prim); | |
49 | |
50 /*==== PRIVAT =====================================================*/ | |
51 | |
52 /*==== VARIABLES ==================================================*/ | |
53 | |
54 /*==== FUNCTIONS ==================================================*/ | |
55 | |
56 /* | |
57 +--------------------------------------------------------------------+ | |
58 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
59 | STATE : code ROUTINE : cc_dtmf_full | | |
60 +--------------------------------------------------------------------+ | |
61 | |
62 PURPOSE : Check whether DTMF buffer is full | |
63 | |
64 */ | |
65 | |
66 LOCAL BOOL cc_dtmf_full (const T_DTMF *p_dtmf) | |
67 { | |
68 TRACE_FUNCTION ("cc_dtmf_full()"); | |
69 | |
70 return ((p_dtmf->read EQ p_dtmf->write + 1) OR | |
71 (p_dtmf->read EQ 0 AND p_dtmf->write EQ DTMF_BUF_SIZE - 1)); | |
72 } | |
73 | |
74 | |
75 /* | |
76 +--------------------------------------------------------------------+ | |
77 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
78 | STATE : code ROUTINE : cc_dtmf_empty | | |
79 +--------------------------------------------------------------------+ | |
80 | |
81 PURPOSE : Check whether DTMF buffer is empty | |
82 | |
83 */ | |
84 | |
85 LOCAL BOOL cc_dtmf_empty (const T_DTMF *p_dtmf) | |
86 { | |
87 TRACE_FUNCTION ("cc_dtmf_empty()"); | |
88 | |
89 return (p_dtmf->read EQ p_dtmf->write); | |
90 } | |
91 | |
92 | |
93 /* | |
94 +--------------------------------------------------------------------+ | |
95 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
96 | STATE : code ROUTINE : cc_dtmf_write | | |
97 +--------------------------------------------------------------------+ | |
98 | |
99 PURPOSE : Write next entry into DTMF buffer. | |
100 No checks are done (e.g. buffer full) | |
101 | |
102 */ | |
103 | |
104 LOCAL void cc_dtmf_write (T_DTMF *p_dtmf, UBYTE val) | |
105 { | |
106 TRACE_FUNCTION ("cc_dtmf_write()"); | |
107 | |
108 p_dtmf->buf[p_dtmf->write++] = val; | |
109 if (p_dtmf->write EQ DTMF_BUF_SIZE) | |
110 p_dtmf->write = 0; | |
111 } | |
112 | |
113 /* | |
114 +--------------------------------------------------------------------+ | |
115 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
116 | STATE : code ROUTINE : cc_dtmf_write | | |
117 +--------------------------------------------------------------------+ | |
118 | |
119 PURPOSE : Read next entry from DTMF buffer. | |
120 No checks are done (e.g. buffer empty) | |
121 | |
122 */ | |
123 | |
124 LOCAL UBYTE cc_dtmf_read (T_DTMF *p_dtmf) | |
125 { | |
126 UBYTE val; | |
127 | |
128 TRACE_FUNCTION ("cc_dtmf_read()"); | |
129 | |
130 val = p_dtmf->buf[p_dtmf->read++]; | |
131 if (p_dtmf->read EQ DTMF_BUF_SIZE) | |
132 p_dtmf->read = 0; | |
133 return val; | |
134 } | |
135 | |
136 | |
137 /* | |
138 +--------------------------------------------------------------------+ | |
139 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
140 | STATE : code ROUTINE : cc_dtmf_allowed | | |
141 +--------------------------------------------------------------------+ | |
142 | |
143 PURPOSE : This functions returns TRUE if DTMF is allowed in the | |
144 current state, otherwise FALSE. | |
145 | |
146 */ | |
147 | |
148 LOCAL BOOL cc_dtmf_allowed (void) | |
149 { | |
150 GET_INSTANCE_DATA; | |
151 TRACE_FUNCTION ("cc_dtmf_allowed()"); | |
152 | |
153 /* | |
154 * "The mobile station shall be capable of transmitting DTMF messages if | |
155 * and only if the mobile station has the user connection for speech | |
156 * attached and an appropriate channel is available. | |
157 * | |
158 * ".." | |
159 * | |
160 * NOTE 1: This specification means that DTMF messages can generally be | |
161 * sent in the active state of a call in speech transmission | |
162 * mode or when a traffic channel is available during setup or | |
163 * release and the progress indicator IE has been received." | |
164 * | |
165 * [TS 24.008 subclause 5.5.7] | |
166 * | |
167 * As of GSM 04.08 the progress indicator IE can be received by | |
168 * CALL PROCEEDING, PROGRESS, CONNECT, SETUP, ALERTING and DISCONNECT. | |
169 */ | |
170 switch (cc_data->state[cc_data->index_ti]) | |
171 { | |
172 case M_CC_CS_3: /* mobile originating call proceeding */ | |
173 case M_CC_CS_4: /* call delivered */ | |
174 case M_CC_CS_8: /* connect request */ | |
175 case M_CC_CS_11: /* disconnect request */ | |
176 case M_CC_CS_12: /* disconnect indication */ | |
177 case M_CC_CS_19: /* release request */ | |
178 case CS_101: /* substate of CS_10, reestablish requested */ | |
179 case M_CC_CS_26: /* mobile originating modify */ | |
180 case CS_261: /* substate of CS_26, reestablish requested */ | |
181 if (cc_data->progress_desc[cc_data->index_ti] EQ NOT_PRESENT_8BIT) | |
182 return FALSE; /* Progress indicator IE has not been received */ | |
183 /*FALLTHROUGH*/ /*lint -fallthrough*/ | |
184 case M_CC_CS_10: /* active */ | |
185 if (cc_data->channel_type EQ NAS_CH_SDCCH) | |
186 return FALSE; /* No TCH assigned */ | |
187 | |
188 if ((cc_data->channel_mode NEQ NAS_CHM_SPEECH) AND | |
189 (cc_data->channel_mode NEQ NAS_CHM_SPEECH_V2) AND | |
190 (cc_data->channel_mode NEQ NAS_CHM_SPEECH_V3)) | |
191 return FALSE; /* Channel mode is not speech */ | |
192 | |
193 return TRUE; | |
194 | |
195 default: | |
196 return FALSE; | |
197 } | |
198 } | |
199 | |
200 /*==== VARIABLES ==================================================*/ | |
201 | |
202 /*==== FUNCTIONS ==================================================*/ | |
203 | |
204 /* | |
205 +--------------------------------------------------------------------+ | |
206 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
207 | STATE : code ROUTINE : cc_mncc_start_dtmf_req | | |
208 +--------------------------------------------------------------------+ | |
209 | |
210 PURPOSE : Sending of DTMF tones to the infrastructure side. | |
211 | |
212 */ | |
213 | |
214 GLOBAL void cc_mncc_start_dtmf_req (T_MNCC_START_DTMF_REQ * dtmf) | |
215 { | |
216 GET_INSTANCE_DATA; | |
217 T_DTMF * p_dtmf; | |
218 | |
219 TRACE_FUNCTION ("cc_mncc_start_dtmf_req()"); | |
220 | |
221 | |
222 if ((cc_data->index_ti = srv_convert_ti (dtmf->ti)) | |
223 EQ NOT_PRESENT_8BIT) | |
224 { | |
225 PFREE (dtmf); | |
226 return; | |
227 } | |
228 | |
229 switch (cc_data->state[cc_data->index_ti]) | |
230 { | |
231 default: | |
232 if (!cc_dtmf_allowed ()) | |
233 { | |
234 /* Tone dropped. Confirm DTMF request with negative cause */ | |
235 PALLOC (dtmf_cnf, MNCC_START_DTMF_CNF); | |
236 dtmf_cnf->ti = dtmf->ti; | |
237 dtmf_cnf->key = dtmf->key; | |
238 dtmf_cnf->cause = MNCC_CAUSE_DTMF_NOT_ALLOWED; | |
239 dtmf_cnf->dtmf_mod = dtmf->dtmf_mod; | |
240 PSENDX (MMI, dtmf_cnf); | |
241 | |
242 PFREE (dtmf); | |
243 return; | |
244 } | |
245 | |
246 p_dtmf = &cc_data->dtmf [cc_data->index_ti]; | |
247 | |
248 if ( dtmf->dtmf_mod EQ MNCC_DTMF_MOD_AUTO OR | |
249 dtmf->dtmf_mod EQ MNCC_DTMF_MOD_MAN_START ) | |
250 { | |
251 if (p_dtmf->state EQ DTMF_IDLE) | |
252 { | |
253 /* | |
254 * If sending of DTMF tones is not in | |
255 * progress send the tone. | |
256 */ | |
257 CCD_START; | |
258 { | |
259 MCAST (start_dtmf, U_START_DTMF); | |
260 | |
261 cc_build_start_dtmf (dtmf->key, start_dtmf); | |
262 for_start_dtmf (start_dtmf); | |
263 } | |
264 CCD_END; | |
265 | |
266 /* On sending a START DTMF message the MS shall start T336 */ | |
267 TIMERSTART (T336, T336_VALUE); | |
268 | |
269 p_dtmf->state = DTMF_SEND_REQUEST; | |
270 p_dtmf->mode = (dtmf->dtmf_mod EQ MNCC_DTMF_MOD_AUTO)?DTMF_AUTO:DTMF_MAN; | |
271 p_dtmf->key = dtmf->key; | |
272 } | |
273 else | |
274 { | |
275 /* | |
276 * Not DTMF_IDLE. | |
277 */ | |
278 | |
279 if (dtmf->dtmf_mod EQ MNCC_DTMF_MOD_AUTO) | |
280 { | |
281 /* | |
282 * If DTMF_MOD_AUTO, store the tone if the buffer is not full. | |
283 */ | |
284 if (!cc_dtmf_full (p_dtmf)) | |
285 cc_dtmf_write (p_dtmf, (UBYTE)SET_DTMF_MOD(dtmf->key, DTMF_AUTO)); | |
286 // PATCH HM 13.04.00 >>> | |
287 else | |
288 { | |
289 /* Tone dropped. Confirm DTMF request with negative cause */ | |
290 PALLOC (dtmf_cnf, MNCC_START_DTMF_CNF); | |
291 dtmf_cnf->ti = dtmf->ti; | |
292 dtmf_cnf->key = dtmf->key; | |
293 dtmf_cnf->cause = MNCC_CAUSE_DTMF_BUFFER_FULL; | |
294 dtmf_cnf->dtmf_mod = dtmf->dtmf_mod; | |
295 PSENDX(MMI, dtmf_cnf); | |
296 } | |
297 // PATCH HM 13.04.00 <<< | |
298 } | |
299 else | |
300 { | |
301 /* | |
302 * If DTMF_MOD_MAN_START, two conditions have to be fullfilled | |
303 * that the tone is stored and not dropped: | |
304 * | |
305 * - The buffer is not full. | |
306 * - There is enough room to store the stop which | |
307 * will follow the tone. | |
308 */ | |
309 if (!cc_dtmf_full (p_dtmf) AND | |
310 (p_dtmf->read NEQ (p_dtmf->write + 2) % DTMF_BUF_SIZE)) | |
311 { | |
312 cc_dtmf_write (p_dtmf, (UBYTE)SET_DTMF_MOD(dtmf->key, DTMF_MAN)); | |
313 } | |
314 // PATCH HM 13.04.00 >>> | |
315 else | |
316 { | |
317 /* Tone dropped. Confirm DTMF request with negative cause */ | |
318 PALLOC (dtmf_cnf, MNCC_START_DTMF_CNF); | |
319 dtmf_cnf->ti = dtmf->ti; | |
320 dtmf_cnf->key = dtmf->key; | |
321 dtmf_cnf->cause = MNCC_CAUSE_DTMF_BUFFER_FULL; | |
322 dtmf_cnf->dtmf_mod = dtmf->dtmf_mod; | |
323 PSENDX (MMI, dtmf_cnf); | |
324 } | |
325 // PATCH HM 13.04.00 <<< | |
326 } | |
327 } | |
328 } | |
329 else | |
330 { | |
331 /* | |
332 * This is DTMF_MOD_MAN_STOP | |
333 */ | |
334 if ( p_dtmf->state EQ DTMF_SEND_ACKNOWLEDGE AND | |
335 cc_dtmf_empty (p_dtmf)) | |
336 { | |
337 /* | |
338 * If sending of DTMF tones is in | |
339 * progress stop the tone. | |
340 */ | |
341 for_stop_dtmf (); | |
342 | |
343 /* On sending a STOP DTMF message the MS shall start T337 */ | |
344 TIMERSTART (T337, T337_VALUE); | |
345 | |
346 p_dtmf->state = DTMF_STOP_REQUEST; | |
347 } | |
348 else | |
349 { | |
350 /* | |
351 * If DTMF_MOD_MAN_STOP, the stop mark is stored if | |
352 * the buffer is not full. If DTMF STOP ACK is received | |
353 * and there are unexpected stops in the buffer due to | |
354 * a loss of the respective tones, the stops are dropped | |
355 * until a tone is found. | |
356 */ | |
357 if (!cc_dtmf_full(p_dtmf)) | |
358 { | |
359 cc_dtmf_write (p_dtmf, NOT_PRESENT_8BIT); | |
360 } | |
361 } | |
362 } | |
363 PFREE (dtmf) | |
364 break; | |
365 | |
366 case M_CC_CS_26: /* mobile originating modify */ | |
367 case CS_101: | |
368 case CS_261: | |
369 srv_store_prim ((T_PRIM *)D2P(dtmf)); | |
370 break; | |
371 } | |
372 } | |
373 | |
374 | |
375 /* | |
376 +--------------------------------------------------------------------+ | |
377 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
378 | STATE : code ROUTINE : cc_reset_dtmf | | |
379 +--------------------------------------------------------------------+ | |
380 | |
381 PURPOSE : Reset DTMF machine. If used before CC leaves any state in | |
382 which DTMF is possible MMI is informed about DTMF failure | |
383 if there was still a DTMF request outstanding. | |
384 | |
385 */ | |
386 | |
387 GLOBAL void cc_reset_dtmf (void) | |
388 { | |
389 GET_INSTANCE_DATA; | |
390 T_DTMF * p_dtmf; | |
391 BOOL dtmf_aborted; | |
392 | |
393 TRACE_FUNCTION ("cc_reset_dtmf"); | |
394 | |
395 p_dtmf = &cc_data->dtmf[cc_data->index_ti]; | |
396 | |
397 if (cc_dtmf_allowed()) | |
398 { | |
399 /* Stop all possibly running DTMF timers */ | |
400 TIMERSTOP (TIMER_DTMF); | |
401 | |
402 /* | |
403 * A DTMF acknowledge maybe outstanding for ACI either if the | |
404 * DTMF state is DTMF_SEND_REQ or | |
405 * a tone was found in the DTMF send buffer | |
406 */ | |
407 dtmf_aborted = (p_dtmf->state EQ DTMF_SEND_REQUEST); | |
408 while (!dtmf_aborted AND !cc_dtmf_empty(p_dtmf)) | |
409 dtmf_aborted = (cc_dtmf_read (p_dtmf) NEQ NOT_PRESENT_8BIT); | |
410 | |
411 if (dtmf_aborted) | |
412 { | |
413 /* Tone dropped. Confirm DTMF request with negative cause */ | |
414 PALLOC (dtmf_cnf, MNCC_START_DTMF_CNF); | |
415 dtmf_cnf->ti = cc_data->ti; | |
416 dtmf_cnf->key = NOT_PRESENT_8BIT; | |
417 dtmf_cnf->cause = MNCC_CAUSE_DTMF_ABORTED; | |
418 dtmf_cnf->dtmf_mod = NOT_PRESENT_8BIT; | |
419 PSENDX (MMI, dtmf_cnf); | |
420 } | |
421 | |
422 } | |
423 p_dtmf->state = DTMF_IDLE; | |
424 p_dtmf->write = 0; | |
425 p_dtmf->read = 0; | |
426 } | |
427 | |
428 | |
429 /* | |
430 +--------------------------------------------------------------------+ | |
431 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
432 | STATE : code ROUTINE : cc_start_dtmf_ack | | |
433 +--------------------------------------------------------------------+ | |
434 | |
435 PURPOSE : Processing an incoming start dtmf acknowledge message. | |
436 | |
437 */ | |
438 | |
439 GLOBAL void cc_start_dtmf_ack (T_D_START_DTMF_ACK * start_dtmf_ack) | |
440 { | |
441 GET_INSTANCE_DATA; | |
442 T_DTMF * p_dtmf; | |
443 | |
444 TRACE_FUNCTION ("cc_start_dtmf_ack()"); | |
445 | |
446 if (cc_dtmf_allowed ()) | |
447 { | |
448 if (cc_check_error_flag ()) | |
449 { | |
450 p_dtmf = &cc_data->dtmf[cc_data->index_ti]; | |
451 | |
452 /* Stop T336 */ | |
453 TIMERSTOP (TIMER_DTMF); | |
454 | |
455 if (p_dtmf->state EQ DTMF_SEND_REQUEST) | |
456 { | |
457 PALLOC (start, MNCC_START_DTMF_CNF); | |
458 | |
459 start->ti = cc_data->ti; | |
460 start->key = start_dtmf_ack->key_facility.key; | |
461 start->cause = MNCC_CAUSE_DTMF_START_SUCCESS; | |
462 start->dtmf_mod = (p_dtmf->mode EQ DTMF_AUTO) ? | |
463 MNCC_DTMF_MOD_AUTO : MNCC_DTMF_MOD_MAN_START; | |
464 PSENDX (MMI, start); | |
465 | |
466 EM_CC_START_DTMF_ACKNOWLEDGE; | |
467 | |
468 if( p_dtmf->mode EQ DTMF_AUTO ) | |
469 { | |
470 for_stop_dtmf (); | |
471 | |
472 /* On sending a STOP DTMF message the MS shall start T337 */ | |
473 TIMERSTART (T337, T337_VALUE); | |
474 | |
475 p_dtmf->state = DTMF_STOP_REQUEST; | |
476 } | |
477 else | |
478 { | |
479 /* This is DTMF_MAN */ | |
480 if (!cc_dtmf_empty (p_dtmf)) | |
481 { | |
482 UBYTE tone; | |
483 | |
484 tone = cc_dtmf_read (p_dtmf); | |
485 if (tone EQ NOT_PRESENT_8BIT) | |
486 { | |
487 /* Should be always true */ | |
488 p_dtmf->mode = GET_DTMF_MOD(tone); | |
489 for_stop_dtmf (); | |
490 | |
491 /* On sending a STOP DTMF message the MS shall start T337 */ | |
492 TIMERSTART (T337, T337_VALUE); | |
493 | |
494 p_dtmf->state = DTMF_STOP_REQUEST; | |
495 } | |
496 while (!cc_dtmf_empty(p_dtmf) AND | |
497 p_dtmf->buf[p_dtmf->read] EQ NOT_PRESENT_8BIT) | |
498 { | |
499 /* Consume all unwanted stop marks */ | |
500 (void)cc_dtmf_read(p_dtmf); | |
501 } | |
502 } | |
503 else | |
504 p_dtmf->state = DTMF_SEND_ACKNOWLEDGE; | |
505 } | |
506 /* Implements Measure# 3 and streamline encoding */ | |
507 CCD_END; | |
508 } | |
509 else | |
510 { | |
511 | |
512 /* Implements Measure# 3 and streamline encoding */ | |
513 CCD_END; | |
514 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
515 } | |
516 /* Implements Measure# 3 and streamline encoding */ | |
517 } /* if (cc_check_error_flag (cc_data)) */ | |
518 } /* if (cc_dtmf_allowed (cc_data)) */ | |
519 else | |
520 { | |
521 /* | |
522 * DTMF not allowed for some reason, e.g. wrong state, | |
523 * call is not a speech call, no TCH assigned etc. | |
524 */ | |
525 CCD_END; | |
526 /* Implements Measure# 3 and streamline encoding */ | |
527 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
528 } | |
529 } | |
530 | |
531 | |
532 /* | |
533 +--------------------------------------------------------------------+ | |
534 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
535 | STATE : code ROUTINE : cc_start_dtmf_rej | | |
536 +--------------------------------------------------------------------+ | |
537 | |
538 PURPOSE : Processing an incoming start dtmf reject message. | |
539 | |
540 */ | |
541 | |
542 GLOBAL void cc_start_dtmf_rej (T_D_START_DTMF_REJ * start_dtmf_rej) | |
543 { | |
544 GET_INSTANCE_DATA; | |
545 T_DTMF * p_dtmf; | |
546 | |
547 TRACE_FUNCTION ("cc_start_dtmf_rej()"); | |
548 | |
549 if (cc_dtmf_allowed ()) | |
550 { | |
551 if (cc_check_error_flag ()) | |
552 { | |
553 /* Stop T336 */ | |
554 TIMERSTOP (TIMER_DTMF); | |
555 p_dtmf = &cc_data->dtmf[cc_data->index_ti]; | |
556 if (p_dtmf->state EQ DTMF_SEND_REQUEST) | |
557 { | |
558 PALLOC (start, MNCC_START_DTMF_CNF); | |
559 | |
560 start->ti = cc_data->ti; | |
561 start->key = NOT_PRESENT_8BIT; | |
562 start->dtmf_mod = NOT_PRESENT_8BIT; | |
563 /* | |
564 * cause IE is mandatory and the check for presence has been done already | |
565 * thus there is no need to check for validity of cause IE here anymore | |
566 */ | |
567 start->cause = CAUSE_MAKE(DEFBY_STD, | |
568 ORIGSIDE_NET, | |
569 MNCC_CC_ORIGINATING_ENTITY, | |
570 start_dtmf_rej->cc_cause.cause); | |
571 PSENDX (MMI, start); | |
572 | |
573 p_dtmf->state = DTMF_IDLE; | |
574 p_dtmf->write = 0; | |
575 p_dtmf->read = 0; | |
576 /* Implements Measure# 3 and streamline encoding */ | |
577 CCD_END; | |
578 } | |
579 else | |
580 { | |
581 /* Implements Measure# 3 and streamline encoding */ | |
582 CCD_END; | |
583 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
584 } | |
585 /* Implements Measure# 3 and streamline encoding */ | |
586 } | |
587 } | |
588 else | |
589 { | |
590 /* | |
591 * DTMF not allowed for some reason, e.g. wrong state, | |
592 * call is not a speech call, no TCH assigned etc. | |
593 */ | |
594 CCD_END; | |
595 /* Implements Measure# 3 and streamline encoding */ | |
596 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
597 } | |
598 } | |
599 | |
600 | |
601 /* | |
602 +--------------------------------------------------------------------+ | |
603 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
604 | STATE : code ROUTINE : cc_stop_dtmf | | |
605 +--------------------------------------------------------------------+ | |
606 | |
607 PURPOSE : Stops DTMF, back to DTMF_IDLE state. | |
608 Reasons for call: | |
609 1.) Reception of STOP DTMF ACK message | |
610 2.) Expiry of T336 | |
611 3.) Expiry of T337 | |
612 | |
613 */ | |
614 | |
615 GLOBAL void cc_stop_dtmf (void) | |
616 { | |
617 GET_INSTANCE_DATA; | |
618 T_DTMF * p_dtmf; | |
619 | |
620 TRACE_FUNCTION ("cc_stop_dtmf()"); | |
621 | |
622 p_dtmf = &cc_data->dtmf[cc_data->index_ti]; | |
623 | |
624 while (!cc_dtmf_empty(p_dtmf)) | |
625 { | |
626 UBYTE tone; | |
627 | |
628 tone = cc_dtmf_read (p_dtmf); | |
629 if (tone NEQ NOT_PRESENT_8BIT) | |
630 { | |
631 /* | |
632 * another DTMF tone has to be sent | |
633 */ | |
634 p_dtmf->mode = GET_DTMF_MOD (tone); | |
635 p_dtmf->key = tone & 0x7f; | |
636 CCD_START; | |
637 { | |
638 MCAST (start, U_START_DTMF); | |
639 | |
640 cc_build_start_dtmf (p_dtmf->key, start); | |
641 for_start_dtmf (start); | |
642 } | |
643 CCD_END; | |
644 | |
645 /* On sending a START DTMF message the MS shall start T336 */ | |
646 TIMERSTART (T336, T336_VALUE); | |
647 | |
648 p_dtmf->state = DTMF_SEND_REQUEST; | |
649 return; | |
650 } | |
651 } | |
652 p_dtmf->state = DTMF_IDLE; | |
653 srv_use_stored_prim (); | |
654 } | |
655 | |
656 | |
657 /* | |
658 +--------------------------------------------------------------------+ | |
659 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
660 | STATE : code ROUTINE : cc_stop_dtmf_ack | | |
661 +--------------------------------------------------------------------+ | |
662 | |
663 PURPOSE : Processing an incoming stop dtmf ack message. | |
664 | |
665 */ | |
666 | |
667 GLOBAL void cc_stop_dtmf_ack (void) | |
668 { | |
669 GET_INSTANCE_DATA; | |
670 T_DTMF * p_dtmf; | |
671 | |
672 TRACE_FUNCTION ("cc_stop_dtmf_ack()"); | |
673 | |
674 if (cc_dtmf_allowed ()) | |
675 { | |
676 if (cc_check_error_flag ()) | |
677 { | |
678 CCD_END; | |
679 p_dtmf = &cc_data->dtmf[cc_data->index_ti]; | |
680 if (p_dtmf->state EQ DTMF_STOP_REQUEST) | |
681 { | |
682 if (p_dtmf->mode EQ DTMF_MAN) | |
683 { | |
684 PALLOC (start, MNCC_START_DTMF_CNF); | |
685 start->ti = cc_data->ti; | |
686 start->key = NOT_PRESENT_8BIT; | |
687 start->cause = MNCC_CAUSE_DTMF_STOP_SUCCESS; | |
688 start->dtmf_mod = MNCC_DTMF_MOD_MAN_STOP; | |
689 PSENDX (MMI, start); | |
690 } | |
691 /* Stop T337 */ | |
692 TIMERSTOP (TIMER_DTMF); | |
693 cc_stop_dtmf (); | |
694 } | |
695 else | |
696 { | |
697 /* | |
698 * The STOP DTMF ACK message was not expected as we did not sent | |
699 * previously a START DTMF request. | |
700 */ | |
701 /* Implements Measure# 3 and streamline encoding */ | |
702 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
703 } | |
704 } | |
705 } | |
706 else | |
707 { | |
708 /* | |
709 * DTMF not allowed in the current state | |
710 */ | |
711 CCD_END; | |
712 /* Implements Measure# 3 and streamline encoding */ | |
713 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
714 } | |
715 } | |
716 | |
717 | |
718 /* | |
719 +--------------------------------------------------------------------+ | |
720 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
721 | STATE : code ROUTINE : cc_mncc_facility_req | | |
722 +--------------------------------------------------------------------+ | |
723 | |
724 PURPOSE : Sending of Facility Information by the mobile side. | |
725 | |
726 */ | |
727 | |
728 GLOBAL void cc_mncc_facility_req (T_MNCC_FACILITY_REQ * facility) | |
729 { | |
730 GET_INSTANCE_DATA; | |
731 | |
732 TRACE_FUNCTION ("cc_mncc_facility_req()"); | |
733 | |
734 if ((cc_data->index_ti = srv_convert_ti (facility->ti)) | |
735 EQ NOT_PRESENT_8BIT) | |
736 { | |
737 PFREE (facility); | |
738 return; | |
739 } | |
740 | |
741 switch (cc_data->state[cc_data->index_ti]) | |
742 { | |
743 case M_CC_CS_19: | |
744 PFREE (facility); | |
745 break; | |
746 | |
747 case M_CC_CS_01: | |
748 case CS_101: | |
749 case CS_261: | |
750 srv_store_prim ((T_PRIM *)D2P(facility)); | |
751 break; | |
752 | |
753 default: | |
754 CCD_START; | |
755 { | |
756 MCAST (facility_msg, U_FACILITY); | |
757 cc_build_facility (facility, facility_msg); | |
758 for_facility (facility_msg); | |
759 | |
760 EM_CC_FACILITY_TO_THE_NETWORK; | |
761 | |
762 } | |
763 CCD_END; | |
764 PFREE (facility); | |
765 break; | |
766 } | |
767 } | |
768 | |
769 | |
770 /* | |
771 +--------------------------------------------------------------------+ | |
772 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
773 | STATE : code ROUTINE : cc_mncc_modify_req | | |
774 +--------------------------------------------------------------------+ | |
775 | |
776 PURPOSE : Start of a mobile originated in-call modification. | |
777 | |
778 */ | |
779 | |
780 GLOBAL void cc_mncc_modify_req (T_MNCC_MODIFY_REQ * modify) | |
781 { | |
782 GET_INSTANCE_DATA; | |
783 | |
784 TRACE_FUNCTION ("cc_mncc_modify_req()"); | |
785 | |
786 if ((cc_data->index_ti = srv_convert_ti (modify->ti)) | |
787 EQ NOT_PRESENT_8BIT) | |
788 { | |
789 PFREE (modify); | |
790 return; | |
791 } | |
792 | |
793 switch (cc_data->state[cc_data->index_ti]) | |
794 { | |
795 case M_CC_CS_10: | |
796 if (((cc_data->hold_state[cc_data->index_ti] EQ M_CC_HLD_IDLE)) AND | |
797 (cc_data->dtmf[cc_data->index_ti].state EQ DTMF_IDLE)) | |
798 { | |
799 /* | |
800 * If no other procedure is running | |
801 */ | |
802 CCD_START; | |
803 { | |
804 MCAST (modify_msg, B_MODIFY); | |
805 cc_build_modify (modify, modify_msg); | |
806 for_modify (modify_msg); | |
807 } | |
808 CCD_END; | |
809 PFREE (modify); | |
810 cc_set_state (M_CC_CS_26); | |
811 TIMERSTART (T323, T323_VALUE); | |
812 | |
813 EM_CC_MO_IN_CALL_MODIFICATION; | |
814 | |
815 } | |
816 else | |
817 srv_store_prim ((T_PRIM *)D2P(modify)); | |
818 break; | |
819 | |
820 default: | |
821 PFREE (modify); | |
822 break; | |
823 } | |
824 } | |
825 | |
826 | |
827 /* | |
828 +--------------------------------------------------------------------+ | |
829 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
830 | STATE : code ROUTINE : cc_mncc_user_req | | |
831 +--------------------------------------------------------------------+ | |
832 | |
833 PURPOSE : Send user information or congestion control. | |
834 | |
835 */ | |
836 | |
837 GLOBAL void cc_mncc_user_req (T_MNCC_USER_REQ * user) | |
838 { | |
839 GET_INSTANCE_DATA; | |
840 | |
841 TRACE_FUNCTION ("cc_mncc_user_req()"); | |
842 | |
843 if ((cc_data->index_ti = srv_convert_ti (user->ti)) | |
844 EQ NOT_PRESENT_8BIT) | |
845 { | |
846 PFREE (user); | |
847 return; | |
848 } | |
849 | |
850 switch (cc_data->state[cc_data->index_ti]) | |
851 { | |
852 case M_CC_CS_10: | |
853 switch (user->congest_lev) | |
854 { | |
855 case M_CC_CL_RECEIVER_READY: | |
856 case M_CC_CL_RECEIVER_NOT_READY: | |
857 /* | |
858 * Send Congestion Control | |
859 */ | |
860 CCD_START; | |
861 { | |
862 MCAST (cong_ctrl, B_CONGEST_CTRL); | |
863 | |
864 cc_build_congestion_control (user, cong_ctrl); | |
865 for_congestion_control (cong_ctrl); | |
866 } | |
867 CCD_END; | |
868 PFREE (user); | |
869 break; | |
870 default: | |
871 /* | |
872 * Send User Information | |
873 */ | |
874 CCD_START; | |
875 { | |
876 MCAST (user_msg, B_USER_INFO); | |
877 | |
878 cc_build_user_information (user, user_msg); | |
879 for_user_information (user_msg); | |
880 } | |
881 CCD_END; | |
882 PFREE (user); | |
883 break; | |
884 } | |
885 break; | |
886 | |
887 case CS_101: | |
888 srv_store_prim ((T_PRIM *)D2P(user)); | |
889 break; | |
890 | |
891 default: | |
892 PFREE (user); | |
893 break; | |
894 } | |
895 } | |
896 | |
897 | |
898 /* | |
899 +--------------------------------------------------------------------+ | |
900 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
901 | STATE : code ROUTINE : cc_mncc_hold_req | | |
902 +--------------------------------------------------------------------+ | |
903 | |
904 PURPOSE : Send hold message. | |
905 | |
906 */ | |
907 | |
908 GLOBAL void cc_mncc_hold_req (T_MNCC_HOLD_REQ * hold) | |
909 { | |
910 | |
911 TRACE_FUNCTION ("cc_mncc_hold_req()"); | |
912 | |
913 /* Implements Measure# 18 */ | |
914 cc_mncc_hold_retrieve_req ((T_PRIM *)D2P(hold)); | |
915 } | |
916 | |
917 | |
918 /* | |
919 +--------------------------------------------------------------------+ | |
920 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
921 | STATE : code ROUTINE : cc_mncc_retrieve_req | | |
922 +--------------------------------------------------------------------+ | |
923 | |
924 PURPOSE : Send retrieve message. | |
925 | |
926 */ | |
927 GLOBAL void cc_mncc_retrieve_req (T_MNCC_RETRIEVE_REQ * retrieve) | |
928 { | |
929 | |
930 TRACE_FUNCTION ("cc_mncc_retrieve_req()"); | |
931 | |
932 /* Implements Measure# 18 */ | |
933 cc_mncc_hold_retrieve_req ((T_PRIM *)D2P(retrieve)); | |
934 } | |
935 | |
936 | |
937 /* | |
938 +--------------------------------------------------------------------+ | |
939 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
940 | STATE : code ROUTINE : cc_call_is_active | | |
941 +--------------------------------------------------------------------+ | |
942 | |
943 PURPOSE : Return TRUE if the respective CC instance is in an active | |
944 state, otherwise return FALSE. | |
945 | |
946 */ | |
947 | |
948 LOCAL BOOL cc_call_is_active (UBYTE index_ti) | |
949 { | |
950 GET_INSTANCE_DATA; | |
951 TRACE_FUNCTION ("cc_call_is_active()"); | |
952 | |
953 switch (cc_data->state[index_ti]) | |
954 { | |
955 case M_CC_CS_10: | |
956 case M_CC_CS_26: | |
957 case CS_101: | |
958 case CS_261: | |
959 return TRUE; | |
960 | |
961 default: | |
962 return FALSE; | |
963 } | |
964 } | |
965 | |
966 | |
967 /* | |
968 +--------------------------------------------------------------------+ | |
969 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
970 | STATE : code ROUTINE : cc_mncc_sync_req | | |
971 +--------------------------------------------------------------------+ | |
972 | |
973 PURPOSE : Processing a MNCC_SYNC_REQ primitive. To be able to | |
974 understand some details of this function, see first | |
975 GSM 03.84, GSM 04.84 and GSM 11.10 chapters 31.4.1 and 31.4.2. | |
976 | |
977 */ | |
978 | |
979 GLOBAL void cc_mncc_sync_req (T_MNCC_SYNC_REQ * mncc_sync_req) | |
980 { | |
981 GET_INSTANCE_DATA; | |
982 UBYTE i; | |
983 | |
984 TRACE_FUNCTION ("cc_mncc_sync_req()"); | |
985 | |
986 if ((cc_data->index_ti = srv_convert_ti (mncc_sync_req->ti)) | |
987 EQ NOT_PRESENT_8BIT) | |
988 { | |
989 PFREE (mncc_sync_req); | |
990 return; | |
991 } | |
992 | |
993 switch (cc_data->state[cc_data->index_ti]) | |
994 { | |
995 /* | |
996 * Note: MPTY and HOLD only has a meaning in the following states, | |
997 * in other states these aux states have absolutely no meaning. | |
998 */ | |
999 case M_CC_CS_10: | |
1000 case M_CC_CS_26: | |
1001 case CS_101: | |
1002 case CS_261: | |
1003 switch (mncc_sync_req->synccs) | |
1004 { | |
1005 case MNCC_SYNCCS_MPTY_EVENT: | |
1006 | |
1007 TRACE_EVENT_P2 (" ti = %d, mpty_event = %d", | |
1008 mncc_sync_req->ti, | |
1009 mncc_sync_req->mpty_event); | |
1010 | |
1011 switch (mncc_sync_req->mpty_event) | |
1012 { | |
1013 case MNCC_MPTY_BUILD_SENT: | |
1014 for (i = 0; i < MAX_CC_CALLS; i++) | |
1015 { | |
1016 if (cc_call_is_active(i) AND | |
1017 cc_data->mpty_state[i] EQ M_CC_MPTY_IDLE) | |
1018 { | |
1019 cc_data->mpty_state[i] = M_CC_MPTY_REQ; | |
1020 } | |
1021 } | |
1022 break; | |
1023 | |
1024 case MNCC_MPTY_BUILD_FAIL: | |
1025 for (i = 0; i < MAX_CC_CALLS; i++) | |
1026 { | |
1027 if (cc_call_is_active(i) AND | |
1028 cc_data->mpty_state[i] EQ M_CC_MPTY_REQ) | |
1029 { | |
1030 cc_data->mpty_state[i] = M_CC_MPTY_IDLE; | |
1031 } | |
1032 } | |
1033 break; | |
1034 | |
1035 case MNCC_MPTY_BUILD_SUCCESS: | |
1036 for (i = 0; i < MAX_CC_CALLS; i++) | |
1037 { | |
1038 if (cc_call_is_active(i)) | |
1039 { | |
1040 cc_data->mpty_state[i] = M_CC_MPTY_CALL; | |
1041 cc_data->hold_state[i] = M_CC_HLD_IDLE; | |
1042 } | |
1043 } | |
1044 break; | |
1045 | |
1046 /* -- */ | |
1047 | |
1048 case MNCC_MPTY_SPLIT_SENT: | |
1049 if (cc_data->mpty_state[cc_data->index_ti] EQ M_CC_MPTY_CALL) | |
1050 { | |
1051 cc_data->mpty_state[cc_data->index_ti] = M_CC_MPTY_SPLIT; | |
1052 } | |
1053 break; | |
1054 | |
1055 case MNCC_MPTY_SPLIT_FAIL: | |
1056 if (cc_data->mpty_state[cc_data->index_ti] EQ M_CC_MPTY_SPLIT) | |
1057 { | |
1058 cc_data->mpty_state[cc_data->index_ti] = M_CC_MPTY_CALL; | |
1059 } | |
1060 break; | |
1061 | |
1062 case MNCC_MPTY_SPLIT_SUCCESS: | |
1063 cc_data->mpty_state[cc_data->index_ti] = M_CC_MPTY_IDLE; | |
1064 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_IDLE; | |
1065 for (i = 0; i < MAX_CC_CALLS; i++) | |
1066 { | |
1067 if (cc_call_is_active(i) AND | |
1068 cc_data->mpty_state[i] NEQ M_CC_MPTY_IDLE) | |
1069 { | |
1070 cc_data->hold_state[i] = M_CC_HLD_CALL_HELD; | |
1071 } | |
1072 } | |
1073 break; | |
1074 | |
1075 /* -- */ | |
1076 | |
1077 case MNCC_MPTY_HOLD_SENT: | |
1078 for (i = 0; i < MAX_CC_CALLS; i++) | |
1079 { | |
1080 if (cc_call_is_active(i) AND | |
1081 cc_data->mpty_state[i] NEQ M_CC_MPTY_IDLE) | |
1082 { | |
1083 cc_data->hold_state[i] = M_CC_HLD_HOLD_REQ; | |
1084 } | |
1085 } | |
1086 break; | |
1087 | |
1088 case MNCC_MPTY_HOLD_FAIL: | |
1089 for (i = 0; i < MAX_CC_CALLS; i++) | |
1090 { | |
1091 if (cc_call_is_active(i) AND | |
1092 cc_data->mpty_state[i] NEQ M_CC_MPTY_IDLE) | |
1093 { | |
1094 cc_data->hold_state[i] = M_CC_HLD_IDLE; | |
1095 } | |
1096 } | |
1097 break; | |
1098 | |
1099 case MNCC_MPTY_HOLD_SUCCESS: | |
1100 for (i = 0; i < MAX_CC_CALLS; i++) | |
1101 { | |
1102 if (cc_call_is_active(i) AND | |
1103 cc_data->mpty_state[i] NEQ M_CC_MPTY_IDLE) | |
1104 { | |
1105 cc_data->hold_state[i] = M_CC_HLD_CALL_HELD; | |
1106 } | |
1107 } | |
1108 break; | |
1109 | |
1110 /* -- */ | |
1111 | |
1112 case MNCC_MPTY_RETRIEVE_SENT: | |
1113 for (i = 0; i < MAX_CC_CALLS; i++) | |
1114 { | |
1115 if (cc_call_is_active(i) AND | |
1116 cc_data->mpty_state[i] NEQ M_CC_MPTY_IDLE) | |
1117 { | |
1118 cc_data->hold_state[i] = M_CC_HLD_RETRIEVE_REQ; | |
1119 } | |
1120 } | |
1121 break; | |
1122 | |
1123 case MNCC_MPTY_RETRIEVE_FAIL: | |
1124 for (i = 0; i < MAX_CC_CALLS; i++) | |
1125 { | |
1126 if (cc_call_is_active(i) AND | |
1127 cc_data->mpty_state[i] NEQ M_CC_MPTY_IDLE) | |
1128 { | |
1129 cc_data->hold_state[i] = M_CC_HLD_CALL_HELD; | |
1130 } | |
1131 } | |
1132 break; | |
1133 | |
1134 case MNCC_MPTY_RETRIEVE_SUCCESS: | |
1135 for (i = 0; i < MAX_CC_CALLS; i++) | |
1136 { | |
1137 if (cc_call_is_active(i) AND | |
1138 cc_data->mpty_state[i] NEQ M_CC_MPTY_IDLE) | |
1139 { | |
1140 cc_data->hold_state[i] = M_CC_HLD_IDLE; | |
1141 } | |
1142 } | |
1143 break; | |
1144 | |
1145 /* -- */ | |
1146 | |
1147 default: | |
1148 TRACE_ERROR ("Illegal MPTY event"); | |
1149 break; | |
1150 } /* switch (mncc_sync_req->mpty_event) */ | |
1151 break; | |
1152 | |
1153 default: | |
1154 TRACE_ERROR ("Illegal SYNCCS"); | |
1155 } /* switch (mncc_sync_req->synccs) */ | |
1156 break; | |
1157 | |
1158 default: | |
1159 break; /* Ignore the event */ | |
1160 } /* switch (cc_data->state[cc_data->index_ti]) */ | |
1161 | |
1162 #ifndef NTRACE | |
1163 for (i = 0; i < MAX_CC_CALLS; i++) | |
1164 { | |
1165 if (cc_call_is_active(i)) | |
1166 { | |
1167 TRACE_EVENT_P4 (" hold[%d] = %d, mpty[%d] = %d", | |
1168 cc_data->stored_ti_values[i], | |
1169 cc_data->hold_state[i], | |
1170 cc_data->stored_ti_values[i], | |
1171 cc_data->mpty_state[i]); | |
1172 } | |
1173 } | |
1174 #endif /* #ifndef NTRACE */ | |
1175 | |
1176 PFREE (mncc_sync_req); | |
1177 } | |
1178 | |
1179 | |
1180 /* | |
1181 +--------------------------------------------------------------------+ | |
1182 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1183 | STATE : code ROUTINE : cc_mncc_status_res | | |
1184 +--------------------------------------------------------------------+ | |
1185 | |
1186 PURPOSE : Processing a MNCC_STATUS_RES primitive. There is an | |
1187 outstanding STATUS message which still has to be sent to | |
1188 the network after having received a STATUS ENQUIRY in U10. | |
1189 | |
1190 */ | |
1191 | |
1192 GLOBAL void cc_mncc_status_res (T_MNCC_STATUS_RES * mncc_status_res) | |
1193 { | |
1194 GET_INSTANCE_DATA; | |
1195 | |
1196 TRACE_FUNCTION ("cc_mncc_status_res()"); | |
1197 | |
1198 if ((cc_data->index_ti = srv_convert_ti (mncc_status_res->ti)) | |
1199 EQ NOT_PRESENT_8BIT) | |
1200 { | |
1201 PFREE (mncc_status_res); | |
1202 return; | |
1203 } | |
1204 | |
1205 switch (cc_data->state[cc_data->index_ti]) | |
1206 { | |
1207 case M_CC_CS_01: /* MM connection pending */ | |
1208 case CS_101: /* No network connection, reestablishment in progress */ | |
1209 case CS_261: | |
1210 break; | |
1211 | |
1212 default: | |
1213 /* Implements Measure# 3 and streamline encoding */ | |
1214 cc_send_status (M_CC_CAUSE_STATUS_ENQUIRY); | |
1215 break; | |
1216 } | |
1217 | |
1218 PFREE (mncc_status_res); | |
1219 } | |
1220 | |
1221 | |
1222 /* | |
1223 +--------------------------------------------------------------------+ | |
1224 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1225 | STATE : code ROUTINE : cc_facility | | |
1226 +--------------------------------------------------------------------+ | |
1227 | |
1228 PURPOSE : Processing of an incoming facility message. | |
1229 | |
1230 */ | |
1231 | |
1232 GLOBAL void cc_facility (T_D_FACILITY * facility) | |
1233 { | |
1234 GET_INSTANCE_DATA; | |
1235 TRACE_FUNCTION ("cc_facility()"); | |
1236 | |
1237 /* | |
1238 * A facility message can be received in every state where CC has a | |
1239 * MM connection, no need to check states here. | |
1240 */ | |
1241 if (cc_check_error_flag ()) | |
1242 { | |
1243 cc_build_facility_ind (MNCC_FAC_IN_FACILITY, TRUE, &facility->facility); | |
1244 CCD_END; | |
1245 } | |
1246 | |
1247 EM_CC_FACILITY_FROM_THE_NETWORK; | |
1248 | |
1249 } | |
1250 | |
1251 | |
1252 /* | |
1253 +--------------------------------------------------------------------+ | |
1254 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1255 | STATE : code ROUTINE : cc_hold_ack | | |
1256 +--------------------------------------------------------------------+ | |
1257 | |
1258 PURPOSE : Processing an incoming hold ack message. | |
1259 | |
1260 */ | |
1261 | |
1262 GLOBAL void cc_hold_ack (void) | |
1263 { | |
1264 GET_INSTANCE_DATA; | |
1265 CCD_END; | |
1266 | |
1267 TRACE_FUNCTION ("cc_hold_ack()"); | |
1268 | |
1269 switch (cc_data->state[cc_data->index_ti]) | |
1270 { | |
1271 /* | |
1272 * CS_0 is handled by the formatter | |
1273 */ | |
1274 case M_CC_CS_10: | |
1275 if (cc_check_error_flag ()) | |
1276 { | |
1277 if (cc_data->hold_state[cc_data->index_ti] EQ M_CC_HLD_HOLD_REQ) | |
1278 { | |
1279 PALLOC (hold_cnf, MNCC_HOLD_CNF); | |
1280 | |
1281 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_CALL_HELD; | |
1282 hold_cnf->ti = cc_data->ti; | |
1283 hold_cnf->cause = MNCC_CAUSE_HOLD_SUCCESS; | |
1284 PSENDX (MMI, hold_cnf); | |
1285 | |
1286 EM_CC_CALL_HOLD_ACKNOWLEDGE; | |
1287 | |
1288 } | |
1289 else | |
1290 { | |
1291 /* Implements Measure# 3 and streamline encoding */ | |
1292 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1293 } | |
1294 } | |
1295 break; | |
1296 | |
1297 default: | |
1298 /* Implements Measure# 3 and streamline encoding */ | |
1299 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1300 break; | |
1301 } | |
1302 } | |
1303 | |
1304 /* | |
1305 +--------------------------------------------------------------------+ | |
1306 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1307 | STATE : code ROUTINE : cc_hold_rej | | |
1308 +--------------------------------------------------------------------+ | |
1309 | |
1310 PURPOSE : Processing an incoming hold rej message. | |
1311 | |
1312 */ | |
1313 | |
1314 GLOBAL void cc_hold_rej (T_D_HOLD_REJ * hold_rej) | |
1315 { | |
1316 GET_INSTANCE_DATA; | |
1317 TRACE_FUNCTION ("cc_hold_rej()"); | |
1318 | |
1319 switch (cc_data->state[cc_data->index_ti]) | |
1320 { | |
1321 /* | |
1322 * CS_0 is handled by the formatter | |
1323 */ | |
1324 case M_CC_CS_10: | |
1325 if (cc_data->hold_state[cc_data->index_ti] EQ M_CC_HLD_HOLD_REQ) | |
1326 { | |
1327 PALLOC (hold_cnf, MNCC_HOLD_CNF); | |
1328 | |
1329 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_IDLE; | |
1330 hold_cnf->ti = cc_data->ti; | |
1331 | |
1332 /* | |
1333 * It is possible for the network to send a REJ without a Cause IE. | |
1334 * This causes the decoder to flag a Madatory IE error. According to | |
1335 * 04.08 Sec: 8.5.3.e, the REJ should still be managed as if a correctly | |
1336 * formatted REJ had been received. | |
1337 */ | |
1338 if (!hold_rej->cc_cause.v_cause) | |
1339 { | |
1340 hold_cnf->cause = MNCC_CAUSE_NO_NET_CAUSE; | |
1341 } | |
1342 else | |
1343 { | |
1344 hold_cnf->cause = CAUSE_MAKE(DEFBY_STD, | |
1345 ORIGSIDE_NET, | |
1346 MNCC_CC_ORIGINATING_ENTITY, | |
1347 hold_rej->cc_cause.cause); | |
1348 } | |
1349 PSENDX (MMI, hold_cnf); | |
1350 srv_use_stored_prim (); | |
1351 | |
1352 EM_CC_CALL_HOLD_REJECT; | |
1353 | |
1354 CCD_END; | |
1355 } | |
1356 else | |
1357 { | |
1358 CCD_END; | |
1359 /* Implements Measure# 3 and streamline encoding */ | |
1360 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1361 } | |
1362 break; | |
1363 | |
1364 default: | |
1365 CCD_END; | |
1366 /* Implements Measure# 3 and streamline encoding */ | |
1367 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1368 break; | |
1369 } | |
1370 } | |
1371 | |
1372 /* | |
1373 +--------------------------------------------------------------------+ | |
1374 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1375 | STATE : code ROUTINE : cc_retrieve_ack | | |
1376 +--------------------------------------------------------------------+ | |
1377 | |
1378 PURPOSE : Processing an incoming retrieve ack message. | |
1379 | |
1380 */ | |
1381 | |
1382 GLOBAL void cc_retrieve_ack (void) | |
1383 { | |
1384 GET_INSTANCE_DATA; | |
1385 | |
1386 TRACE_FUNCTION ("cc_retrieve_ack()"); | |
1387 | |
1388 switch (cc_data->state[cc_data->index_ti]) | |
1389 { | |
1390 /* | |
1391 * CS_0 is handled by the formatter | |
1392 */ | |
1393 case M_CC_CS_10: | |
1394 if (cc_check_error_flag ()) | |
1395 { | |
1396 CCD_END; | |
1397 if (cc_data->hold_state[cc_data->index_ti] EQ M_CC_HLD_RETRIEVE_REQ) | |
1398 { | |
1399 PALLOC (retrieve_cnf, MNCC_RETRIEVE_CNF); | |
1400 | |
1401 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_IDLE; | |
1402 retrieve_cnf->ti = cc_data->ti; | |
1403 retrieve_cnf->cause = MNCC_CAUSE_RETRIEVE_SUCCESS; | |
1404 PSENDX (MMI, retrieve_cnf); | |
1405 | |
1406 EM_CC_CALL_RETRIEVE_ACKNOWLEDGE; | |
1407 | |
1408 } | |
1409 else | |
1410 { | |
1411 /* Implements Measure# 3 and streamline encoding */ | |
1412 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1413 } | |
1414 } | |
1415 break; | |
1416 | |
1417 default: | |
1418 CCD_END; | |
1419 /* Implements Measure# 3 and streamline encoding */ | |
1420 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1421 break; | |
1422 } | |
1423 } | |
1424 | |
1425 /* | |
1426 +--------------------------------------------------------------------+ | |
1427 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1428 | STATE : code ROUTINE : cc_retrieve_rej | | |
1429 +--------------------------------------------------------------------+ | |
1430 | |
1431 PURPOSE : Processing an incoming retrieve rej message. | |
1432 | |
1433 */ | |
1434 | |
1435 GLOBAL void cc_retrieve_rej (T_D_RETRIEVE_REJ * retrieve_rej) | |
1436 { | |
1437 GET_INSTANCE_DATA; | |
1438 TRACE_FUNCTION ("cc_retrieve_rej()"); | |
1439 | |
1440 switch (cc_data->state[cc_data->index_ti]) | |
1441 { | |
1442 /* | |
1443 * CS_0 is handled by the formatter | |
1444 */ | |
1445 case M_CC_CS_10: | |
1446 if (cc_data->hold_state[cc_data->index_ti] EQ M_CC_HLD_RETRIEVE_REQ) | |
1447 { | |
1448 PALLOC (retrieve_cnf, MNCC_RETRIEVE_CNF); | |
1449 | |
1450 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_CALL_HELD; | |
1451 retrieve_cnf->ti = cc_data->ti; | |
1452 | |
1453 /* | |
1454 * It is possible for the network to send a REJ without a Cause IE. | |
1455 * This causes the decoder to flag a Madatory IE error. According to | |
1456 * 04.08 Sec: 8.5.3.e, the REJ should still be managed as if a correctly | |
1457 * formatted REJ had been received. | |
1458 */ | |
1459 if (!retrieve_rej->cc_cause.v_cause) | |
1460 { | |
1461 retrieve_cnf->cause = MNCC_CAUSE_NO_NET_CAUSE; | |
1462 } | |
1463 else | |
1464 { | |
1465 retrieve_cnf->cause = CAUSE_MAKE(DEFBY_STD, | |
1466 ORIGSIDE_NET, | |
1467 MNCC_CC_ORIGINATING_ENTITY, | |
1468 retrieve_rej->cc_cause.cause); | |
1469 } | |
1470 PSENDX (MMI, retrieve_cnf); | |
1471 srv_use_stored_prim (); | |
1472 | |
1473 EM_CC_CALL_RETRIEVE_REJECT; | |
1474 | |
1475 CCD_END; | |
1476 } | |
1477 else | |
1478 { | |
1479 CCD_END; | |
1480 /* Implements Measure# 3 and streamline encoding */ | |
1481 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1482 } | |
1483 break; | |
1484 | |
1485 default: | |
1486 CCD_END; | |
1487 /* Implements Measure# 3 and streamline encoding */ | |
1488 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1489 break; | |
1490 } | |
1491 } | |
1492 | |
1493 /* | |
1494 +--------------------------------------------------------------------+ | |
1495 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1496 | STATE : code ROUTINE : cc_congestion_control | | |
1497 +--------------------------------------------------------------------+ | |
1498 | |
1499 PURPOSE : Processing an incoming congestion control message. | |
1500 | |
1501 */ | |
1502 | |
1503 GLOBAL void cc_congestion_control (T_B_CONGEST_CTRL * cong) | |
1504 { | |
1505 GET_INSTANCE_DATA; | |
1506 TRACE_FUNCTION ("cc_congestion_control()"); | |
1507 | |
1508 switch (cc_data->state[cc_data->index_ti]) | |
1509 { | |
1510 /* | |
1511 * CS_0 is handled by the formatter | |
1512 */ | |
1513 case M_CC_CS_10: | |
1514 if (cc_check_error_flag ()) | |
1515 { | |
1516 PALLOC (user, MNCC_USER_IND); | |
1517 | |
1518 cc_build_user_ind_from_cong (user, cong); | |
1519 PSENDX (MMI, user); | |
1520 CCD_END; | |
1521 } | |
1522 break; | |
1523 | |
1524 default: | |
1525 CCD_END; | |
1526 /* Implements Measure# 3 and streamline encoding*/ | |
1527 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1528 break; | |
1529 } | |
1530 } | |
1531 | |
1532 /* | |
1533 +--------------------------------------------------------------------+ | |
1534 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1535 | STATE : code ROUTINE : cc_user_information | | |
1536 +--------------------------------------------------------------------+ | |
1537 | |
1538 PURPOSE : Processing an incoming user information message. | |
1539 | |
1540 */ | |
1541 | |
1542 GLOBAL void cc_user_information ( T_B_USER_INFO * user) | |
1543 { | |
1544 GET_INSTANCE_DATA; | |
1545 TRACE_FUNCTION ("cc_user_information()"); | |
1546 | |
1547 switch (cc_data->state[cc_data->index_ti]) | |
1548 { | |
1549 /* | |
1550 * CS_0 is handled by the formatter | |
1551 */ | |
1552 case M_CC_CS_10: | |
1553 if (cc_check_error_flag ()) | |
1554 { | |
1555 PALLOC (user_ind, MNCC_USER_IND); | |
1556 | |
1557 cc_build_user_ind_from_user (user_ind, user); | |
1558 CCD_END; | |
1559 PSENDX (MMI, user_ind); | |
1560 | |
1561 EM_CC_USER_TO_USER_DATA_RECEIVED; | |
1562 | |
1563 } | |
1564 break; | |
1565 | |
1566 default: | |
1567 CCD_END; | |
1568 /* Implements Measure# 4 and streamline encoding*/ | |
1569 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1570 break; | |
1571 } | |
1572 } | |
1573 | |
1574 /* | |
1575 +--------------------------------------------------------------------+ | |
1576 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1577 | STATE : code ROUTINE : cc_modify | | |
1578 +--------------------------------------------------------------------+ | |
1579 | |
1580 PURPOSE : Processing an incoming modify message. | |
1581 | |
1582 */ | |
1583 | |
1584 GLOBAL void cc_modify (T_B_MODIFY * modify) | |
1585 { | |
1586 GET_INSTANCE_DATA; | |
1587 | |
1588 TRACE_FUNCTION ("cc_modify()"); | |
1589 | |
1590 switch (cc_data->state[cc_data->index_ti]) | |
1591 { | |
1592 /* | |
1593 * CS_0 is handled by the formatter | |
1594 */ | |
1595 case M_CC_CS_10: | |
1596 if (cc_check_error_flag ()) | |
1597 { | |
1598 switch (cc_data->neg_ri) | |
1599 { | |
1600 case M_CC_REPEAT_CIRCULAR: | |
1601 if (cc_data->active_service EQ cc_data->neg_serv1) | |
1602 { | |
1603 if (cc_bcs_compatible (&modify->bearer_cap, | |
1604 &cc_data->neg_bc2, TRUE) EQ TRUE) | |
1605 { | |
1606 CCD_END; | |
1607 cc_mod_complete (); | |
1608 } | |
1609 else | |
1610 { | |
1611 CCD_END; | |
1612 cc_mod_reject (); | |
1613 } | |
1614 } | |
1615 else | |
1616 { | |
1617 if (cc_bcs_compatible (&modify->bearer_cap, | |
1618 &cc_data->neg_bc1, TRUE) EQ TRUE) | |
1619 { | |
1620 CCD_END; | |
1621 cc_mod_complete (); | |
1622 } | |
1623 else | |
1624 { | |
1625 CCD_END; | |
1626 cc_mod_reject (); | |
1627 } | |
1628 } | |
1629 break; | |
1630 #ifndef REL99 | |
1631 case M_CC_REPEAT_SEQUENTIAL: | |
1632 if (cc_data->active_service EQ cc_data->neg_serv1) | |
1633 { | |
1634 if (cc_bcs_compatible (&modify->bearer_cap, | |
1635 &cc_data->neg_bc2, TRUE) EQ TRUE) | |
1636 { | |
1637 CCD_END; | |
1638 cc_mod_complete (); | |
1639 } | |
1640 else | |
1641 { | |
1642 CCD_END; | |
1643 cc_mod_reject (); | |
1644 } | |
1645 } | |
1646 else | |
1647 { | |
1648 CCD_END; | |
1649 cc_mod_reject (); | |
1650 } | |
1651 break; | |
1652 #endif /* #ifndef REL99 */ | |
1653 default: | |
1654 CCD_END; | |
1655 cc_mod_reject (); | |
1656 break; | |
1657 } | |
1658 } | |
1659 break; | |
1660 | |
1661 default: | |
1662 CCD_END; | |
1663 /* Implements Measure# 5 and streamline encoding*/ | |
1664 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1665 break; | |
1666 } | |
1667 } | |
1668 | |
1669 /* | |
1670 +--------------------------------------------------------------------+ | |
1671 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1672 | STATE : code ROUTINE : cc_mod_reject | | |
1673 +--------------------------------------------------------------------+ | |
1674 | |
1675 PURPOSE : Negative end of a mobile terminated in-call modification. | |
1676 | |
1677 */ | |
1678 | |
1679 GLOBAL void cc_mod_reject (void) | |
1680 { | |
1681 GET_INSTANCE_DATA; | |
1682 TRACE_FUNCTION ("cc_mod_reject()"); | |
1683 | |
1684 CCD_START; | |
1685 { | |
1686 MCAST (modify_rej, B_MODIFY_REJ); | |
1687 | |
1688 | |
1689 cc_build_modify_reject (modify_rej, | |
1690 CAUSE_MAKE(DEFBY_STD, | |
1691 ORIGSIDE_MS, | |
1692 MNCC_CC_ORIGINATING_ENTITY, | |
1693 M_CC_CAUSE_BEARER_CAP_AUTHORIZ)); | |
1694 for_modify_reject (modify_rej); | |
1695 } | |
1696 | |
1697 EM_CC_MT_IN_CALL_MODIFICATION_FAILED; | |
1698 | |
1699 CCD_END; | |
1700 } | |
1701 | |
1702 /* | |
1703 +--------------------------------------------------------------------+ | |
1704 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1705 | STATE : code ROUTINE : cc_mod_complete | | |
1706 +--------------------------------------------------------------------+ | |
1707 | |
1708 PURPOSE : Positive end of a mobile terminated in-call modification. | |
1709 | |
1710 */ | |
1711 | |
1712 GLOBAL void cc_mod_complete (void) | |
1713 { | |
1714 GET_INSTANCE_DATA; | |
1715 TRACE_FUNCTION ("cc_mod_complete()"); | |
1716 | |
1717 CCD_START; | |
1718 { | |
1719 MCAST (modify_com, B_MODIFY_COMP); | |
1720 PALLOC (mod_ind, MNCC_MODIFY_IND); | |
1721 | |
1722 | |
1723 if (cc_data->active_service EQ cc_data->neg_serv1) | |
1724 cc_data->active_service = cc_data->neg_serv2; | |
1725 else | |
1726 cc_data->active_service = cc_data->neg_serv1; | |
1727 | |
1728 mod_ind->ti = cc_data->ti; | |
1729 mod_ind->serv = cc_data->active_service; | |
1730 PSENDX (MMI, mod_ind); | |
1731 | |
1732 EM_CC_MT_IN_CALL_MODIFICATION_PASSED; | |
1733 | |
1734 cc_build_modify_complete (modify_com); | |
1735 for_modify_complete (modify_com); | |
1736 } | |
1737 CCD_END; | |
1738 } | |
1739 | |
1740 /* | |
1741 +--------------------------------------------------------------------+ | |
1742 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1743 | STATE : code ROUTINE : cc_modify_complete | | |
1744 +--------------------------------------------------------------------+ | |
1745 | |
1746 PURPOSE : Processing an incoming modify complete message. | |
1747 | |
1748 */ | |
1749 | |
1750 GLOBAL void cc_modify_complete ( T_B_MODIFY_COMP * mod_com) | |
1751 { | |
1752 GET_INSTANCE_DATA; | |
1753 TRACE_FUNCTION ("cc_modify_complete()"); | |
1754 | |
1755 switch (cc_data->state[cc_data->index_ti]) | |
1756 { | |
1757 /* | |
1758 * CS_0 is handled by the formatter | |
1759 */ | |
1760 case M_CC_CS_26: | |
1761 if (cc_check_error_flag ()) | |
1762 { | |
1763 if (cc_data->new_itc EQ mod_com->bearer_cap.trans_cap) | |
1764 { | |
1765 PALLOC (mod_cnf, MNCC_MODIFY_CNF); | |
1766 | |
1767 TIMERSTOP (TIMER_CC); | |
1768 if (cc_data->active_service EQ cc_data->serv1) | |
1769 cc_data->active_service = cc_data->serv2; | |
1770 else | |
1771 cc_data->active_service = cc_data->serv1; | |
1772 mod_cnf->ti = cc_data->ti; | |
1773 mod_cnf->cause = MNCC_CAUSE_MODIFY_SUCCESS; | |
1774 /* Setting raw_cause to empty as we are not sending any cause from network*/ | |
1775 mod_cnf->c_raw_cause = 0; | |
1776 | |
1777 EM_CC_MO_IN_CALL_MODIFICATION_PASSED; | |
1778 | |
1779 PSENDX (MMI, mod_cnf); | |
1780 cc_set_state (M_CC_CS_10); | |
1781 } | |
1782 CCD_END; | |
1783 } | |
1784 break; | |
1785 | |
1786 default: | |
1787 CCD_END; | |
1788 /* Implements Measure# 6 and streamline encoding*/ | |
1789 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1790 break; | |
1791 } | |
1792 } | |
1793 | |
1794 /* | |
1795 +--------------------------------------------------------------------+ | |
1796 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1797 | STATE : code ROUTINE : cc_modify_reject | | |
1798 +--------------------------------------------------------------------+ | |
1799 | |
1800 PURPOSE : Processing an incoming modify reject message. | |
1801 | |
1802 */ | |
1803 | |
1804 GLOBAL void cc_modify_reject (T_B_MODIFY_REJ * mod_rej) | |
1805 { | |
1806 GET_INSTANCE_DATA; | |
1807 TRACE_FUNCTION ("cc_modify_reject()"); | |
1808 | |
1809 switch (cc_data->state[cc_data->index_ti]) | |
1810 { | |
1811 /* | |
1812 * CS_0 is handled by the formatter | |
1813 */ | |
1814 case M_CC_CS_26: | |
1815 if (cc_check_error_flag ()) | |
1816 { | |
1817 if (cc_data->old_itc EQ mod_rej->bearer_cap.trans_cap) | |
1818 { | |
1819 PALLOC (mod_cnf, MNCC_MODIFY_CNF); | |
1820 | |
1821 TIMERSTOP (TIMER_CC); | |
1822 mod_cnf->ti = cc_data->ti; | |
1823 /* | |
1824 * cause IE is mandatory and the check for presence has been done | |
1825 * already thus there is no need to check for validity of cause IE | |
1826 * here anymore | |
1827 */ | |
1828 mod_cnf->cause = CAUSE_MAKE(DEFBY_STD, | |
1829 ORIGSIDE_NET, | |
1830 MNCC_CC_ORIGINATING_ENTITY, | |
1831 mod_rej->cc_cause.cause); | |
1832 mod_cnf->c_raw_cause = cc_build_cause (&mod_rej->cc_cause, | |
1833 mod_cnf->raw_cause); | |
1834 PSENDX (MMI, mod_cnf); | |
1835 cc_set_state (M_CC_CS_10); | |
1836 } | |
1837 | |
1838 EM_CC_MO_IN_CALL_MODIFICATION_FAILED; | |
1839 | |
1840 CCD_END; | |
1841 } | |
1842 break; | |
1843 | |
1844 default: | |
1845 CCD_END; | |
1846 /* Implements Measure# 7 and streamline encoding*/ | |
1847 cc_send_status (M_CC_CAUSE_MESSAGE_TYPE_INCOMPAT); | |
1848 break; | |
1849 } | |
1850 } | |
1851 | |
1852 | |
1853 /* | |
1854 +--------------------------------------------------------------------+ | |
1855 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
1856 | STATE : code ROUTINE : cc_status | | |
1857 +--------------------------------------------------------------------+ | |
1858 | |
1859 PURPOSE : Processing an incoming status message. | |
1860 | |
1861 */ | |
1862 | |
1863 GLOBAL void cc_status (T_B_STATUS * status) | |
1864 { | |
1865 GET_INSTANCE_DATA; | |
1866 TRACE_FUNCTION ("cc_status()"); | |
1867 | |
1868 /* The cause is in STATUS a mandatory IE (given intact message) */ | |
1869 TRACE_EVENT_P1 ("STATUS cause: %02x", status->cc_cause.cause); | |
1870 | |
1871 switch (cc_data->state[cc_data->index_ti]) | |
1872 { | |
1873 case M_CC_CS_0: | |
1874 CCD_END; | |
1875 if (status->call_state.state NEQ M_CC_CS_0) | |
1876 { | |
1877 CCD_START; | |
1878 { | |
1879 MCAST (rel_com, U_RELEASE_COMP); | |
1880 | |
1881 cc_build_release_complete (rel_com, | |
1882 CAUSE_MAKE(DEFBY_STD, | |
1883 ORIGSIDE_MS, | |
1884 MNCC_CC_ORIGINATING_ENTITY, | |
1885 M_CC_CAUSE_MESSAGE_INCOMPAT)); | |
1886 for_release_complete (rel_com); | |
1887 } | |
1888 CCD_END; | |
1889 } | |
1890 for_rel_req (); | |
1891 break; | |
1892 | |
1893 case M_CC_CS_1: | |
1894 case M_CC_CS_3: | |
1895 case M_CC_CS_4: | |
1896 case M_CC_CS_6: | |
1897 case M_CC_CS_7: | |
1898 case M_CC_CS_8: | |
1899 case M_CC_CS_9: | |
1900 case M_CC_CS_10: | |
1901 case M_CC_CS_26: | |
1902 if (cc_check_error_flag ()) | |
1903 { | |
1904 /* check for incompatible state */ | |
1905 if (status->call_state.state NEQ cc_data->state[cc_data->index_ti]) | |
1906 { | |
1907 PALLOC (rel_ind, MNCC_RELEASE_IND); | |
1908 | |
1909 cc_reset_dtmf (); // China change HM 11.07.00 | |
1910 | |
1911 TIMERSTOP (TIMER_CC); | |
1912 | |
1913 rel_ind->ti = cc_data->ti; | |
1914 | |
1915 rel_ind->cause = CAUSE_MAKE(DEFBY_STD, | |
1916 ORIGSIDE_MS, | |
1917 MNCC_CC_ORIGINATING_ENTITY, | |
1918 M_CC_CAUSE_MESSAGE_INCOMPAT); | |
1919 rel_ind->c_raw_cause = 0; | |
1920 PSENDX (MMI, rel_ind); | |
1921 | |
1922 CCD_END; | |
1923 CCD_START; | |
1924 { | |
1925 MCAST (rel_com, U_RELEASE_COMP); | |
1926 | |
1927 cc_build_release_complete (rel_com, | |
1928 CAUSE_MAKE(DEFBY_STD, | |
1929 ORIGSIDE_MS, | |
1930 MNCC_CC_ORIGINATING_ENTITY, | |
1931 M_CC_CAUSE_MESSAGE_INCOMPAT)); | |
1932 for_release_complete (rel_com); | |
1933 } | |
1934 CCD_END; | |
1935 for_rel_req (); | |
1936 cc_set_state (M_CC_CS_0); | |
1937 } | |
1938 else | |
1939 /* | |
1940 * compatible, perform checks/ actions of 04.08, ch. 5.5.3.2.2; | |
1941 * Condat action (option!) is to initiate normal call clearing | |
1942 * (with DISCONNECT) | |
1943 */ | |
1944 { | |
1945 if ((status->cc_cause.cause >= M_CC_CAUSE_INCORRECT_MESSAGE) | |
1946 AND | |
1947 (status->cc_cause.cause <= M_CC_CAUSE_COND_INFO_ELEM)) | |
1948 { | |
1949 /* | |
1950 * Block entered for | |
1951 * CAUSE_INCORRECT_MESSAGE, CAUSE_INVALID_MAND_INFO, | |
1952 * CAUSE_MESSAGE_TYPE_NOT_IMPLEM, CAUSE_MESSAGE_TYPE_INCOMPAT, | |
1953 * CAUSE_INFO_ELEM_NOT_IMPLEM, CAUSE_COND_INFO_ELEM. (0x5f..0x64) | |
1954 */ | |
1955 if ((cc_data->state[cc_data->index_ti] EQ M_CC_CS_10) AND | |
1956 (cc_data->hold_state[cc_data->index_ti] EQ M_CC_HLD_HOLD_REQ)) | |
1957 { | |
1958 /* | |
1959 * Compatible state, last CC message was a hold request which is | |
1960 * not supported by the network. Handled like HOLD REJECT. | |
1961 */ | |
1962 PALLOC (hold_cnf, MNCC_HOLD_CNF); /* T_MNCC_HOLD_CNF */ | |
1963 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_IDLE; | |
1964 hold_cnf->ti = cc_data->ti; | |
1965 hold_cnf->cause = CAUSE_MAKE(DEFBY_STD, | |
1966 ORIGSIDE_NET, | |
1967 MNCC_CC_ORIGINATING_ENTITY, | |
1968 status->cc_cause.cause); | |
1969 PSENDX (MMI, hold_cnf); | |
1970 CCD_END; | |
1971 srv_use_stored_prim (); | |
1972 } | |
1973 else if (status->cc_cause.cause NEQ M_CC_CAUSE_INFO_ELEM_NOT_IMPLEM) | |
1974 { | |
1975 /* | |
1976 * Compatible state, special condition for HOLD REQUEST not met. | |
1977 * The network is also not complaining about an optional | |
1978 * information element which can be simply ignored. | |
1979 * Disconnect the call. | |
1980 */ | |
1981 PALLOC (disc_ind, MNCC_DISCONNECT_IND); | |
1982 | |
1983 TIMERSTOP (TIMER_CC); | |
1984 | |
1985 disc_ind->ti = cc_data->ti; | |
1986 disc_ind->cause = CAUSE_MAKE(DEFBY_STD, | |
1987 ORIGSIDE_NET, | |
1988 MNCC_CC_ORIGINATING_ENTITY, | |
1989 status->cc_cause.cause); | |
1990 disc_ind->c_raw_cause = cc_build_cause (&status->cc_cause, | |
1991 disc_ind->raw_cause); | |
1992 disc_ind->diagnostic = NOT_PRESENT_8BIT; | |
1993 disc_ind->progress_desc = MNCC_PROG_NOT_PRES; | |
1994 PSENDX (MMI, disc_ind); | |
1995 | |
1996 CCD_END; | |
1997 CCD_START; | |
1998 { | |
1999 MCAST (disconnect, U_DISCONNECT); | |
2000 | |
2001 cc_build_disconnect (disconnect, | |
2002 CAUSE_MAKE(DEFBY_STD, | |
2003 ORIGSIDE_MS, | |
2004 MNCC_CC_ORIGINATING_ENTITY, | |
2005 M_CC_CAUSE_CALL_CLEAR), | |
2006 NULL, MNCC_SS_VER_NOT_PRES); | |
2007 for_disconnect (disconnect); | |
2008 } | |
2009 TIMERSTART (T305, T305_VALUE); | |
2010 cc_set_state (M_CC_CS_11); | |
2011 } | |
2012 } | |
2013 else | |
2014 { | |
2015 /* | |
2016 * STATUS message but neither incompatible state nor indicating | |
2017 * incorrect message / IE; check if we received a STATUS with cause | |
2018 * "message not compatible with protocol state". GSM 04.08 does not | |
2019 * define what to do and also does not define that this case has to | |
2020 * be handled at all; | |
2021 * Condat (HM) decided to "clear DTMF" if it was running to try to | |
2022 * recover from the misaligned states scenario. | |
2023 */ | |
2024 T_DTMF *p_dtmf; | |
2025 | |
2026 p_dtmf = &cc_data->dtmf[cc_data->index_ti]; | |
2027 if ((p_dtmf->state EQ DTMF_SEND_REQUEST) AND | |
2028 (status->cc_cause.cause EQ M_CC_CAUSE_MESSAGE_INCOMPAT)) | |
2029 { | |
2030 /* Send negative acknowledge for DTMF send request to MMI */ | |
2031 PALLOC (mncc_start_dtmf_cnf, MNCC_START_DTMF_CNF); | |
2032 mncc_start_dtmf_cnf->ti = cc_data->ti; | |
2033 mncc_start_dtmf_cnf->key = NOT_PRESENT_8BIT; | |
2034 mncc_start_dtmf_cnf->dtmf_mod = NOT_PRESENT_8BIT; | |
2035 mncc_start_dtmf_cnf->cause = CAUSE_MAKE(DEFBY_STD, | |
2036 ORIGSIDE_NET, | |
2037 MNCC_CC_ORIGINATING_ENTITY, | |
2038 M_CC_CAUSE_MESSAGE_INCOMPAT); | |
2039 PSENDX (MMI, mncc_start_dtmf_cnf); | |
2040 } | |
2041 | |
2042 /* Bring screwed up network back to work */ | |
2043 for_stop_dtmf (); | |
2044 | |
2045 /* Reset screwed up DTMF state machine */ | |
2046 p_dtmf->state = DTMF_IDLE; | |
2047 p_dtmf->read = 0; | |
2048 p_dtmf->write = 0; | |
2049 } | |
2050 CCD_END; | |
2051 } | |
2052 } | |
2053 break; | |
2054 | |
2055 case M_CC_CS_11: | |
2056 case M_CC_CS_12: | |
2057 if (cc_check_error_flag ()) | |
2058 { | |
2059 if (status->call_state.state NEQ cc_data->state[cc_data->index_ti]) | |
2060 { | |
2061 /* | |
2062 * STATUS message with incompatible state | |
2063 * On receipt of a STATUS message reporting an incompatible call | |
2064 * control state, the receiving entity shall clear the call by | |
2065 * sending a RELEASE COMPLETE message with cause # 101 "message | |
2066 * not compatible with protocol state". The reported call control | |
2067 * state is incompatible if the combination of call control states | |
2068 * at the sender and receiver side cannot occur, do not match or cannot | |
2069 * be aligned by actions of the receiver; the exact definition is | |
2070 * implementation dependent. [04.08 clause 5.5.3.2.1] | |
2071 */ | |
2072 cc_reset_dtmf (); | |
2073 | |
2074 TIMERSTOP (TIMER_CC); | |
2075 | |
2076 /* Send MNCC_RELEASE_IND to MMI */ | |
2077 { | |
2078 PALLOC (rel_ind, MNCC_RELEASE_IND); /* T_MNCC_RELEASE_IND */ | |
2079 rel_ind->ti = cc_data->ti; | |
2080 rel_ind->cause = CAUSE_MAKE(DEFBY_STD, | |
2081 ORIGSIDE_MS, | |
2082 MNCC_CC_ORIGINATING_ENTITY, | |
2083 M_CC_CAUSE_MESSAGE_INCOMPAT); | |
2084 rel_ind->c_raw_cause = 0; | |
2085 PSENDX (MMI, rel_ind); | |
2086 } | |
2087 | |
2088 CCD_END; | |
2089 CCD_START; | |
2090 { | |
2091 MCAST (rel_com, U_RELEASE_COMP); /* T_U_RELEASE_COMP */ | |
2092 cc_build_release_complete (rel_com, | |
2093 CAUSE_MAKE(DEFBY_STD, | |
2094 ORIGSIDE_MS, | |
2095 MNCC_CC_ORIGINATING_ENTITY, | |
2096 M_CC_CAUSE_MESSAGE_INCOMPAT)); | |
2097 for_release_complete (rel_com); | |
2098 for_rel_req (); | |
2099 cc_set_state (M_CC_CS_0); | |
2100 } | |
2101 } | |
2102 CCD_END; | |
2103 } | |
2104 break; | |
2105 | |
2106 case M_CC_CS_19: | |
2107 if (cc_check_error_flag ()) | |
2108 { | |
2109 if (status->call_state.state NEQ cc_data->state[cc_data->index_ti]) | |
2110 { | |
2111 TIMERSTOP (TIMER_CC); | |
2112 | |
2113 cc_reset_dtmf (); | |
2114 | |
2115 { | |
2116 PALLOC (rel_cnf, MNCC_RELEASE_CNF); /* T_MNCC_RELEASE_CNF */ | |
2117 rel_cnf->ti = cc_data->ti; | |
2118 rel_cnf->cause = CAUSE_MAKE(DEFBY_STD, | |
2119 ORIGSIDE_MS, | |
2120 MNCC_CC_ORIGINATING_ENTITY, | |
2121 M_CC_CAUSE_MESSAGE_INCOMPAT); | |
2122 /* Setting raw_cause to empty as this is a local release | |
2123 * of MM connection,CC is not receiving any cause value | |
2124 * from Network | |
2125 */ | |
2126 rel_cnf->c_raw_cause = 0; | |
2127 PSENDX (MMI, rel_cnf); | |
2128 } | |
2129 | |
2130 CCD_END; | |
2131 CCD_START; | |
2132 { | |
2133 MCAST (rel_com, U_RELEASE_COMP); /* T_U_RELEASE_COMP */ | |
2134 cc_build_release_complete (rel_com, | |
2135 CAUSE_MAKE(DEFBY_STD, | |
2136 ORIGSIDE_MS, | |
2137 MNCC_CC_ORIGINATING_ENTITY, | |
2138 M_CC_CAUSE_MESSAGE_INCOMPAT)); | |
2139 for_release_complete (rel_com); | |
2140 for_rel_req (); | |
2141 cc_set_state (M_CC_CS_0); | |
2142 } | |
2143 } | |
2144 CCD_END; | |
2145 } | |
2146 break; | |
2147 | |
2148 default: | |
2149 CCD_END; | |
2150 break; | |
2151 } | |
2152 | |
2153 EM_CC_STATUS_RECEIVED; | |
2154 | |
2155 } | |
2156 | |
2157 /* | |
2158 +--------------------------------------------------------------------+ | |
2159 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
2160 | STATE : code ROUTINE : cc_status_enquiry | | |
2161 +--------------------------------------------------------------------+ | |
2162 | |
2163 PURPOSE : Processing an incoming status enquiry message. | |
2164 | |
2165 */ | |
2166 | |
2167 GLOBAL void cc_status_enquiry (void) | |
2168 { | |
2169 GET_INSTANCE_DATA; | |
2170 | |
2171 TRACE_FUNCTION ("cc_status_enquiry()"); | |
2172 | |
2173 /* | |
2174 * CS_0 is handled by the formatter | |
2175 */ | |
2176 switch (cc_data->state[cc_data->index_ti]) | |
2177 { | |
2178 case M_CC_CS_10: | |
2179 /* | |
2180 * Ensure synchronization of auxiliary states with ACI. | |
2181 */ | |
2182 if (cc_check_error_flag ()) | |
2183 { | |
2184 CCD_END; | |
2185 { | |
2186 PALLOC (mncc_status_ind, MNCC_STATUS_IND); | |
2187 mncc_status_ind->ti = cc_data->ti; | |
2188 PSENDX (MMI, mncc_status_ind); | |
2189 } | |
2190 | |
2191 EM_CC_STATUS_ENQUIRY_RECEIVED; | |
2192 | |
2193 } | |
2194 break; | |
2195 | |
2196 default: | |
2197 /* | |
2198 * No auxiliary states in non-active states. Immediate response is safe. | |
2199 */ | |
2200 if (cc_check_error_flag ()) | |
2201 { | |
2202 CCD_END; | |
2203 /* EM call moved above cc_send_status should not have any impact */ | |
2204 EM_CC_STATUS_ENQUIRY_RECEIVED; | |
2205 | |
2206 /* Implements Measure# 7 and streamline encoding*/ | |
2207 cc_send_status (M_CC_CAUSE_STATUS_ENQUIRY); | |
2208 } | |
2209 break; | |
2210 } | |
2211 } | |
2212 | |
2213 | |
2214 /* | |
2215 +--------------------------------------------------------------------+ | |
2216 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
2217 | STATE : code ROUTINE : cc_unknown_message | | |
2218 +--------------------------------------------------------------------+ | |
2219 | |
2220 PURPOSE : Processing of an incoming unknown message. | |
2221 | |
2222 */ | |
2223 | |
2224 GLOBAL void cc_unknown_message (void) | |
2225 { | |
2226 | |
2227 CCD_END; | |
2228 CCD_START; | |
2229 { | |
2230 MCAST (status, B_STATUS); | |
2231 | |
2232 TRACE_FUNCTION ("cc_unknown_message()"); | |
2233 | |
2234 cc_build_status (status, | |
2235 CAUSE_MAKE(DEFBY_STD, | |
2236 ORIGSIDE_MS, | |
2237 MNCC_CC_ORIGINATING_ENTITY, | |
2238 M_CC_CAUSE_MESSAGE_TYPE_NOT_IMPLEM)); | |
2239 for_status (status); | |
2240 } | |
2241 CCD_END; | |
2242 } | |
2243 | |
2244 /* Implements Measure# 18 */ | |
2245 /* | |
2246 +--------------------------------------------------------------------+ | |
2247 | PROJECT : GSM-PS (6147) MODULE : CC_ACT | | |
2248 | STATE : code ROUTINE : cc_mncc_hold_retrieve_req | | |
2249 +--------------------------------------------------------------------+ | |
2250 | |
2251 PURPOSE : Send hold REQ/retrieve REQ. | |
2252 | |
2253 */ | |
2254 | |
2255 LOCAL void cc_mncc_hold_retrieve_req (T_PRIM * prim) | |
2256 { | |
2257 GET_INSTANCE_DATA; | |
2258 UBYTE ti; | |
2259 | |
2260 TRACE_FUNCTION ("cc_mncc_hold_retrieve_req()"); | |
2261 | |
2262 if(prim->custom.opc EQ MNCC_HOLD_REQ) | |
2263 { | |
2264 ti = ((T_MNCC_HOLD_REQ *)P2D(prim))->ti; | |
2265 } | |
2266 else | |
2267 { | |
2268 ti = ((T_MNCC_RETRIEVE_REQ *)P2D(prim))->ti; | |
2269 } | |
2270 if ((cc_data->index_ti = srv_convert_ti (ti)) EQ NOT_PRESENT_8BIT) | |
2271 { | |
2272 PFREE (P2D(prim)); | |
2273 return; | |
2274 } | |
2275 | |
2276 switch (cc_data->state[cc_data->index_ti]) | |
2277 { | |
2278 case M_CC_CS_10: | |
2279 if(prim->custom.opc EQ MNCC_HOLD_REQ) | |
2280 { | |
2281 /* We should think about storing the hold request | |
2282 until DTMF idle state reached. ... | |
2283 This causes some other changes, we have to add some | |
2284 calls to serv_use_stored_prim() at some places after | |
2285 state transition of the DTMF state machine to DTMF idle.*/ | |
2286 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_HOLD_REQ; | |
2287 for_hold (); | |
2288 EM_CC_CALL_HOLD; | |
2289 } | |
2290 else | |
2291 { | |
2292 cc_data->hold_state[cc_data->index_ti] = M_CC_HLD_RETRIEVE_REQ; | |
2293 for_retrieve (); | |
2294 EM_CC_CALL_RETRIEVE; | |
2295 } | |
2296 PFREE (P2D(prim)); | |
2297 | |
2298 break; | |
2299 | |
2300 case CS_101: | |
2301 case M_CC_CS_26: | |
2302 case CS_261: | |
2303 srv_store_prim (prim); | |
2304 break; | |
2305 | |
2306 default: | |
2307 PFREE (P2D(prim)); | |
2308 break; | |
2309 } | |
2310 } | |
2311 | |
2312 #endif |