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