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