comparison src/g23m-aci/aci/aoc.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 : AOC
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 module defines the functions for the
18 | advice of charge handling of ACI.
19 +-----------------------------------------------------------------------------
20 */
21
22 #include "aci_all.h"
23
24 #include "l4_tim.h"
25
26 #include "pcm.h"
27
28 #include "aci_cmh.h"
29
30 #include "psa.h"
31 #include "psa_sim.h"
32 #include "psa_mm.h"
33
34 #include "aoc.h"
35 #include "psa_cc.h"
36 #include "cmh.h"
37 #include "cmh_cc.h"
38
39 #ifdef SIM_TOOLKIT
40 #include "psa_sat.h"
41 #endif
42
43 #ifdef FAX_AND_DATA
44 #include "aci_fd.h"
45 #endif /* of #ifdef FAX_AND_DATA */
46
47 #ifdef UART
48 #include "dti.h"
49 #include "dti_conn_mng.h"
50 #endif
51
52 #include "cmh_sim.h"
53
54 #define MC_AOC_ROUND_UP(X) ((((X)%100) EQ 0) ? ((X)/100) : (((X)/100) + 1))
55 #define E_IN_MS(X) ((X)*100)
56
57 #ifdef TI_PS_OP_VSI_NO_CALL_ID
58 #define TIMER_START(C,I,T) vsi_t_start_nc(I,T)
59 #define TIMER_PSTART(C,I,T,R) vsi_t_pstart_nc(I,T,R)
60 #define TIMER_STOP(C,I) vsi_t_stop_nc(I)
61 #define TIMER_STATUS(C,I,T) vsi_t_status_nc(I,T)
62 #define SUSPEND_SELF(C,T) vsi_t_sleep_nc(T)
63 #define SYSTEM_TIME(C,T) vsi_t_time_nc(T)
64 #else /* TI_PS_OP_VSI_NO_CALL_ID */
65 #define TIMER_START(C,I,T) vsi_t_start(C,I,T)
66 #define TIMER_PSTART(C,I,T,R) vsi_t_pstart(C,I,T,R)
67 #define TIMER_STOP(C,I) vsi_t_stop(C,I)
68 #define TIMER_STATUS(C,I,T) vsi_t_status(C,I,T)
69 #define SUSPEND_SELF(C,T) vsi_t_sleep(C,T)
70 #define SYSTEM_TIME(C,T) vsi_t_time(C,T)
71 #endif /* TI_PS_OP_VSI_NO_CALL_ID */
72
73 /********* current define *********************************************/
74 static UBYTE aoc_state = AOC_NULL; /* actual AoC state */
75 static UBYTE sim_data[10]; /* SIM data exchange */
76 static UBYTE currency [4]; /* used for currency */
77 static ULONG ccm; /* current call meter */
78 static ULONG ccm_already_incremented; /* value of CCM increm. */
79 static ULONG acm; /* accumulated call meter */
80 static UBYTE acm_increment_flag; /* counter for incr. ACM */
81 static ULONG acmmax; /* maximum of ACM */
82 static ULONG eppu; /* elementary unit price */
83 static ULONG sexp; /* sign of expression */
84 static ULONG exp; /* expression value */
85 static UBYTE pwd [9]; /* password */
86 static UBYTE act_upd_op; /* actual update operation*/
87 static ULONG act_value; /* new value for ACM(Max) */
88 static T_ACI_CMD_SRC act_src_id; /* source of AT command */
89
90 GLOBAL T_CC_AOC_TBL cc_aoc_table[MAX_CALL_NR]; /* AoC Call Table */
91 EXTERN T_PCEER causeMod;
92 EXTERN SHORT causeCeer;
93
94 static ULONG cct; /* current call timer */
95 /*static ULONG act; *//* accumulated call timer */ /* never used */
96 static USHORT ct_running; /* call timer is running */
97 static UBYTE limit_reached = FALSE; /* ACM over limit ? */
98
99 static const ULONG ppu_values [16][2] =
100 {
101 /* exp, sexp index */
102 1L, 0L, /* 0 */
103 1L, 0L, /* 1 */
104 10L, 0L, /* 2 */
105 10L, 1L, /* 3 */
106 100L, 0L, /* 4 */
107 100L, 1L, /* 5 */
108 1000L, 0L, /* 6 */
109 1000L, 1L, /* 7 */
110 10000L, 0L, /* 8 */
111 10000L, 1L, /* 9 */
112 100000L, 0L, /* 10 */
113 100000L, 1L, /* 11 */
114 1000000L, 0L, /* 12 */
115 1000000L, 1L, /* 13 */
116 10000000L, 0L, /* 14 */
117 10000000L, 1L /* 15 */
118 };
119
120 #ifdef SIM_TOOLKIT
121 BOOL aoc_update (int ref, T_SIM_FILE_UPDATE_IND *fu);
122 #endif
123 static UBYTE ccwv_charging = CCWV_CHRG_Termination;
124
125 /********* function prototypes **************************************/
126 void aoc_calc_acm_wrn_evnt ( ULONG charge,
127 BOOL aoc_running );
128
129 void aoc_set_time_ut_charge ( SHORT cId,
130 T_TIME time );
131 void aoc_calc_expct_charge ( UBYTE mode );
132 void aoc_ntfy_acm_wrn_evnt ( T_ACI_CCWV_CHRG charging );
133
134 T_TIME aoc_calc_time_ut_charge ( SHORT cId,
135 UBYTE e_value_flag );
136
137 void aoc_start_info_newcall (SHORT Cid);
138 void aoc_start_newinfo_existingcall (SHORT Cid);
139
140 static void aoc_calculate_charging_parameter_part1 (SHORT Cid);
141 static void aoc_calculate_charging_parameter_part2 (SHORT Cid);
142 /********* functions ************************************************/
143 LOCAL void aoc_update_sim_datafield_cb(SHORT table_id, T_ACI_AT_CMD at_cmd_idn);
144 LOCAL void aoc_read_sim_datafield (UBYTE accType,
145 USHORT reqDataFld,
146 void (*rplyCB)(SHORT),
147 UBYTE dataLen);
148 /*
149 +--------------------------------------------------------------------+
150 | PROJECT: GSM-PS (6147) MODULE: AOC |
151 | STATE : code ROUTINE: aoc_init |
152 +--------------------------------------------------------------------+
153
154
155 PURPOSE : Initialisation of the Advice of charge module. The function
156 is called after PIN entering. The actual phase of the SIM
157 card, the SIM service table and the PCM entry is checked.
158 The return value indicates whether AoC is supported.
159
160 */
161
162 UBYTE aoc_init (UBYTE phase, UBYTE * sim_service_table)
163 {
164 EF_MSSUP mssup;
165 UBYTE version;
166
167 TRACE_FUNCTION ("aoc_init()");
168
169 aoc_state = AOC_DISABLE;
170 /* Check Phase. It must be at least Phase 2 */
171 if (phase <= PHASE_1_SIM)
172 return FALSE;
173 TRACE_EVENT ("AOC: Card >= Phase 2");
174
175 /* Check SIM Service Table */
176 if (aoc_ssc(SRV_AOC,sim_service_table) NEQ ALLOCATED_AND_ACTIVATED)
177 return FALSE;
178 TRACE_EVENT ("AOC: Card supports AoC");
179
180 /* check PCM entry in MSCAP field */
181 pcm_Init ();
182 /* Implements Measure#32: Row 60 & 1039 */
183 pcm_ReadFile ((UBYTE *)ef_mssup_id, SIZE_EF_MSSUP, (UBYTE *)&mssup, &version);
184 if (FldGet(mssup.feat1, AoC))
185 {
186 /* start reading ACM, ACMMax and PUCT */
187 TRACE_EVENT ("AOC: MS supports AoC");
188 aoc_state = AOC_ENABLE;
189 /* Implements Measure 156 and 157 */
190 aoc_read_sim_datafield ( ACT_RD_REC, SIM_ACM, aoc_read_acm_cb, 3 );
191 return TRUE;
192 }
193
194 #ifdef _SIMULATION_
195 aoc_state = AOC_ENABLE;
196 return TRUE;
197 #else
198 return FALSE;
199 #endif
200
201 }
202
203 /*
204 +--------------------------------------------------------------------+
205 | PROJECT: GSM-PS (6147) MODULE: AOC |
206 | STATE : code ROUTINE: aoc_reset |
207 +--------------------------------------------------------------------+
208
209 PURPOSE : Deactivation of AoC Service. Necessary, when SIM card
210 becomes unavailable
211 */
212
213 void aoc_reset (void)
214 {
215 TRACE_FUNCTION ("aoc_reset()");
216 aoc_state = AOC_DISABLE;
217 }
218
219 /*
220 +--------------------------------------------------------------------+
221 | PROJECT: GSM-PS (6147) MODULE: AOC |
222 | STATE : code ROUTINE: aoc_sms |
223 +--------------------------------------------------------------------+
224
225
226 PURPOSE : Indication that a SMS has received. This can be a trigger
227 for changed ACM or ACMMax on the SIM card.
228 */
229
230 void aoc_sms (void)
231 {
232 TRACE_FUNCTION ("aoc_sms()");
233 if (aoc_state EQ AOC_ENABLE)
234 {
235 /* start reading ACM, ACMMax and PUCT again */
236 /* Implements Measure 156 and 157 */
237 aoc_read_sim_datafield ( ACT_RD_REC, SIM_ACM, aoc_read_acm_cb, 3 );
238 }
239 }
240
241 /*
242 +--------------------------------------------------------------------+
243 | PROJECT: GSM-PS (6147) MODULE: AOC |
244 | STATE : code ROUTINE: aoc_update |
245 +--------------------------------------------------------------------+
246
247 PURPOSE : Evaluation of File Change Notification and update AOC,
248 if required.
249 */
250
251 #ifdef SIM_TOOLKIT
252 BOOL aoc_update (int ref, T_SIM_FILE_UPDATE_IND *fu)
253 {
254 BOOL found = FALSE;
255 int i;
256
257 TRACE_FUNCTION ("aoc_update ()");
258
259 if (aoc_state NEQ AOC_ENABLE)
260 return TRUE; /* not used at all! */ /* AOC not supported */
261
262 for (i = 0; i < (int)fu->val_nr; i++)
263 {
264 /* Check the full path as well */
265 if (fu->file_info[i].v_path_info EQ TRUE AND
266 fu->file_info[i].path_info.df_level1 EQ SIM_DF_GSM AND
267 fu->file_info[i].path_info.v_df_level2 EQ FALSE AND
268 ( fu->file_info[i].datafield EQ SIM_ACM OR
269 fu->file_info[i].datafield EQ SIM_ACMMAX OR
270 fu->file_info[i].datafield EQ SIM_PUCT ) )
271 {
272 found = TRUE;
273 break;
274 }
275 }
276
277 if (found)
278 {
279 simShrdPrm.fuRef = ref;
280 /* Implements Measure 156 and 157 */
281 aoc_read_sim_datafield ( ACT_RD_REC, SIM_ACM, aoc_read_acm_cb, 3 );
282 return FALSE;
283 }
284 else
285 {
286 simShrdPrm.fuRef = -1; /* no update needed */
287 return TRUE;
288 }
289 }
290 #endif
291
292 /*
293 +--------------------------------------------------------------------+
294 | PROJECT: GSM-PS (6147) MODULE: AOC |
295 | STATE : code ROUTINE: aoc_info |
296 +--------------------------------------------------------------------+
297
298 PURPOSE : Information of the Advice of charge module. The following
299 causes are defined:
300 AOC_START_TIME Start call time measurements.
301 AOC_STOP_TIME Stop call timer measurements.
302 AOC_START_AOC Advice of Charge is started.
303 AOC_SUSPEND_AOC Suspension of Call.
304 AOC_RESUME_AOC Resumption of Call.
305 */
306
307 UBYTE aoc_info (SHORT Cid, UBYTE cause)
308 {
309 BOOL calFlg; /* call flag */
310
311 TRACE_FUNCTION ("aoc_info()");
312
313 switch (cause)
314 {
315 case AOC_START_TIME: /* Indication of a new call. */
316 #ifdef _SIMULATION_
317 TRACE_EVENT ("AOC_START_TIME");
318 #endif
319 /* Call Time Measurements shall be
320 * started if it is the first call (ct_runnning = 0) */
321 if (ct_running EQ 0)
322 {
323 /* this is the first call. Then start call timer (periodic)
324 * and clear current calltimer value and current call meter. */
325 cct = ccm = ccm_already_incremented = 0L;
326 TIMER_PSTART (aci_handle, AOC_CALLTIMER, AOC_THOUSAND_MILLISECONDS, AOC_THOUSAND_MILLISECONDS);
327
328 simShrdPrm.synCs = SYNC_START_CALL;
329 psaSIM_SyncSIM();
330 }
331
332 cmhCC_flagCall( Cid, &ct_running );
333
334 /* Clear aoc table parameter */
335 memset (&cc_aoc_table[Cid], 0, sizeof(T_CC_AOC_TBL));
336 break;
337
338 case AOC_STOP_TIME: /* Indication of the end of a call. */
339 #ifdef _SIMULATION_
340 TRACE_EVENT ("AOC_STOP_TIME");
341 #endif
342 TRACE_EVENT_P1("CT Running = %4X", ct_running);
343 calFlg = cmhCC_tstAndUnflagCall( Cid, &ct_running );
344
345 /*Call Time Measurements shall be
346 * stopped if it is the last call (ct_runnning <= 1) */
347 if (ct_running EQ 0 AND calFlg)
348 {
349 /* this is the last call. Then stop call timer. */
350 TRACE_EVENT ("Last Call Stop Call Timer");
351 TIMER_STOP (aci_handle, AOC_CALLTIMER);
352
353
354 simShrdPrm.synCs = SYNC_STOP_CALL;
355 psaSIM_SyncSIM();
356
357 aoc_ntfy_acm_wrn_evnt ( CCWV_CHRG_Termination );
358 }
359
360 if (cc_aoc_table[Cid].aoc_timer_running) /* stop AoC timer if running */
361 {
362 TIMER_STOP (aci_handle, (USHORT)(AOC_AOCTIMER+Cid));
363 cc_aoc_table[Cid].aoc_timer_running = FALSE;
364 aoc_increment_charge (0L, TRUE); /* add rest to SIM */
365 }
366 break;
367
368 case AOC_START_AOC: /* Advice of Charge information has received for the indicated call. */
369 #ifdef _SIMULATION_
370 TRACE_EVENT ("*** AOC_START_AOC");
371 #endif
372 TRACE_EVENT_P2("AOC started Cid = %u State = %u", Cid, aoc_state);
373
374 if (aoc_state EQ AOC_ENABLE) /* AoC is supported */
375 {
376 limit_reached = FALSE;
377
378 if (cc_aoc_table[Cid].aoc_timer_running)
379 aoc_start_newinfo_existingcall(Cid);
380 else
381 aoc_start_info_newcall(Cid);
382
383 return TRUE;
384 }
385 else /* AoC not supported */
386 {
387 TRACE_EVENT ("AOC not supported");
388 return FALSE;
389 }
390
391 case AOC_SUSPEND_AOC: /* Suspension of Call is indicated. */
392 #ifdef _SIMULATION_
393 TRACE_EVENT ("*** AOC_SUSPEND_AOC");
394 #endif
395 if (aoc_state EQ AOC_ENABLE AND
396 cc_aoc_table[Cid].aoc_timer_running) /* AoC timer is running, then stop it. */
397 {
398 /* save remaining timeslice prior stopping the timer */
399 TIMER_STATUS (aci_handle, (USHORT)(AOC_AOCTIMER+Cid), &cc_aoc_table[Cid].remaining_time);
400 TIMER_STOP (aci_handle, (USHORT)(AOC_AOCTIMER+Cid));
401
402 cc_aoc_table[Cid].aoc_timer_running = FALSE;
403 }
404 break;
405
406 case AOC_RESUME_AOC: /* Resumption of Call is indicated. */
407 #ifdef _SIMULATION_
408 TRACE_EVENT ("*** AOC_RESUME_AOC");
409 #endif
410 if (aoc_state EQ AOC_ENABLE AND
411 aoc_non_zero_cai (Cid))
412 {
413 /* AoC info is available, then start again. calculate the remaining time */
414 TIMER_PSTART (aci_handle, (USHORT)(AOC_AOCTIMER + Cid),
415 cc_aoc_table[Cid].remaining_time,
416 cc_aoc_table[Cid].next_interval);
417 cc_aoc_table[Cid].aoc_timer_running = TRUE;
418
419 aoc_set_time_ut_charge ( Cid, cc_aoc_table[Cid].remaining_time );
420 }
421 break;
422
423 case AOC_CALL_CONNECTED: /* Call active state of a Call is indicated. */
424 #ifdef _SIMULATION_
425 TRACE_EVENT ("*** AOC_CALL_CONNECTED");
426 #endif
427 if (aoc_state EQ AOC_ENABLE AND
428 aoc_non_zero_cai (Cid))
429 {
430 /* AoC info is available, then start send initial CCM value to MMI. */
431 aoc_send_ccm ();
432 }
433 break;
434
435 default:
436 #ifdef _SIMULATION_
437 TRACE_EVENT ("*** Wrong cause ***");
438 #endif
439 break;
440
441 }
442 return TRUE;
443 }
444
445 /*
446 +--------------------------------------------------------------------+
447 | PROJECT: GSM-PS (6147) MODULE: AOC |
448 | STATE : code ROUTINE: aoc_get_values |
449 +--------------------------------------------------------------------+
450
451 PURPOSE : Request of Advice of Charge Values.
452 */
453
454 void aoc_get_values (UBYTE value_type, void * value)
455 {
456 ULONG * longPtr = value;
457 T_puct_raw * raw_puct;
458
459 TRACE_FUNCTION ("aoc_get_values()");
460
461 switch (value_type)
462 {
463 case AOC_CTV: /* Current Timer Value */
464 *longPtr = cct;
465 break;
466
467 case AOC_CCM: /* Current Call Meter Value */
468 #if defined _SIMULATION_
469 TRACE_EVENT_P1("CCM = %u", MC_AOC_ROUND_UP(ccm));
470 #endif
471 *longPtr = MC_AOC_ROUND_UP(ccm);
472 break;
473
474 case AOC_ACM: /* Accumulated Call Meter Value */
475 *longPtr = MC_AOC_ROUND_UP(acm);
476 break;
477
478 case AOC_ACMMAX: /* Maximum Accumulated Call Meter Value */
479 *longPtr = MC_AOC_ROUND_UP(acmmax);
480 break;
481
482 case AOC_PUCT: /* Price per Unit and Currency */
483 aoc_calculate_puct (1L, (T_puct *)value);
484 break;
485
486 case AOC_PUCT_RAW: /* Price per Unit and Currency as RAW data */
487 raw_puct = (T_puct_raw *)value;
488 raw_puct->exp = exp;
489 raw_puct->sexp = sexp;
490 raw_puct->eppu = eppu;
491 memcpy (raw_puct->currency, currency, 4);
492 break;
493
494 case AOC_CCM_PUCT: /* CCM in Price per Unit and Currency */
495 aoc_calculate_puct (MC_AOC_ROUND_UP(ccm), (T_puct *)value);
496 break;
497
498 case AOC_ACM_PUCT: /* ACM in Price per Unit and Currency */
499 aoc_calculate_puct (MC_AOC_ROUND_UP(acm), (T_puct *)value);
500 break;
501
502 case AOC_ACMMAX_PUCT: /* ACMMax in Price per Unit and Currency */
503 aoc_calculate_puct (MC_AOC_ROUND_UP(acmmax), (T_puct *)value);
504 break;
505 }
506 }
507
508 /*
509 +--------------------------------------------------------------------+
510 | PROJECT: GSM-PS (6147) MODULE: AOC |
511 | STATE : code ROUTINE: aoc_set_values |
512 +--------------------------------------------------------------------+
513
514 PURPOSE : Setting of Advice of charge values.
515 */
516
517 T_ACI_RETURN aoc_set_values (T_ACI_CMD_SRC srcId,
518 UBYTE value_type,
519 void *value,
520 UBYTE *password)
521 {
522 TRACE_FUNCTION ("aoc_set_values()");
523
524 /* Store Password, if available and start writing to the SIM Card. */
525 memcpy (pwd, password, 9);
526 act_src_id = srcId;
527
528 /* AOC not supported in SIM, Check for aoc_state return AT_FAIL */
529 if( aoc_state NEQ AOC_ENABLE )
530 {
531 return( AT_FAIL );
532 }
533
534 switch (value_type)
535 {
536 case AOC_ACM:
537 /* Implements Measure 152 */
538 act_value = 0L;
539 aoc_update_sim_datafield ( FIRST_UPDATE, ACT_WR_REC,
540 SIM_ACM, aoc_update_acm_cb );
541 break;
542
543 case AOC_ACMMAX:
544 /* Implements Measure 152 */
545 act_value = (ULONG)value;
546 aoc_update_sim_datafield ( FIRST_UPDATE, ACT_WR_DAT,
547 SIM_ACMMAX, aoc_update_acmmax_cb );
548 break;
549
550 case AOC_PUCT:
551 aoc_update_puct (FIRST_UPDATE, (T_puct *)value);
552 break;
553 }
554
555 return( AT_EXCT );
556 }
557
558 /*
559 +--------------------------------------------------------------------+
560 | PROJECT: GSM-PS (6147) MODULE: AOC |
561 | STATE : code ROUTINE: aoc_check_moc |
562 +--------------------------------------------------------------------+
563
564 PURPOSE : The function checks whether ACM is greater than ACMMax.
565 In this case only emergency calls are allowed for mobile
566 originated call direction.
567 */
568
569 UBYTE aoc_check_moc (void)
570 {
571 TRACE_FUNCTION ("aoc_check_moc()");
572
573 return aoc_check_acm();
574 }
575
576
577 /*
578 +--------------------------------------------------------------------+
579 | PROJECT: GSM-PS (6147) MODULE: AOC |
580 | STATE : code ROUTINE: aoc_ssc |
581 +--------------------------------------------------------------------+
582
583 PURPOSE : Check SIM service status. The value of service nr is
584 extracted from the SIM service table.
585 */
586
587 UBYTE aoc_ssc (UBYTE nr, UBYTE * serv_table)
588 {
589 TRACE_FUNCTION ("aoc_ssc()");
590
591 if (nr > MAX_SRV_TBL*4)
592 {
593 TRACE_ERROR ("serv_table overflow in pb_ssc()");
594 return NO_ALLOCATED;
595 }
596
597 return ( *(serv_table+(nr-1)/4) >> (((nr-1)&3)*2) & 0x03);
598 }
599
600
601 /*
602 +--------------------------------------------------------------------+
603 | PROJECT: GSM-PS (6147) MODULE: AOC |
604 | STATE : code ROUTINE: aoc_read_acm_cb |
605 +--------------------------------------------------------------------+
606
607 PURPOSE : Callback function for reading ACM.
608 */
609
610 void aoc_read_acm_cb(SHORT table_id)
611 {
612 TRACE_FUNCTION ("aoc_read_acm_cb()");
613
614 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
615
616 if (simShrdPrm.atb[table_id].errCode NEQ SIM_NO_ERROR)
617 {
618 /* ACM is not readable, disable set to default values */
619 acm=0L;
620 TRACE_EVENT ("AOC: Card has no ACM field");
621 #ifdef SIM_TOOLKIT
622 if (simShrdPrm.fuRef >= 0)
623 {
624 psaSAT_FUConfirm (simShrdPrm.fuRef, SIM_FU_ERROR);
625 }
626 #endif
627 }
628 else
629 {
630 /* calculate ACM and start reading ACMMax */
631 acm = (sim_data[0]<<16) + (sim_data[1]<<8) + sim_data[2];
632 acm *= 100; /* internal unit is 1/100 */
633 TRACE_EVENT_P1("ACM value = %u", (USHORT)acm);
634 /* Implements Measure 156 and 157 */
635 aoc_read_sim_datafield ( ACT_RD_DAT, SIM_ACMMAX, aoc_read_acmmax_cb, 3 );
636
637 }
638 }
639
640
641 /*
642 +--------------------------------------------------------------------+
643 | PROJECT: GSM-PS (6147) MODULE: AOC |
644 | STATE : code ROUTINE: aoc_read_acmmax_cb |
645 +--------------------------------------------------------------------+
646
647 PURPOSE : Callback function for reading ACMMax.
648 */
649
650 void aoc_read_acmmax_cb(SHORT table_id)
651 {
652 TRACE_FUNCTION ("aoc_read_acmmax_cb()");
653
654 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
655
656 if (simShrdPrm.atb[table_id].errCode EQ SIM_NO_ERROR)
657 {
658 /* calculate ACMMAX and start reading PUCT */
659 acmmax = (sim_data[0]<<16) + (sim_data[1]<<8) + sim_data[2];
660 acmmax *= 100; /* internal unit is 1/100 */
661 TRACE_EVENT_P1("ACMMAX value = %u", (USHORT)acmmax);
662 /* Implements Measure 156 and 157 */
663 aoc_read_sim_datafield ( ACT_RD_DAT, SIM_PUCT, aoc_read_puct_cb, 5 );
664 }
665 else
666 {
667 /* ACMMAX is not readable, disable set to default values */
668 acmmax=0;
669 TRACE_EVENT ("AOC: Card has no ACMmax field");
670 #ifdef SIM_TOOLKIT
671 if (simShrdPrm.fuRef >= 0)
672 {
673 psaSAT_FUConfirm (simShrdPrm.fuRef, SIM_FU_ERROR);
674 }
675 #endif
676 }
677 }
678
679
680 /*
681 +--------------------------------------------------------------------+
682 | PROJECT: GSM-PS (6147) MODULE: AOC |
683 | STATE : code ROUTINE: aoc_read_puct_cb |
684 +--------------------------------------------------------------------+
685
686 PURPOSE : Callback function for reading PUCT.
687 */
688
689 void aoc_read_puct_cb(SHORT table_id)
690 {
691 UBYTE index;
692
693 TRACE_FUNCTION ("aoc_read_puct_cb()");
694 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
695
696 if (simShrdPrm.atb[table_id].errCode EQ SIM_NO_ERROR)
697 {
698 /* calculate PUCT */
699 #if defined WIN32
700 TRACE_EVENT_P2("PUCT %x %x",sim_data[3],sim_data[4]);
701 #endif
702
703 currency [0] = sim_data[0];
704 currency [1] = sim_data[1];
705 currency [2] = sim_data[2];
706 currency [3] = 0;
707 eppu = (sim_data[3]<<4 & 0xFF0) + (sim_data[4] & 0x0F);
708 index = sim_data[4]>>4 & 0x0F;
709 if (index > 15) /* only 0 to 15 */
710 {
711 index = 15;
712 }
713 exp = ppu_values[index][0];
714 sexp = ppu_values[index][1];
715 }
716 else
717 {
718 /* PUCT is not readable, disable set to default values */
719 eppu = exp = sexp = 0;
720 TRACE_EVENT ("AOC: Card has no PUCT field");
721 }
722
723 #ifdef SIM_TOOLKIT
724 if (simShrdPrm.fuRef >= 0)
725 {
726 psaSAT_FUConfirm (simShrdPrm.fuRef, SIM_FU_SUCC_ADD);
727 }
728 #endif
729 }
730
731
732 /*
733 +--------------------------------------------------------------------+
734 | PROJECT: GSM-PS (6147) MODULE: AOC |
735 | STATE : code ROUTINE: aoc_init_calltable |
736 +--------------------------------------------------------------------+
737
738 PURPOSE : Initialisation of the AoC parameters of the call table.
739
740 */
741
742 void aoc_init_calltable (void)
743 {
744 TRACE_FUNCTION ("aoc_init_calltable()");
745
746 /* Initialize AoC parameters and open
747 * the call dependent AoC timer */
748 memset (cc_aoc_table, 0, sizeof (cc_aoc_table));
749
750 /* Initialize AoC Parameter */
751 ccm = 0L;
752 ccm_already_incremented = 0L;
753 acm_increment_flag = 0;
754
755 /* Initialize the Call Timer Variables */
756 cct = 0L;
757 /* act = 0L; */
758 ct_running = 0;
759
760 #ifdef SIM_TOOLKIT
761 simShrdPrm.fuRef = -1;
762 if (!psaSAT_FURegister (aoc_update))
763 {
764 TRACE_EVENT ("FAILED to register the handler aoc_update() for FU");
765 }
766
767 #endif
768 }
769
770 /*
771 +--------------------------------------------------------------------+
772 | PROJECT: GSM-PS (6147) MODULE: AOC |
773 | STATE : code ROUTINE: aoc_timeout |
774 +--------------------------------------------------------------------+
775
776 PURPOSE : A timeout has occured for a timer. The funtion returns
777 TRUE, if it is a call timer or a AoC timer, else FALSE
778 is returned to indicate that the timer has not been
779 processed.
780
781 */
782 UBYTE aoc_timeout (USHORT index)
783 {
784 if (index EQ AOC_CALLTIMER)
785 {
786 /* timeout call timer */
787 aoc_timeout_call_timer ();
788 return TRUE;
789 }
790 else if (index >= AOC_AOCTIMER AND index < AOC_AOCTIMER+MAX_CALL_NR)
791 {
792 /* Check Advice of Charge Timer */
793 aoc_timeout_aoc_timer ((USHORT)(index - AOC_AOCTIMER));
794 return TRUE;
795 }
796 else
797 {
798 /* the timeout is not for AoC */
799 return FALSE;
800 }
801 }
802
803 /*
804 +--------------------------------------------------------------------+
805 | PROJECT: GSM-PS (6147) MODULE : AOC |
806 | STATE : code ROUTINE: aoc_timeout_call_timer |
807 +--------------------------------------------------------------------+
808
809 PURPOSE : the call timer timeout has occured. The CCT and ACT are
810 increased.
811
812 */
813
814 void aoc_timeout_call_timer (void)
815 {
816 int Cid;
817 T_ACI_CMD_SRC idx;
818 UBYTE five_second_have_just_elapsed = FALSE;
819
820 /* TRACE_FUNCTION ("aoc_timeout_call_timer()"); */
821
822 cct++;
823 /* act++; */
824
825 if (acm_increment_flag EQ 1)
826 five_second_have_just_elapsed = TRUE;
827
828 /* Flag to realize 5 second delay for incrementing ACM on the SIM card. */
829 if (acm_increment_flag)
830 acm_increment_flag--;
831
832 /* flush the charge on the SIM, 5 seconds after the last writing,
833 * if there some units to add */
834 if (five_second_have_just_elapsed)
835 aoc_increment_charge (0L, FALSE);
836
837 /* Update the remaining time for running AoC timer */
838 for (Cid=0; Cid<MAX_CALL_NR; Cid++)
839 {
840 if (cc_aoc_table[Cid].aoc_timer_running AND
841 cc_aoc_table[Cid].remaining_time > 0)
842 {
843 TIMER_STATUS (aci_handle, (USHORT)(AOC_AOCTIMER + Cid), &cc_aoc_table[Cid].remaining_time);
844 }
845 }
846
847 for( idx = CMD_SRC_LCL; idx < CMD_SRC_MAX; idx++ )
848 {
849 R_AT( RAT_CTV, idx )( );
850 }
851
852 aoc_set_time_ut_charge ( ACI_NumParmNotPresent, 0L );
853 }
854
855
856 /*
857 +--------------------------------------------------------------------+
858 | PROJECT: GSM-PS (6147) MODULE : AOC |
859 | STATE : code ROUTINE: aoc_timeout_aoc_timer |
860 +--------------------------------------------------------------------+
861
862 PURPOSE : An AoC timer timeout has occured.
863
864 */
865
866 void aoc_timeout_aoc_timer (SHORT Cid)
867 {
868 SHORT dummy_waitId; /* holds call waiting id */
869 T_ACI_CMD_SRC src_dummy = CMD_SRC_NONE;
870
871 TRACE_FUNCTION ("aoc_timeout_aoc_timer()");
872
873 if ((aoc_check_acm () EQ FALSE) AND
874 (cc_aoc_table[Cid].aoci_active EQ FALSE) AND
875 (cc_aoc_table[Cid].next_unit) ) /* check if the next intervall would charge (time related charge > 0)*/
876 {
877 /* ACM exceeds ACMMax, and call is not free, so disconnect call */
878 TRACE_EVENT ("ACM > ACMMax");
879 cmhCC_ClearCall (Cid,
880 CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_ACI_ORIGINATING_ENTITY, MNCC_CAUSE_ACM_MAX),
881 src_dummy, AT_CMD_NONE, &dummy_waitId);
882 }
883 //TISH, patch for OMAPS00128043
884 //start
885 else if (ccShrdPrm.ctb[Cid]->prio EQ 1) //PRIO_EMERG_CALL
886 return;
887 //end
888 else
889 {
890 /* e3 may have changed during the current intervall but recalc is already done */
891 aoc_increment_charge (cc_aoc_table[Cid].next_unit, FALSE);
892 if (cc_aoc_table[Cid].new_data_avail)
893 {
894 /* New Parameter available */
895 /* 4.3.e) bring parameters held in abeyance into operation */
896 if (cc_aoc_table[Cid].e_next_bitmap & E1_CHANGED) cc_aoc_table[Cid].e1 = cc_aoc_table[Cid].e1_next;
897 if (cc_aoc_table[Cid].e_next_bitmap & E2_CHANGED) cc_aoc_table[Cid].e2 = cc_aoc_table[Cid].e2_next;
898 if (cc_aoc_table[Cid].e_next_bitmap & E3_CHANGED) cc_aoc_table[Cid].e3 = cc_aoc_table[Cid].e3_next;
899 if (cc_aoc_table[Cid].e_next_bitmap & E7_CHANGED) cc_aoc_table[Cid].e7 = cc_aoc_table[Cid].e7_next;
900
901 aoc_calculate_charging_parameter_part2 (Cid);
902
903 /* timing has changed? */
904 if (cc_aoc_table[Cid].e_next_bitmap & (E2_CHANGED | E7_CHANGED))
905 {
906 /* reschedule timer */
907 TIMER_STOP (aci_handle, (USHORT)(AOC_AOCTIMER + Cid));
908 TIMER_PSTART (aci_handle, (USHORT)(AOC_AOCTIMER + Cid), cc_aoc_table[Cid].first_interval,
909 cc_aoc_table[Cid].next_interval);
910 cc_aoc_table[Cid].remaining_time = cc_aoc_table[Cid].first_interval;
911 }
912 else
913 /* ask the timer since we could already be ahead */
914 /* cc_aoc_table[Cid].remaining_time = cc_aoc_table[Cid].next_interval; */
915 TIMER_STATUS (aci_handle, (USHORT)(AOC_AOCTIMER + Cid), &cc_aoc_table[Cid].remaining_time);
916
917 cc_aoc_table[Cid].new_data_avail = FALSE;
918 cc_aoc_table[Cid].e_next_bitmap &= ~(E1_CHANGED | E2_CHANGED | E3_CHANGED | E7_CHANGED);
919 }
920 else
921 {
922 /* re-initialise remaining time counter */
923 /* ask the timer since we could already be ahead */
924 /* cc_aoc_table[Cid].remaining_time = cc_aoc_table[Cid].next_interval; */
925 TIMER_STATUS (aci_handle, (USHORT)(AOC_AOCTIMER + Cid), &cc_aoc_table[Cid].remaining_time);
926 }
927
928 /* check if timer had e2=0 and e7>= */
929 if (cc_aoc_table[Cid].next_interval == 0)
930 {
931 cc_aoc_table[Cid].aoc_timer_running = FALSE;
932 /* cc_aoc_table[Cid].aoci_active = FALSE;*/
933 cc_aoc_table[Cid].remaining_time = 0L;
934 aoc_set_time_ut_charge ( Cid, (ULONG)ACI_NumParmNotPresent );
935 }
936 else
937 aoc_set_time_ut_charge ( Cid, cc_aoc_table[Cid].remaining_time );
938 }
939 }
940
941
942 /*
943 +--------------------------------------------------------------------+
944 | PROJECT: GSM-PS (6147) MODULE : AOC |
945 | STATE : code ROUTINE: aoc_start_aoc_timer |
946 +--------------------------------------------------------------------+
947
948 PURPOSE : AoC is started for the indicated call or
949 new AoC parameter are received.
950 */
951
952 void aoc_start_newinfo_existingcall (SHORT Cid)
953 {
954 UBYTE no_more_timer_running = FALSE;
955 T_ACI_CMD_SRC src_dummy = CMD_SRC_NONE;
956 SHORT dummy_waitId;
957
958 TRACE_FUNCTION ("aoc_start_newinfo_existingcall()");
959
960 if(!aoc_non_zero_cai (Cid))
961 {
962 return;
963 }
964
965 if (cc_aoc_table[Cid].aoc_timer_running EQ FALSE)
966 {
967 /* New Parameter available */
968 /* 4.3.e) bring parameters held in abeyance into operation */
969 if (cc_aoc_table[Cid].e_next_bitmap & E1_CHANGED) cc_aoc_table[Cid].e1 = cc_aoc_table[Cid].e1_next;
970 if (cc_aoc_table[Cid].e_next_bitmap & E2_CHANGED) cc_aoc_table[Cid].e2 = cc_aoc_table[Cid].e2_next;
971 if (cc_aoc_table[Cid].e_next_bitmap & E3_CHANGED) cc_aoc_table[Cid].e3 = cc_aoc_table[Cid].e3_next;
972 if (cc_aoc_table[Cid].e_next_bitmap & E7_CHANGED) cc_aoc_table[Cid].e7 = cc_aoc_table[Cid].e7_next;
973
974 aoc_calculate_charging_parameter_part2 (Cid);
975
976 /* vsi_t_status (VSI_CALLER (USHORT)(AOC_AOCTIMER + Cid), &cc_aoc_table[Cid].remaining_time);*/
977
978 cc_aoc_table[Cid].new_data_avail = FALSE;
979 cc_aoc_table[Cid].e_next_bitmap &= ~(E1_CHANGED | E2_CHANGED | E3_CHANGED | E7_CHANGED);
980 no_more_timer_running = TRUE;
981 }
982
983
984 /* charging information available, else wait for end of interval.*/
985 if ( (cc_aoc_table[Cid].next_interval EQ 0) AND
986 ((cc_aoc_table[Cid].first_interval EQ 0) OR (cc_aoc_table[Cid].remaining_time EQ 0)) )
987 {
988 /* if CDUR is not actively timing (i.e. due to e2 being zero,
989 * e7 being zero or the processing of e7 has been completed),
990 * then a new value of e2 and/or e7 is applied immediately as per a normal call. */
991 no_more_timer_running = TRUE;
992 }
993
994 /* charging information available, else wait for end of interval. */
995 if ((aoc_check_acm () EQ TRUE) OR
996 (cc_aoc_table[Cid].aoci_active EQ TRUE))
997 {
998 /* ACM has not exceeded ACMMax then calculate charging parameters and increment inital charge */
999 aoc_calculate_charging_parameter_part1 (Cid);
1000 aoc_increment_initial_charge (Cid);
1001 cc_aoc_table[Cid].new_data_avail = TRUE;
1002 }
1003 else
1004 {
1005 /*
1006 * ACM has reached ACM max, the call is kept till the next interval elapses
1007 * but if there is no timer running, for a new reception of CAI non zero,
1008 * we behave as on reception of a first CAI for a call, if acm has reached ACM max,
1009 * we disconnect the call.
1010 * "Rec 2.24 : 4.2.2 ACM : If the ACM max is valid and the ACM is equal to or greater
1011 * than the value of ACM max, and an incoming call is received and subsequently
1012 * a non-zero CAI is received for that call, then the call shall be terminated by
1013 * the ME with an appropriate indication given to the user."
1014 */
1015 if (no_more_timer_running)
1016 {
1017 /* if we are here, it means that it's a non-zero CAI, so no need to test it again */
1018 TRACE_EVENT("no more timer running clear call");
1019 cmhCC_ClearCall (Cid,
1020 CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_ACI_ORIGINATING_ENTITY, MNCC_CAUSE_ACM_MAX),
1021 src_dummy, AT_CMD_NONE, &dummy_waitId);
1022 }
1023 }
1024
1025 if (no_more_timer_running)
1026 {
1027 /* New Parameter available */
1028 aoc_calculate_charging_parameter_part2 (Cid);
1029
1030 cc_aoc_table[Cid].new_data_avail = FALSE;
1031 TIMER_STOP (aci_handle, (USHORT)(AOC_AOCTIMER + Cid));
1032 TIMER_PSTART (aci_handle, (USHORT)(AOC_AOCTIMER + Cid), cc_aoc_table[Cid].first_interval,
1033 cc_aoc_table[Cid].next_interval);
1034 /* re-initialise remaining time counter for first interval */
1035 cc_aoc_table[Cid].remaining_time = cc_aoc_table[Cid].first_interval;
1036 }
1037 }
1038
1039 void aoc_start_info_newcall (SHORT Cid)
1040 {
1041 T_ACI_CMD_SRC src_dummy = CMD_SRC_NONE;
1042 SHORT dummy_waitId;
1043
1044 TRACE_FUNCTION ("aoc_start_info_newcall()");
1045
1046 if( !aoc_non_zero_cai(Cid) )
1047 {
1048 return;
1049 }
1050 /* charging information available */
1051
1052 if( (aoc_check_acm() EQ FALSE) AND
1053 (cc_aoc_table[Cid].aoci_active EQ FALSE) )
1054 {
1055 /* ACM exceeds ACMMax, disconnect call */
1056 TRACE_EVENT("clear call on initial call");
1057 cmhCC_ClearCall (Cid,
1058 CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_ACI_ORIGINATING_ENTITY, MNCC_CAUSE_ACM_MAX),
1059 src_dummy,
1060 AT_CMD_NONE,
1061 &dummy_waitId);
1062 return;
1063 }
1064
1065 /* ACM has not exceeded ACMMax then calculate charging parameters,
1066 * increment inital charge and start AoC Timer. */
1067 {
1068 /* bring new parameters into operation */
1069
1070 if (cc_aoc_table[Cid].e_next_bitmap & E1_CHANGED) cc_aoc_table[Cid].e1 = cc_aoc_table[Cid].e1_next;
1071 if (cc_aoc_table[Cid].e_next_bitmap & E2_CHANGED) cc_aoc_table[Cid].e2 = cc_aoc_table[Cid].e2_next;
1072 if (cc_aoc_table[Cid].e_next_bitmap & E3_CHANGED) cc_aoc_table[Cid].e3 = cc_aoc_table[Cid].e3_next;
1073 if (cc_aoc_table[Cid].e_next_bitmap & E7_CHANGED) cc_aoc_table[Cid].e7 = cc_aoc_table[Cid].e7_next;
1074
1075 /* cc_aoc_table[Cid].new_data_avail = FALSE;*/
1076 cc_aoc_table[Cid].e_next_bitmap &= ~(E1_CHANGED | E2_CHANGED | E3_CHANGED | E7_CHANGED);
1077 }
1078
1079 aoc_calculate_charging_parameter (Cid);
1080 aoc_increment_initial_charge (Cid);
1081
1082 if(cc_aoc_table[Cid].first_interval)
1083 {
1084 TIMER_PSTART (aci_handle, (USHORT)(AOC_AOCTIMER + Cid), cc_aoc_table[Cid].first_interval,
1085 cc_aoc_table[Cid].next_interval);
1086
1087 cc_aoc_table[Cid].aoc_timer_running = TRUE;
1088 }
1089
1090 cc_aoc_table[Cid].new_data_avail = FALSE;
1091 cc_aoc_table[Cid].remaining_time = cc_aoc_table[Cid].first_interval;
1092
1093 aoc_set_time_ut_charge ( Cid, cc_aoc_table[Cid].remaining_time );
1094 }
1095
1096
1097 /*
1098 +--------------------------------------------------------------------+
1099 | PROJECT: GSM-PS (6147) MODULE : AOC |
1100 | STATE : code ROUTINE: aoc_non_zero_cai |
1101 +--------------------------------------------------------------------+
1102
1103 PURPOSE : Checks whether the Advice of Charge parameter indicate
1104 a free call (parameters are not available or equal zero).
1105 */
1106
1107 UBYTE aoc_non_zero_cai (SHORT Cid)
1108 {
1109 TRACE_FUNCTION ("aoc_non_zero_cai()");
1110
1111 /* AoC = e3 * { e4 + e1*INT(CDUR/(e7,e2)) + e5*INT(SEG/e6) }
1112 * = scaling * { constant + time related + data related}
1113 *
1114 * Ref. GSM 2.24 Section 4 Functional operation in MS */
1115
1116 if ((cc_aoc_table[Cid].e3 EQ 0) OR
1117 ((cc_aoc_table[Cid].e1 EQ 0) AND (cc_aoc_table[Cid].e4 EQ 0) /* AND (cc_aoc_table[Cid].e5 EQ 0) */ ))
1118 /* e5, e6 is currently not supported */
1119 return FALSE;
1120
1121 return TRUE;
1122 }
1123
1124 /*
1125 +--------------------------------------------------------------------+
1126 | PROJECT: GSM-PS (6147) MODULE : AOC |
1127 | STATE : code ROUTINE: aoc_check_acm |
1128 +--------------------------------------------------------------------+
1129
1130 PURPOSE : The function indicates whether ACM exceeds ACMMax.
1131
1132 */
1133
1134 UBYTE aoc_check_acm (void)
1135 {
1136 TRACE_FUNCTION ("aoc_check_acm()");
1137
1138 TRACE_EVENT_P2("ACM=%u ACMMax=%u", acm, acmmax);
1139
1140 if (acmmax NEQ 0)
1141 {
1142 /*
1143 * ACMMax is valid
1144 */
1145 if (acm >= acmmax)
1146 {
1147 causeMod = P_CEER_sim; /* Set the module to sim to report ceer */
1148 causeCeer = P_CEER_ACMMaxReachedOrExceeded; /* Set proprietary cause */
1149 return FALSE; /* ACM exceeds ACMMax */
1150 }
1151 else
1152 {
1153 causeMod = P_CEER_mod; /* Clear module which is set */
1154 causeCeer = P_CEER_NotPresent; /* Clear proprietary cause */
1155 }
1156 }
1157 return TRUE;
1158 }
1159
1160 /*
1161 +--------------------------------------------------------------------+
1162 | PROJECT: GSM-PS (6147) MODULE : AOC |
1163 | STATE : code ROUTINE: aoc_calculate_charging_params_part1 |
1164 +--------------------------------------------------------------------+
1165
1166 PURPOSE : The function calculates an initial rime related charge
1167
1168 */
1169
1170 static void aoc_calculate_charging_parameter_part1 (SHORT Cid)
1171 {
1172 TRACE_FUNCTION ("aoc_calculate_charging_parameter_part1()");
1173
1174 /*
1175 * Calculation for inital charge
1176 */
1177 cc_aoc_table[Cid].first_unit =
1178 ((ULONG)cc_aoc_table[Cid].e3 * (ULONG)cc_aoc_table[Cid].e4) / 10;
1179 }
1180
1181 /*
1182 +--------------------------------------------------------------------+
1183 | PROJECT: GSM-PS (6147) MODULE : AOC |
1184 | STATE : code ROUTINE: aoc_calculate_charging_params_part2 |
1185 +--------------------------------------------------------------------+
1186
1187 PURPOSE : The function calculates the interval length and the
1188 number of units which will be incremented at interval
1189 end.
1190
1191 */
1192
1193 static void aoc_calculate_charging_parameter_part2 (SHORT Cid)
1194 {
1195
1196 TRACE_FUNCTION ("aoc_calculate_charging_parameter_part2()");
1197
1198 /* Calculation of first time interval */
1199 cc_aoc_table[Cid].first_interval = (T_TIME) E_IN_MS(cc_aoc_table[Cid].e7);
1200
1201 /* Calculation of next time interval */
1202 cc_aoc_table[Cid].next_interval = (T_TIME) E_IN_MS(cc_aoc_table[Cid].e2);
1203
1204
1205 /* 4.3.a) E7 is not available or E7 is equal zero then use E2 */
1206 if (cc_aoc_table[Cid].first_interval EQ 0L)
1207 cc_aoc_table[Cid].first_interval = cc_aoc_table[Cid].next_interval;
1208
1209 /*
1210 * Calculation for charge of next units
1211 */
1212 cc_aoc_table[Cid].next_unit =
1213 ((ULONG)cc_aoc_table[Cid].e3 * (ULONG)cc_aoc_table[Cid].e1) / 10;
1214 }
1215
1216 /*
1217 +--------------------------------------------------------------------+
1218 | PROJECT: GSM-PS (6147) MODULE : AOC |
1219 | STATE : code ROUTINE: aoc_calculate_charging_params |
1220 +--------------------------------------------------------------------+
1221
1222 PURPOSE : The function calculates the interval length and the
1223 number of units which will be incremented at interval
1224 end.
1225
1226 */
1227
1228 void aoc_calculate_charging_parameter (SHORT Cid)
1229 {
1230 TRACE_FUNCTION ("aoc_calculate_charging_parameter()");
1231
1232 aoc_calculate_charging_parameter_part1 (Cid);
1233 aoc_calculate_charging_parameter_part2 (Cid);
1234 }
1235
1236 /*
1237 +--------------------------------------------------------------------+
1238 | PROJECT: GSM-PS (6147) MODULE : AOC |
1239 | STATE : code ROUTINE: aoc_increment_initial_charge |
1240 +--------------------------------------------------------------------+
1241
1242 PURPOSE : The function increments the inital charge to CCM and ACM.
1243
1244 */
1245
1246 void aoc_increment_initial_charge (SHORT Cid)
1247 {
1248 TRACE_FUNCTION ("aoc_increment_inital_charge()");
1249
1250 if (cc_aoc_table[Cid].first_unit)
1251 {
1252 /*
1253 * if initial charge is available, charge it and
1254 * inform MMI about it although it has no charge.
1255 */
1256 aoc_increment_charge (cc_aoc_table[Cid].first_unit, FALSE);
1257 cc_aoc_table[Cid].first_unit = 0L;
1258 }
1259 aoc_send_ccm ();
1260 }
1261
1262
1263 /*
1264 +--------------------------------------------------------------------+
1265 | PROJECT: GSM-PS (6147) MODULE : AOC |
1266 | STATE : code ROUTINE: aoc_increment_charge |
1267 +--------------------------------------------------------------------+
1268
1269 PURPOSE : The function increments charge to CCM and ACM. If necessary
1270 the ACM is incremented on the SIM card.
1271
1272 */
1273
1274 void aoc_increment_charge (ULONG charge, UBYTE ever)
1275 {
1276 SHORT table_id;
1277 ULONG acm_for_sim;
1278
1279 TRACE_FUNCTION ("aoc_increment_charge()");
1280
1281 /*
1282 * Both CCM is incremented
1283 */
1284 ccm += charge;
1285
1286 if (ccm > (0xFFFFFF * 100)) /* limit to 0xffffff since datafeld is only 3 bytes long.*/
1287 ccm = (0xFFFFFF * 100);
1288
1289
1290
1291 TRACE_EVENT_P2("NewCCM %u charge %u", ccm, charge);
1292
1293 /*
1294 * the update on the SIM is the difference between the rounded up value of the current CCM
1295 * and the old CCM (already rounded up)
1296 */
1297 acm_for_sim = MC_AOC_ROUND_UP(ccm) - MC_AOC_ROUND_UP(ccm_already_incremented);
1298
1299 if (acm_for_sim)
1300 {
1301 if (acm_increment_flag EQ 0 OR ever)
1302 {
1303 /*
1304 * Nothing stored in the last five seconds on the SIM card
1305 * and now something to store
1306 */
1307 acm_increment_flag = 5;
1308
1309 ccm_already_incremented += acm_for_sim * 100;
1310
1311 acm += acm_for_sim * 100;
1312
1313 if (acm > (0xFFFFFF * 100))
1314 acm = (0xFFFFFF * 100);
1315
1316 if (limit_reached EQ FALSE)
1317 {
1318 /*
1319 * request table id for SIM SAP access
1320 */
1321 table_id = psaSIM_atbNewEntry();
1322
1323 if(table_id NEQ NO_ENTRY)
1324 {
1325 /*
1326 * Fill formular for access
1327 *
1328 * set datafield type = Binary field
1329 * set datafield = SIM_ACM
1330 * set offset = 0 Bytes
1331 * set length = 3 Bytes
1332 */
1333 simShrdPrm.atb[table_id].accType = ACT_INC_DAT;
1334 simShrdPrm.atb[table_id].v_path_info = FALSE;
1335 simShrdPrm.atb[table_id].reqDataFld = SIM_ACM;
1336 simShrdPrm.atb[table_id].dataOff = 0;
1337 simShrdPrm.atb[table_id].dataLen = 3;
1338 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
1339 simShrdPrm.atb[table_id].exchData = sim_data;
1340 simShrdPrm.atb[table_id].rplyCB = aoc_increment_cb;
1341 simShrdPrm.aId = table_id;
1342 sim_data[0] = (UBYTE)(acm_for_sim >> 16);
1343 sim_data[1] = (UBYTE)(acm_for_sim >> 8);
1344 sim_data[2] = (UBYTE)(acm_for_sim & 0xFF);
1345
1346 TRACE_EVENT_P1("ACM increment = %u", acm_for_sim);
1347
1348 if(psaSIM_AccessSIMData() < 0)
1349 {
1350 TRACE_EVENT("FATAL ERROR");
1351 }
1352 }
1353 }
1354 }
1355 aoc_send_ccm ();
1356 }
1357 }
1358
1359
1360 /*
1361 +--------------------------------------------------------------------+
1362 | PROJECT: GSM-PS (6147) MODULE: AOC |
1363 | STATE : code ROUTINE: aoc_increment_cb |
1364 +--------------------------------------------------------------------+
1365
1366 PURPOSE : Callback function for incrementing ACM.
1367
1368 */
1369
1370 void aoc_increment_cb(SHORT table_id)
1371 {
1372 UBYTE i;
1373 SHORT dummy_waitId; /* holds call waiting id */
1374 T_ACI_CMD_SRC src_dummy = CMD_SRC_NONE;
1375
1376
1377 TRACE_FUNCTION ("aoc_increment_cb()");
1378
1379 switch (simShrdPrm.atb[table_id].errCode)
1380 {
1381 case SIM_NO_ERROR:
1382 break;
1383 case SIM_CAUSE_MAX_INCREASE:
1384 /*
1385 * ACM has reached limit 0xFFFFFF,
1386 * If ACMMAX is zero, ACM shall be cleared
1387 * by MMI. Only an indication is forwarded
1388 * to MMI, else the call is released.
1389 */
1390 if (acmmax EQ 0)
1391 {
1392 limit_reached = TRUE;
1393 R_AT( RAT_CME, simEntStat.entOwn )
1394 ( AT_CMD_CACM, CME_ERR_AcmResetNeeded );
1395 break;
1396 }
1397 /*lint -fallthrough */
1398 default:
1399 /*
1400 * ACM increment is not successfull
1401 */
1402 aoc_state = AOC_DISABLE;
1403
1404 /*
1405 * release all chargeable calls
1406 */
1407 for (i=0;i<MAX_CALL_NR;i++)
1408 {
1409 if (aoc_non_zero_cai(i))
1410 {
1411 cmhCC_ClearCall (i,
1412 CAUSE_MAKE(DEFBY_STD, ORIGSIDE_MS, MNCC_ACI_ORIGINATING_ENTITY, MNCC_CAUSE_ACM_MAX),
1413 src_dummy, AT_CMD_NONE,
1414 &dummy_waitId);
1415 }
1416 }
1417 break;
1418 }
1419 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1420 }
1421
1422 /*
1423 +--------------------------------------------------------------------+
1424 | PROJECT: GSM-PS (6147) MODULE: AOC |
1425 | STATE : code ROUTINE: aoc_calculate_puct |
1426 +--------------------------------------------------------------------+
1427
1428 PURPOSE : Calculate counter in PUCT.
1429
1430 */
1431
1432 void aoc_calculate_puct (ULONG value, T_puct * result)
1433 {
1434 TRACE_FUNCTION ("aoc_calculate_puct()");
1435 #if defined WIN32
1436 {
1437 TRACE_EVENT_P1("EPPU %u",eppu);
1438 TRACE_EVENT_P1("SEXP %u",sexp);
1439 TRACE_EVENT_P1("EXP %u",exp);
1440 TRACE_EVENT_P1("VAL %u",value);
1441 }
1442 #endif
1443 /*
1444 * copy currency
1445 */
1446 memcpy (result->currency, currency, 4);
1447
1448 /*
1449 * Multiply counter value with elementary price per unit
1450 */
1451 value *= eppu;
1452 /*
1453 * If sexp is set divide by logarithm of ten, else multiply
1454 */
1455 if (sexp)
1456 {
1457 value *= 1000; /* internal calculation is 1/1000 unit */
1458 value /= exp; /* to support e-3 to e-1 */
1459 sprintf ((char *) result->value, "%u.%03u", value / 1000, value % 1000);
1460 }
1461 else
1462 {
1463 value *= exp;
1464 sprintf ((char *) result->value, "%u", value );
1465 }
1466 }
1467
1468
1469 /*
1470 +--------------------------------------------------------------------+
1471 | PROJECT: GSM-PS (6147) MODULE : AOC |
1472 | STATE : code ROUTINE: aoc_update_acm |
1473 +--------------------------------------------------------------------+
1474
1475 PURPOSE : The function tries to reset the ACM field on the SIM card.
1476
1477 */
1478
1479 void aoc_update_acm (UBYTE operation, ULONG value)
1480 {
1481 SHORT table_id;
1482
1483 TRACE_FUNCTION ("aoc_update_acm()");
1484
1485 /*
1486 * request table id for SIM SAP access
1487 */
1488 table_id = psaSIM_atbNewEntry();
1489 act_upd_op = operation;
1490
1491 if(table_id NEQ NO_ENTRY)
1492 {
1493 switch (operation)
1494 {
1495 case FIRST_UPDATE:
1496 /*
1497 * This is the first access to ACM. It may fail,
1498 * because PIN2 is needed.
1499 */
1500 act_value = 0L;
1501 /*lint -fallthrough*/
1502 case SECOND_UPDATE:
1503 /*
1504 * This is the second access to ACM after PIN entering.
1505 */
1506 simShrdPrm.atb[table_id].accType = ACT_WR_REC;
1507 simShrdPrm.atb[table_id].v_path_info = FALSE;
1508 simShrdPrm.atb[table_id].reqDataFld = SIM_ACM;
1509 simShrdPrm.atb[table_id].dataOff = 0;
1510 simShrdPrm.atb[table_id].dataLen = 3;
1511 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
1512 simShrdPrm.atb[table_id].exchData = sim_data;
1513 simShrdPrm.atb[table_id].rplyCB = aoc_update_acm_cb;
1514 simShrdPrm.aId = table_id;
1515 sim_data[0] = (UBYTE)(act_value >> 16);
1516 sim_data[1] = (UBYTE)(act_value >> 8);
1517 sim_data[2] = (UBYTE)(act_value & 0xFF);
1518
1519 if(psaSIM_AccessSIMData() < 0)
1520 {
1521 TRACE_EVENT("FATAL ERROR");
1522 }
1523 break;
1524 }
1525 }
1526 }
1527
1528 /*
1529 +--------------------------------------------------------------------+
1530 | PROJECT: GSM-PS (6147) MODULE: AOC |
1531 | STATE : code ROUTINE: aoc_update_acm_cb |
1532 +--------------------------------------------------------------------+
1533
1534 PURPOSE : Callback function for updating ACM.
1535
1536 */
1537
1538 void aoc_update_acm_cb(SHORT table_id)
1539 {
1540
1541 TRACE_FUNCTION ("aoc_update_acm_cb()");
1542 /* Implements Measure 213 */
1543 aoc_update_sim_datafield_cb( table_id, AT_CMD_CACM );
1544 }
1545
1546
1547 /*
1548 +--------------------------------------------------------------------+
1549 | PROJECT: GSM-PS (6147) MODULE : AOC |
1550 | STATE : code ROUTINE: aoc_update_acmmax |
1551 +--------------------------------------------------------------------+
1552
1553 PURPOSE : The function tries to set the ACMMAX field on the SIM card.
1554
1555 */
1556
1557 void aoc_update_acmmax (UBYTE operation, ULONG value)
1558 {
1559 SHORT table_id;
1560
1561 TRACE_FUNCTION ("aoc_update_acmmax()");
1562
1563 /*
1564 * request table id for SIM SAP access
1565 */
1566 table_id = psaSIM_atbNewEntry();
1567 act_upd_op = operation;
1568
1569 if(table_id NEQ NO_ENTRY)
1570 {
1571 switch (operation)
1572 {
1573 case FIRST_UPDATE:
1574 /*
1575 * This is the first access to ACMMAX. It may fail,
1576 * because PIN2 is needed.
1577 */
1578 act_value = value;
1579 /*lint -fallthrough*/
1580 case SECOND_UPDATE:
1581 /*
1582 * This is the second access to ACMMAX after PIN entering.
1583 */
1584 simShrdPrm.atb[table_id].accType = ACT_WR_DAT;
1585 simShrdPrm.atb[table_id].v_path_info = FALSE;
1586 simShrdPrm.atb[table_id].reqDataFld = SIM_ACMMAX;
1587 simShrdPrm.atb[table_id].dataOff = 0;
1588 simShrdPrm.atb[table_id].dataLen = 3;
1589 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
1590 simShrdPrm.atb[table_id].exchData = sim_data;
1591 simShrdPrm.atb[table_id].rplyCB = aoc_update_acmmax_cb;
1592 simShrdPrm.aId = table_id;
1593 sim_data[0] = (UBYTE)(act_value >> 16);
1594 sim_data[1] = (UBYTE)(act_value >> 8);
1595 sim_data[2] = (UBYTE)(act_value & 0xFF);
1596
1597 if(psaSIM_AccessSIMData() < 0)
1598 {
1599 TRACE_EVENT("FATAL ERROR");
1600 }
1601 break;
1602 }
1603 }
1604 }
1605
1606 /*
1607 +--------------------------------------------------------------------+
1608 | PROJECT: GSM-PS (6147) MODULE: AOC |
1609 | STATE : code ROUTINE: aoc_update_acmmax_cb |
1610 +--------------------------------------------------------------------+
1611
1612 PURPOSE : Callback function for updating ACMMax.
1613
1614 */
1615
1616 void aoc_update_acmmax_cb(SHORT table_id)
1617 {
1618
1619 TRACE_FUNCTION ("aoc_update_acmmax_cb()");
1620 /* Implements Measure 213 */
1621 aoc_update_sim_datafield_cb( table_id, AT_CMD_CAMM );
1622 }
1623
1624 /*
1625 +--------------------------------------------------------------------+
1626 | PROJECT: GSM-PS (6147) MODULE : AOC |
1627 | STATE : code ROUTINE: aoc_update_puct |
1628 +--------------------------------------------------------------------+
1629
1630 PURPOSE : The function tries to modify the PUCT field on the SIM card.
1631
1632 */
1633
1634 void aoc_update_puct (UBYTE operation, T_puct * value)
1635 {
1636 SHORT table_id;
1637
1638 TRACE_FUNCTION ("aoc_update_puct()");
1639
1640 /*
1641 * request table id for SIM SAP access
1642 */
1643 table_id = psaSIM_atbNewEntry();
1644 act_upd_op = operation;
1645
1646 if(table_id NEQ NO_ENTRY)
1647 {
1648 switch (operation)
1649 {
1650 case FIRST_UPDATE:
1651 /*
1652 * This is the first access to PUCT. It may fail,
1653 * because PIN2 is needed.
1654 */
1655 if (aoc_set_puct_values (value) EQ FALSE)
1656 {
1657 R_AT( RAT_CME, simEntStat.entOwn )
1658 ( AT_CMD_CPUC, CME_ERR_OpNotAllow );
1659
1660 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1661 return;
1662 }
1663 /*lint -fallthrough*/
1664 case SECOND_UPDATE:
1665 /*
1666 * This is the second access to PUCT after PIN entering.
1667 */
1668 simShrdPrm.atb[table_id].accType = ACT_WR_DAT;
1669 simShrdPrm.atb[table_id].v_path_info = FALSE;
1670 simShrdPrm.atb[table_id].reqDataFld = SIM_PUCT;
1671 simShrdPrm.atb[table_id].dataOff = 0;
1672 simShrdPrm.atb[table_id].dataLen = 5;
1673 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
1674 simShrdPrm.atb[table_id].exchData = sim_data;
1675 simShrdPrm.atb[table_id].rplyCB = aoc_update_puct_cb;
1676 simShrdPrm.aId = table_id;
1677 if(psaSIM_AccessSIMData() < 0)
1678 {
1679 TRACE_EVENT("FATAL ERROR");
1680 }
1681 break;
1682 }
1683 }
1684 }
1685
1686 /*
1687 +--------------------------------------------------------------------+
1688 | PROJECT: GSM-PS (6147) MODULE: AOC |
1689 | STATE : code ROUTINE: aoc_update_puct_cb |
1690 +--------------------------------------------------------------------+
1691
1692 PURPOSE : Callback function for updating PUCT.
1693
1694 */
1695
1696 void aoc_update_puct_cb(SHORT table_id)
1697 {
1698 T_SIM_SET_PRM * pSIMSetPrm; /* points to MM parameter set */
1699 UBYTE index;
1700
1701 TRACE_FUNCTION ("aoc_update_puct_cb()");
1702
1703 switch (simShrdPrm.atb[table_id].errCode)
1704 {
1705 case SIM_NO_ERROR:
1706 /*
1707 * No error has occured, read ACM etc. again from SIM Card
1708 */
1709 currency [0] = sim_data[0];
1710 currency [1] = sim_data[1];
1711 currency [2] = sim_data[2];
1712 currency [3] = 0;
1713 eppu = (sim_data[3]<<4 & 0xFF0) + (sim_data[4] & 0x0F);
1714 index = sim_data[4]>>4 & 0x0F;
1715
1716 if (index > 15) /* only 0 to 15 */
1717 {
1718 index = 15;
1719 }
1720
1721 exp = ppu_values[index][0];
1722 sexp = ppu_values[index][1];
1723
1724 simEntStat.curCmd = AT_CMD_NONE;
1725 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1726 R_AT( RAT_OK, simEntStat.entOwn) (AT_CMD_CPUC );
1727 aoc_sms ();
1728 break;
1729 case SIM_CAUSE_PIN2_EXPECT:
1730 /*
1731 * error has occured, maybe PIN2 is needed
1732 */
1733 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1734 if (strlen ((char *) pwd) AND
1735 act_upd_op EQ FIRST_UPDATE)
1736 {
1737 /*
1738 * Password is available and
1739 * it is the first update, then
1740 * try to verify PIN2
1741 */
1742 act_upd_op = VERIFY_PWD;
1743 pSIMSetPrm = &simShrdPrm.setPrm[act_src_id];
1744
1745 cmhSIM_FillInPIN ( (char *) pwd, pSIMSetPrm -> curPIN, PIN_LEN);
1746 pSIMSetPrm -> PINType = PHASE_2_PIN_2;
1747 simEntStat.curCmd = AT_CMD_CPUC;
1748 simShrdPrm.owner = (T_OWN)act_src_id;
1749 simEntStat.entOwn = act_src_id;
1750
1751 if ( psaSIM_VerifyPIN() < 0 ) /* verify PIN */
1752 {
1753 TRACE_EVENT( "FATAL RETURN psaSIM in +CAMM" );
1754 }
1755 }
1756 else
1757 {
1758 /*
1759 * PIN2 not available or second attempt
1760 */
1761 simEntStat.curCmd = AT_CMD_NONE;
1762 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1763 if (act_upd_op EQ FIRST_UPDATE)
1764 {
1765 R_AT( RAT_CME, simEntStat.entOwn )
1766 ( AT_CMD_CPUC, CME_ERR_SimPin2Req );
1767 }
1768 else
1769 {
1770 R_AT( RAT_CME, simEntStat.entOwn )
1771 ( AT_CMD_CPUC, CME_ERR_WrongPasswd );
1772 }
1773 }
1774 break;
1775 default:
1776 /*
1777 * Any other error, respective error code is returned
1778 */
1779 simEntStat.curCmd = AT_CMD_NONE;
1780 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
1781 R_AT( RAT_CME, simEntStat.entOwn )
1782 (
1783 AT_CMD_CPUC,
1784 cmhSIM_GetCmeFromSim ( simShrdPrm.atb[table_id].errCode )
1785 );
1786 break;
1787 }
1788 }
1789
1790 /*
1791 +--------------------------------------------------------------------+
1792 | PROJECT: GSM-PS (6147) MODULE: AOC |
1793 | STATE : code ROUTINE: aoc_set_puct_values |
1794 +--------------------------------------------------------------------+
1795
1796 PURPOSE : Converts the PUCT values from string to SIM format.
1797 */
1798
1799 UBYTE aoc_set_puct_values(T_puct * puct)
1800 {
1801 UBYTE first_digit = FALSE;
1802 UBYTE colon_found = FALSE;
1803 UBYTE position_dot = 0;
1804 SHORT temp_pos = 0;
1805 SHORT position = 0;
1806 SHORT length = 0;
1807 ULONG eppu = 0L;
1808 ULONG temp_eppu = 0L;
1809 UBYTE i;
1810
1811 TRACE_FUNCTION ("aoc_set_puct_values()");
1812
1813 sim_data[0] = puct->currency [0];
1814 sim_data[1] = puct->currency [1];
1815 sim_data[2] = puct->currency [2];
1816
1817 for (i=0;i<20;i++)
1818 {
1819 if (puct->value[i] EQ '\0')
1820 break;
1821
1822 if (first_digit)
1823 {
1824 /* at least one digit detected */
1825 if (colon_found)
1826 {
1827 /* checking the digits after the colon */
1828 switch (puct->value[i])
1829 {
1830 case '0':
1831 /* zeros after the colon are counted */
1832 temp_eppu = temp_eppu * 10 + (puct->value[i] - '0');
1833 temp_pos++;
1834 break;
1835
1836 default:
1837 /* digits available before the colon */
1838 eppu = (temp_eppu * 10) + (puct->value[i] - '0');
1839 temp_eppu = eppu;
1840 length = length + temp_pos + 1;
1841 temp_pos = 0;
1842 if (position_dot)
1843 {
1844 position = position_dot;
1845 position_dot = 0;
1846 }
1847 break;
1848 }
1849 }
1850 else
1851 {
1852 /* checking the digits before the colon */
1853 switch (puct->value[i])
1854 {
1855 case '0':
1856 /* zeros before the colon are counted */
1857 temp_eppu = temp_eppu * 10 + (puct->value[i] - '0');
1858 temp_pos++;
1859 break;
1860
1861 case '.':
1862 colon_found = TRUE;
1863 position_dot = position + temp_pos;
1864 length += temp_pos;
1865 temp_pos = 0;
1866 break;
1867
1868 default:
1869 /* digits available before the colon */
1870 if (temp_pos)
1871 eppu = (temp_eppu * 10) + (puct->value[i] - '0');
1872 else
1873 eppu = eppu * 10 + (puct->value[i] - '0');
1874 temp_eppu = eppu;
1875 length = length + temp_pos + 1;
1876 position = position + temp_pos + 1;
1877 temp_pos = 0;
1878 break;
1879 }
1880 }
1881 }
1882 else
1883 {
1884 /* no digit found */
1885 if (colon_found)
1886 {
1887 /* searching for the first digit after the colon
1888 * e.g. 0.0034 */
1889 switch (puct->value[i])
1890 {
1891 case '0':
1892 /* count the number of zeros after the colon */
1893 temp_pos++;
1894 break;
1895
1896 default:
1897 /* digits available before the colon */
1898 first_digit = TRUE;
1899 position -= temp_pos;
1900 temp_pos = 0;
1901 temp_eppu = eppu = puct->value[i]-'0';
1902 length++;
1903 break;
1904 }
1905 }
1906 else
1907 {
1908 /* checking the digits before the colon
1909 * e.g 234.56 looking for the 2 */
1910 switch (puct->value[i])
1911 {
1912 case '0':
1913 /* leading zeros are ignored */
1914 break;
1915 case '.':
1916 /* no digits before the colon, e.g. 0.23 */
1917 colon_found = TRUE;
1918 break;
1919 default:
1920 /* digits available before the colon */
1921 first_digit = TRUE;
1922 temp_eppu = eppu = puct->value[i]-'0';
1923 position++;
1924 length++;
1925 break;
1926 }
1927 }
1928 }
1929
1930 if (puct->value[i] EQ 0)
1931 break;
1932 }
1933
1934 #if defined WIN32
1935 {
1936 TRACE_EVENT_P2("PUCT POS=%d LEN=%d", position, length);
1937 TRACE_EVENT_P1("EPPU=%d", eppu);
1938 }
1939 #endif
1940
1941 /*
1942 * check the maximum of EPPU
1943 */
1944 if (eppu > 0xFFF)
1945 return FALSE;
1946
1947 /*
1948 * set the EPPU, SEXP and EXP for the SIM Card
1949 */
1950
1951 sim_data[3] = (UBYTE)(eppu >> 4);
1952 sim_data[4] = (UBYTE)(eppu & 0xF);
1953
1954
1955 /*
1956 * for the case : reset PUCT
1957 */
1958 if (!first_digit)
1959 {
1960 /*
1961 * set the first 4 bits of the fifth bytes to 0 (exp2, exp1, exp0, sexp)
1962 */
1963 sim_data[4] = sim_data[4] & 0x0F;
1964 }
1965 else
1966 {
1967 if (!colon_found)
1968 {
1969 if (temp_pos)
1970 {
1971 sim_data[4] += (temp_pos << 5);
1972 }
1973 else
1974 {
1975 sim_data[4] += ((length - position) << 5);
1976 }
1977 }
1978 else
1979 {
1980 if (position_dot NEQ 0)
1981 sim_data[4] += ((length - position) << 5);
1982 else
1983 sim_data[4] += 0x10 + ((length - position) << 5);
1984 }
1985 }
1986 return TRUE;
1987 }
1988
1989
1990 /*
1991 +--------------------------------------------------------------------+
1992 | PROJECT: GSM-PS (6147) MODULE: AOC |
1993 | STATE : code ROUTINE: aoc_parameter |
1994 +--------------------------------------------------------------------+
1995
1996 PURPOSE : Copies the e-parameters of the facility IE.
1997
1998 */
1999 void aoc_parameter(SHORT Cid, T_FWD_CHG_ADVICE_INV * aoc_para)
2000 {
2001 T_chargingInformation * charge;
2002
2003 TRACE_FUNCTION ("aoc_parameter()");
2004
2005 switch (aoc_para->forwardChargeAdviceArg.ssCode)
2006 {
2007 case(SS_CD_AOCI):
2008 cc_aoc_table[Cid].aoci_active=TRUE;
2009 break;
2010 case(SS_CD_AOCC):
2011 cc_aoc_table[Cid].aoci_active=FALSE;
2012 break;
2013 default:
2014 TRACE_EVENT_P1("UNEXPECTED SS_CODE in FWD_AOC %d, assume AOCC", aoc_para->forwardChargeAdviceArg.ssCode);
2015 cc_aoc_table[Cid].aoci_active=FALSE;
2016 }
2017
2018 charge = &aoc_para->forwardChargeAdviceArg.chargingInformation;
2019
2020 cc_aoc_table[Cid].new_data_avail = TRUE;
2021
2022 if (charge->v_e1)
2023 {
2024 if (cc_aoc_table[Cid].aoc_timer_running)
2025 {
2026 /* E1 is available, 4.3.e) special */
2027 cc_aoc_table[Cid].e1_next = aoc_getEVal(&charge->e1);
2028 cc_aoc_table[Cid].e_next_bitmap |= E1_CHANGED;
2029 TRACE_EVENT_P1("E1 = %u", cc_aoc_table[Cid].e1_next);
2030 }
2031 else
2032 {
2033 cc_aoc_table[Cid].e1 = aoc_getEVal(&charge->e1);
2034 TRACE_EVENT_P1("E1 = %u", cc_aoc_table[Cid].e1);
2035 }
2036
2037 }
2038
2039 if (charge->v_e2)
2040 {
2041 if (cc_aoc_table[Cid].aoc_timer_running)
2042 {
2043 /* E2 is available, 4.3.e) special */
2044 cc_aoc_table[Cid].e2_next = aoc_getEVal(&charge->e2);
2045 cc_aoc_table[Cid].e_next_bitmap |= E2_CHANGED;
2046 TRACE_EVENT_P1("E2 = %u", cc_aoc_table[Cid].e2_next);
2047 }
2048 else
2049 {
2050 cc_aoc_table[Cid].e2 = aoc_getEVal(&charge->e2);
2051 TRACE_EVENT_P1("E2 = %u", cc_aoc_table[Cid].e2);
2052 }
2053 }
2054
2055 if (charge->v_e3)
2056 {
2057 /* Special handling of E3, see AOC08226 */
2058 cc_aoc_table[Cid].e3_next = aoc_getEVal(&charge->e3);
2059 cc_aoc_table[Cid].e_next_bitmap |= E3_CHANGED;
2060 TRACE_EVENT_P1("E3 = %u", cc_aoc_table[Cid].e3_next);
2061 }
2062
2063 if (charge->v_e4)
2064 {
2065 cc_aoc_table[Cid].e4 = aoc_getEVal(&charge->e4);
2066 cc_aoc_table[Cid].e_next_bitmap |= E4_CHANGED;
2067 TRACE_EVENT_P1("E4 = %u", cc_aoc_table[Cid].e4);
2068 }
2069
2070 /* e5 and e6 are not (yet?) supported */
2071 if (charge->v_e5)
2072 {
2073 cc_aoc_table[Cid].e5 = aoc_getEVal(&charge->e5);
2074 TRACE_EVENT_P1("E5 = %u", cc_aoc_table[Cid].e5);
2075 }
2076
2077 if (charge->v_e6)
2078 {
2079 cc_aoc_table[Cid].e6 = aoc_getEVal(&charge->e6);
2080 TRACE_EVENT_P1("E6 = %u", cc_aoc_table[Cid].e6);
2081 }
2082
2083 if (charge->v_e7)
2084 {
2085 if (cc_aoc_table[Cid].aoc_timer_running)
2086 {
2087 /* E7 is available, 4.3.e) special */
2088 cc_aoc_table[Cid].e7_next = aoc_getEVal(&charge->e7);
2089 cc_aoc_table[Cid].e_next_bitmap |= E7_CHANGED;
2090 TRACE_EVENT_P1("E7 = %u", cc_aoc_table[Cid].e7_next);
2091 }
2092 else
2093 {
2094 cc_aoc_table[Cid].e7 = aoc_getEVal(&charge->e7);
2095 TRACE_EVENT_P1("E7 = %u", cc_aoc_table[Cid].e7);
2096 }
2097
2098 }
2099
2100 if(cc_aoc_table[Cid].e_next_bitmap & (E1_CHANGED | E2_CHANGED | E7_CHANGED))
2101 {
2102 /* e3 should be applied to the parameters held in abeyance, see AOC08226 */
2103 }
2104 else
2105 {
2106 /* bring e3 immediately into operation */
2107 cc_aoc_table[Cid].e3 = cc_aoc_table[Cid].e3_next;
2108 }
2109
2110
2111
2112 if(cc_aoc_table[Cid].e_next_bitmap & E3_CHANGED)
2113 {
2114 /* e3 is updated recalc is needed now */
2115 aoc_calculate_charging_parameter_part2( Cid );
2116 }
2117
2118 /*
2119 if(cc_aoc_table[Cid].e_next_bitmap & E4_CHANGED)
2120 {
2121 if e4 is updated while charging running, charge amount now
2122 if (cc_aoc_table[Cid].aoc_timer_running EQ TRUE)
2123 {
2124 aoc_calculate_charging_parameter_part1( Cid );
2125 aoc_increment_initial_charge( Cid );
2126 cc_aoc_table[Cid].e_next_bitmap &= ~E4_CHANGED;
2127 }
2128 }
2129 */
2130
2131 }
2132
2133 /*
2134 +--------------------------------------------------------------------+
2135 | PROJECT: GSM-PS (6147) MODULE: AOC |
2136 | STATE : code ROUTINE: aoc_getEVal |
2137 +--------------------------------------------------------------------+
2138
2139 PURPOSE : Assembles e-value out of the facility IE.
2140 */
2141
2142 USHORT aoc_getEVal( void * eBuf )
2143 {
2144 T_e1 *pE = (T_e1*)eBuf;
2145 USHORT val = 0;
2146 UBYTE len;
2147
2148 for( len = 0; len < pE->c_e_val; len++ )
2149 {
2150 val<<= 8;
2151 val += pE->e_val[len];
2152 }
2153
2154 return( val );
2155 }
2156
2157
2158 /*
2159 +--------------------------------------------------------------------+
2160 | PROJECT: GSM-PS (6147) MODULE: AOC |
2161 | STATE : code ROUTINE: aoc_send_ccm |
2162 +--------------------------------------------------------------------+
2163
2164 PURPOSE : The ccm is forwarded if at least one of the calls is
2165 active.
2166 */
2167
2168 void aoc_send_ccm ()
2169 {
2170 ULONG ccm_output;
2171 T_ACI_CMD_SRC idx;
2172
2173 if (qAT_CallActive())
2174 {
2175 /* call back function to notify the MMI */
2176 for( idx = CMD_SRC_LCL; idx < CMD_SRC_MAX; idx++ )
2177 {
2178 /*
2179 * forward ccm in whole units to MMI
2180 */
2181 ccm_output = MC_AOC_ROUND_UP(ccm);
2182
2183 R_AT( RAT_CCCM, idx )( &ccm_output );
2184 }
2185 }
2186 }
2187
2188 /*
2189 +--------------------------------------------------------------------+
2190 | PROJECT: GSM-PS (6147) MODULE: AOC |
2191 | STATE : code ROUTINE: aoc_set_time_ut_charge |
2192 +--------------------------------------------------------------------+
2193
2194 PURPOSE : This function is used to set the period of time until
2195 the next charging occur.
2196 */
2197
2198 void aoc_set_time_ut_charge ( SHORT cId, T_TIME time )
2199 {
2200 UBYTE mode = AOC_CALL_TIMER_ELAPSED; /* indicates the elapsed */
2201 /* timer */
2202 /*
2203 * in case an AoC timer is elapsed the time until
2204 * next charging will be fixed to the new value
2205 */
2206 if ( cId NEQ ACI_NumParmNotPresent )
2207 {
2208 cc_aoc_table[cId].time_ut_charge = time;
2209 mode = AOC_AOC_TIMER_ELAPSED;
2210 }
2211
2212 aoc_calc_expct_charge ( mode );
2213 }
2214
2215 /*
2216 +--------------------------------------------------------------------+
2217 | PROJECT: GSM-PS (6147) MODULE: AOC |
2218 | STATE : code ROUTINE: aoc_calc_expct_charge |
2219 +--------------------------------------------------------------------+
2220
2221 PURPOSE : This function is used to calculate the amount of charge
2222 which is going to be consumed during the period of time
2223 fixed by AOC_MAX_REMAIN_CALL_TIME.
2224 */
2225
2226 void aoc_calc_expct_charge ( UBYTE mode )
2227 {
2228 ULONG expct_charge = 0; /* expected charge */
2229 T_TIME remain_time; /* remaining time until next */
2230 ULONG num_chrg_pts; /* number of charging points */
2231 UBYTE idx; /* used for counting */
2232 BOOL aoc_running = FALSE; /* indicates whether at least */
2233 /* one AoC timer is running */
2234
2235 for ( idx = 0; idx < MAX_CALL_NR; idx++ )
2236 {
2237 if ( cc_aoc_table[idx].aoc_timer_running AND cc_aoc_table[idx].e1 )
2238 {
2239 aoc_running = TRUE;
2240
2241 if ( mode EQ AOC_CALL_TIMER_ELAPSED )
2242 {
2243 #if defined (WIN32)
2244 TRACE_EVENT_P1("time to charge: %d ms",
2245 cc_aoc_table[idx].time_ut_charge - AOC_THOUSAND_MILLISECONDS);
2246 #endif
2247
2248 /* in case the call timer is elapsed the actual
2249 * time until next charging will be calculated */
2250 if (cc_aoc_table[idx].time_ut_charge >= AOC_THOUSAND_MILLISECONDS)
2251 {
2252 cc_aoc_table[idx].time_ut_charge -= AOC_THOUSAND_MILLISECONDS;
2253 }
2254 else
2255 {
2256 /* calculate the expected charging intervals based on the E parameter */
2257 if ( cc_aoc_table[idx].new_data_avail EQ TRUE AND
2258 cc_aoc_table[idx].e_next_bitmap & E7_CHANGED )
2259 {
2260 cc_aoc_table[idx].time_ut_charge = aoc_calc_time_ut_charge ( idx, E7_CHANGED );
2261 }
2262 else if ( cc_aoc_table[idx].e_next_bitmap & E2_CHANGED )
2263 {
2264 cc_aoc_table[idx].time_ut_charge = aoc_calc_time_ut_charge ( idx, E2_CHANGED );
2265 }
2266 else
2267 {
2268 cc_aoc_table[idx].time_ut_charge = ~0L;
2269 }
2270
2271 /* calculate the expected initial charge and
2272 * add to the expected charge */
2273 /* The fixed amount is charged immediately and not somewhen later
2274 if ( cc_aoc_table[idx].new_data_avail EQ TRUE AND
2275 cc_aoc_table[idx].e_bitmap & E4_AVAILABLE )
2276 {
2277 expct_charge += ( ( ULONG ) cc_aoc_table[idx].e3 *
2278 ( ULONG ) cc_aoc_table[idx].e4 ) / 10;
2279 }
2280 */
2281 }
2282 }
2283
2284 /* calculate expected charge for next AOC_MAX_REMAIN_CALL_TIME milliseconds */
2285 num_chrg_pts = 1;
2286
2287 if ( cc_aoc_table[idx].time_ut_charge <= AOC_MAX_REMAIN_CALL_TIME )
2288 {
2289 if (cc_aoc_table[idx].e2)
2290 {
2291 remain_time = AOC_MAX_REMAIN_CALL_TIME -
2292 cc_aoc_table[idx].time_ut_charge;
2293 num_chrg_pts +=
2294 (ULONG)(remain_time / E_IN_MS ( cc_aoc_table[idx].e2 ));
2295 }
2296
2297 expct_charge += ( num_chrg_pts *
2298 ( cc_aoc_table[idx].e1 * cc_aoc_table[idx].e3 ) / 10 );
2299 }
2300 }
2301 }
2302
2303 aoc_calc_acm_wrn_evnt ( expct_charge, aoc_running );
2304 }
2305
2306 /*
2307 +--------------------------------------------------------------------+
2308 | PROJECT: GSM-PS (6147) MODULE: AOC |
2309 | STATE : code ROUTINE: aoc_calc_acm_wrn_evnt |
2310 +--------------------------------------------------------------------+
2311
2312 PURPOSE : In case the remaining credit is low a call timer warning
2313 event is generated.
2314 */
2315
2316 void aoc_calc_acm_wrn_evnt ( ULONG charge, BOOL aoc_running )
2317 {
2318 ULONG credit; /* remaining credit */
2319 ULONG acm_for_sim; /* lack of the actual ACM value */
2320 T_ACI_CCWV_CHRG charging; /* CCWV mode indicated to MMI */
2321
2322 /*
2323 * the update on the SIM is the difference between the rounded up
2324 * value of the current CCM and the old CCM (already rounded up)
2325 */
2326 acm_for_sim = MC_AOC_ROUND_UP(ccm) - MC_AOC_ROUND_UP(ccm_already_incremented);
2327 credit = acmmax - acm - ( acm_for_sim * 100 );
2328
2329 #if defined (WIN32)
2330 {
2331 TRACE_EVENT_P2("AoC charge for next %u ms = %u", AOC_MAX_REMAIN_CALL_TIME, charge );
2332 }
2333 #endif
2334
2335 if ( aoc_running EQ TRUE )
2336 {
2337 if ( charge >= credit )
2338 charging = CCWV_CHRG_Shortage;
2339 else
2340 charging = CCWV_CHRG_Abundance;
2341 }
2342 else
2343 charging = CCWV_CHRG_Termination;
2344
2345 aoc_ntfy_acm_wrn_evnt ( charging );
2346 }
2347
2348 /*
2349 +--------------------------------------------------------------------+
2350 | PROJECT: GSM-PS (6147) MODULE: AOC |
2351 | STATE : code ROUTINE: aoc_ntfy_acm_wrn_evnt |
2352 +--------------------------------------------------------------------+
2353
2354 PURPOSE : Notifies the MMI about the call meter warning event.
2355
2356 */
2357 void aoc_ntfy_acm_wrn_evnt ( T_ACI_CCWV_CHRG charging )
2358 {
2359 T_ACI_CMD_SRC idx;
2360
2361 if ( ccwv_charging NEQ charging )
2362 {
2363 ccwv_charging = charging;
2364
2365 for( idx=CMD_SRC_LCL; idx<CMD_SRC_MAX; idx++ )
2366 {
2367 R_AT( RAT_CCWV, idx )( charging );
2368 }
2369 }
2370 }
2371
2372 /*
2373 +--------------------------------------------------------------------+
2374 | PROJECT: GSM-PS (6147) MODULE: AOC |
2375 | STATE : code ROUTINE: aoc_calc_time_ut_charge |
2376 +--------------------------------------------------------------------+
2377
2378 PURPOSE : This function calculates the new time to charge with
2379 respect to the previous value.
2380
2381 */
2382 T_TIME aoc_calc_time_ut_charge ( SHORT cId,
2383 UBYTE e_value_flag )
2384 {
2385 T_TIME new_time = ~0L; /* new time until next charging */
2386 T_TIME e_value; /* interval value */
2387
2388 switch ( e_value_flag )
2389 {
2390 case (E2_CHANGED): e_value = E_IN_MS ( cc_aoc_table[cId].e2 );
2391 break;
2392 case (E7_CHANGED): e_value = E_IN_MS ( cc_aoc_table[cId].e7 );
2393 break;
2394 default : e_value = 0L;
2395 break;
2396 }
2397
2398 if ( e_value <= ( AOC_THOUSAND_MILLISECONDS - cc_aoc_table[cId].time_ut_charge ) )
2399 {
2400 new_time = e_value;
2401 }
2402 else if ( e_value NEQ 0L )
2403 {
2404 new_time = e_value - ( AOC_THOUSAND_MILLISECONDS - cc_aoc_table[cId].time_ut_charge );
2405 }
2406
2407 return new_time;
2408 }
2409
2410 /* Implements Measure 213 */
2411 /*
2412 +------------------------------------------------------------------------------
2413 | Function : aoc_update_sim_datafield_cb
2414 +------------------------------------------------------------------------------
2415 | Purpose : Callback function for updating ACM.or ACMMAX Field
2416 | on the SIM Card.
2417 |
2418 | Parameters : table_id -
2419 | at_cmd_idn - AT COMMAND Identifier
2420 | (AT_CMD_CAMM or AT_CMD_CACM)
2421 |
2422 | Return : void
2423 +------------------------------------------------------------------------------
2424 */
2425
2426 LOCAL void aoc_update_sim_datafield_cb(SHORT table_id, T_ACI_AT_CMD at_cmd_idn)
2427 {
2428 T_SIM_SET_PRM * pSIMSetPrm; /* points to MM parameter set */
2429
2430 TRACE_FUNCTION ("aoc_update_sim_datafield_cb()");
2431
2432 simEntStat.curCmd = AT_CMD_NONE;
2433 simShrdPrm.atb[table_id].ntryUsdFlg = FALSE;
2434
2435 switch (simShrdPrm.atb[table_id].errCode)
2436 {
2437 case SIM_NO_ERROR:
2438 /*
2439 * No error has occured, read ACM etc. again from SIM Card
2440 */
2441 R_AT( RAT_OK, simEntStat.entOwn) (at_cmd_idn);
2442 aoc_sms ();
2443
2444 if (at_cmd_idn EQ AT_CMD_CAMM)
2445 {
2446 aoc_set_time_ut_charge ( ACI_NumParmNotPresent, 0L );
2447 }
2448 break;
2449 case SIM_CAUSE_PIN2_EXPECT:
2450 /*
2451 * error has occured, maybe PIN2 is needed
2452 */
2453 if (strlen ((char *) pwd) AND
2454 act_upd_op EQ FIRST_UPDATE)
2455 {
2456 /*
2457 * Password is available and
2458 * it is the first update, then
2459 * try to verify PIN2
2460 */
2461 act_upd_op = VERIFY_PWD;
2462 pSIMSetPrm = &simShrdPrm.setPrm[act_src_id];
2463
2464 cmhSIM_FillInPIN ( (char *) pwd, pSIMSetPrm -> curPIN, PIN_LEN);
2465 pSIMSetPrm -> PINType = PHASE_2_PIN_2;
2466 simEntStat.curCmd = at_cmd_idn;
2467 simShrdPrm.owner = (T_OWN)act_src_id;
2468 simEntStat.entOwn = act_src_id;
2469
2470 if ( psaSIM_VerifyPIN() < 0 ) /* verify PIN */
2471 {
2472 TRACE_EVENT( "FATAL RETURN psaSIM in +CACM or +CAMM" );
2473 }
2474 }
2475 else
2476 {
2477 /*
2478 * PIN2 not available or second attempt
2479 */
2480 if (act_upd_op EQ FIRST_UPDATE)
2481 {
2482 R_AT( RAT_CME, simEntStat.entOwn )
2483 ( at_cmd_idn, CME_ERR_SimPin2Req );
2484 }
2485 else
2486 {
2487 R_AT( RAT_CME, simEntStat.entOwn )
2488 ( at_cmd_idn, CME_ERR_WrongPasswd );
2489 }
2490 }
2491 break;
2492 default:
2493 /*
2494 * Any other error, respective error code is returned
2495 */
2496 R_AT( RAT_CME, simEntStat.entOwn )
2497 (
2498 at_cmd_idn,
2499 cmhSIM_GetCmeFromSim ( simShrdPrm.atb[table_id].errCode )
2500 );
2501 break;
2502 }
2503 }
2504
2505 /* Implements Measure 156 and 157 */
2506 /*
2507 +------------------------------------------------------------------------------
2508 | Function : aoc_read_sim_datafield
2509 +------------------------------------------------------------------------------
2510 | Purpose : Reads the SIM_ACM , SIM_ACMMAX and SIM_PUCT field
2511 | on the SIM card
2512 |
2513 | Parameters : accType - ACCESS TYPE, (ACT_RD_REC or ACT_RD_DAT)
2514 | reqDataFld - Requested DataField Identifier
2515 | (SIM_ACM/SIM_ACMMAX/SIM_PUCT)
2516 | rplyCB - Pointer to the Reply Call Back Function
2517 | (aoc_read_acm_cb or aoc_read_acmmax_cb)
2518 | dataLen - Data Length depending upon the which
2519 | field to be read.
2520 |
2521 | Return : void
2522 +------------------------------------------------------------------------------
2523 */
2524
2525 LOCAL void aoc_read_sim_datafield ( UBYTE accType, USHORT reqDataFld,
2526 void (*rplyCB)(SHORT), UBYTE dataLen)
2527 {
2528 SHORT table_id;
2529
2530 TRACE_FUNCTION ("aoc_read_sim_datafield()");
2531
2532 table_id = psaSIM_atbNewEntry();
2533
2534 if(table_id NEQ NO_ENTRY)
2535 {
2536 simShrdPrm.atb[table_id].accType = accType;
2537 simShrdPrm.atb[table_id].v_path_info = FALSE;
2538 simShrdPrm.atb[table_id].reqDataFld = reqDataFld;
2539 if (reqDataFld EQ SIM_ACM)
2540 {
2541 simShrdPrm.atb[table_id].recNr = 1;
2542 }
2543 else
2544 {
2545 simShrdPrm.atb[table_id].dataOff = 0;
2546 }
2547 simShrdPrm.atb[table_id].dataLen = dataLen;
2548 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
2549 simShrdPrm.atb[table_id].exchData = sim_data;
2550 simShrdPrm.atb[table_id].rplyCB = rplyCB;
2551
2552 simShrdPrm.aId = table_id;
2553 if(psaSIM_AccessSIMData() < 0)
2554 {
2555 TRACE_EVENT("FATAL ERROR");
2556 }
2557 }
2558 }
2559
2560 /* Implements Measure 152 */
2561 /*
2562 +------------------------------------------------------------------------------
2563 | Function : aoc_update_sim_datafield
2564 +------------------------------------------------------------------------------
2565 | Purpose : Updates the ACM field on the SIM card
2566 |
2567 | Parameters : operation - FIRST_UPDATE or SECOND_UPDATE
2568 | accType - ACCESS TYPE, (ACT_WR_REC or ACT_WR_DAT)
2569 | reqDataFld - Requested DataField Identifier
2570 | (SIM_ACM or SIM_ACMMAX)
2571 | rplyCB - Pointer to the Reply Call Back Function
2572 | (aoc_update_acm_cb or aoc_update_acmmax_cb)
2573 |
2574 | Return : void
2575 +------------------------------------------------------------------------------
2576 */
2577
2578 void aoc_update_sim_datafield ( UBYTE operation, UBYTE accType,
2579 USHORT reqDataFld, void (*rplyCB)(SHORT) )
2580 {
2581 SHORT table_id;
2582
2583 TRACE_FUNCTION ("aoc_update_sim_datafield()");
2584
2585 /*
2586 * request table id for SIM SAP access
2587 */
2588 table_id = psaSIM_atbNewEntry();
2589 act_upd_op = operation;
2590
2591 if(table_id NEQ NO_ENTRY)
2592 {
2593 simShrdPrm.atb[table_id].accType = accType;
2594 simShrdPrm.atb[table_id].v_path_info = FALSE;
2595 simShrdPrm.atb[table_id].reqDataFld = reqDataFld;
2596 simShrdPrm.atb[table_id].dataOff = 0;
2597 simShrdPrm.atb[table_id].dataLen = 3;
2598 simShrdPrm.atb[table_id].ntryUsdFlg = TRUE;
2599 simShrdPrm.atb[table_id].exchData = sim_data;
2600 simShrdPrm.atb[table_id].rplyCB = rplyCB;
2601 simShrdPrm.aId = table_id;
2602
2603 sim_data[0] = (UBYTE)(act_value >> 16);
2604 sim_data[1] = (UBYTE)(act_value >> 8);
2605 sim_data[2] = (UBYTE)(act_value & 0xFF);
2606
2607 if(psaSIM_AccessSIMData() < 0)
2608 {
2609 TRACE_EVENT("FATAL ERROR");
2610 }
2611 }
2612 }
2613