comparison g23m/condat/ms/src/mfw/Mfw_em.c @ 0:509db1a7b7b8

initial import: leo2moko-r1
author Space Falcon <falcon@ivan.Harhan.ORG>
date Mon, 01 Jun 2015 03:24:05 +0000
parents
children
comparison
equal deleted inserted replaced
-1:000000000000 0:509db1a7b7b8
1 /*
2 +--------------------------------------------------------------------+
3 | PROJECT: MMI-Framework (8417) $Workfile:: mfw_em.c $|
4 | $Author:: MC $ CONDAT UK $Revision:: 1 $|
5 | CREATED: 23.09.02 $|
6 | STATE : code |
7 +--------------------------------------------------------------------+
8
9 MODULE : MFW_EM
10
11 PURPOSE : Engineering Mode functions
12
13 */
14
15 /*
16 ********************************Include Files**********************************************
17 **/
18
19 #define ENTITY_MFW
20
21
22 #include <string.h>
23 #include <stdio.h>
24 #include <stdlib.h>
25
26 #include "typedefs.h"
27 #include "vsi.h"
28 #include "pei.h"
29 #include "custom.h"
30 #include "gsm.h"
31
32 #ifndef PCM_2_FFS
33 #include "pcm.h"
34 #endif
35
36 #include "ffs/ffs.h"
37
38 #include "message.h"
39 #include "prim.h"
40 #include "aci_cmh.h"
41 #if defined (FAX_AND_DATA)
42 #include "aci_fd.h"
43 #endif
44
45 #ifdef GPRS
46 #include "gprs.h"
47 #endif
48 #include "dti_conn_mng.h"
49 #include "phb.h"
50 #include "psa.h"
51 #include "cmh.h"
52 #include "cmh_phb.h"
53 #include "psa.h"
54 #include "psa_sim.h"
55 #include "cus_aci.h"
56 #include "cmh_mm.h"
57 #include "cmh_sim.h"
58 #include "Mfw_em.h"
59 #include "aci_em.h"
60 #include "mfw_win.h"
61
62
63
64 #define ASCII_OFFSET 0x30 /*SPR 1554*/
65
66 /*
67 ********************************Internal data types**********************************************
68 **/
69
70
71 typedef union
72 {
73 MFW_EM_Mobile_Info MobileInfo;
74 MFW_EM_Serving_Cell_Parameters SCInfo;
75 MFW_EM_Neighbour_Cell_Parameters NCInfo;
76 MFW_EM_Location_Parameters LocInfo;
77 MFW_EM_Ciph_hop_DTX_Parameters CHDTXInfo;
78 MFW_EM_GPRS_Parameter GPRSInfo;
79 }
80 T_MFW_EM_PARA;
81
82 typedef struct
83 {
84 T_MFW_EVENT emask; /* events of interest */
85 T_MFW_EVENT event; /* current event */
86 T_MFW_CB handler;
87 T_MFW_EM_PARA para;
88 } T_MFW_EM;
89 /*
90 ********************************Global variables**********************************************
91 **/
92 MFW_EM_Data* MfwEmData= NULL;
93
94 EXTERN MfwHdr *current_mfw_elem;
95
96 /*
97 ********************************Prototypes**********************************************
98 **/
99 int Mfw_em_sign_exec(T_MFW_HDR * hdr, T_MFW_EVENT event,T_MFW_EM_PARA *para);
100 void Mfw_em_signal(MfwEvt event, void *para);
101 void Mfw_em_cb(T_DRV_SIGNAL_EM* signal);
102 static int emCommand (U32 cmd, void *h);
103
104 /**************************************Public Functions*****************************************/
105
106 /*
107 +--------------------------------------------------------------------+
108 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
109 | STATE : code ROUTINE : Mfw_em_init |
110 +--------------------------------------------------------------------+
111
112 PURPOSE : initialise module
113
114 */
115 int Mfw_em_init()
116 { TRACE_EVENT("Mfw_em_init()");
117 em_Init(Mfw_em_cb, NULL); /*init EM driver*/
118 mfwCommand[MfwTypEm] = (MfwCb) emCommand;
119 return TRUE;
120 }
121
122 /*
123 +--------------------------------------------------------------------+
124 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
125 | STATE : code ROUTINE : Mfw_em_create |
126 +--------------------------------------------------------------------+
127
128 PURPOSE : binds passed callback function to event mask
129
130 */
131 MfwHnd Mfw_em_create(MfwHnd hWin, MfwEvt event, MfwCb cb_func)
132 {
133 MfwHdr *hdr;
134 T_MFW_EM *em_para;
135
136 TRACE_EVENT("em_create()");
137
138 hdr = (MfwHdr *) mfwAlloc(sizeof(MfwHdr));
139 em_para = (T_MFW_EM *) mfwAlloc(sizeof(T_MFW_EM));
140
141 if (!hdr || !em_para)
142 return 0;
143
144 em_para->emask = event;
145 em_para->handler = cb_func;
146
147 hdr->data = em_para;
148 hdr->type = MfwTypEm;
149
150 return mfwInsert((MfwHdr *) hWin,hdr);
151 }
152
153 /*
154 +--------------------------------------------------------------------+
155 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
156 | STATE : code ROUTINE : Mfw_em_exit |
157 +--------------------------------------------------------------------+
158
159 PURPOSE : exit module
160
161 */
162 void Mfw_em_exit()
163 { TRACE_EVENT("Mfw_em_exit()");
164 if (MfwEmData != NULL)
165 mfwFree((void*)MfwEmData, sizeof(MFW_EM_Data));
166
167 em_Exit();
168 }
169 /*
170 +--------------------------------------------------------------------+
171 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
172 | STATE : code ROUTINE : Mfw_em_get_data |
173 +--------------------------------------------------------------------+
174
175 PURPOSE : requests data from ACI EM driver
176
177 */
178 int Mfw_em_get_data(MfwEmDataType type)
179 {
180 TRACE_EVENT("Mfw_em_get_data()");
181
182 //#define _EM_MMI_MFW_TEST
183
184 #ifndef _EM_MMI_MFW_TEST
185 /*If not already allocated, Allocate memory to store data in*/
186 if (MfwEmData == NULL)
187 if ((MfwEmData = (MFW_EM_Data*)mfwAlloc(sizeof(MFW_EM_Data))) == NULL)
188 return FALSE;
189 /*Request appropriate data from Em driver*/
190 switch(type)
191 {
192 case EM_MOBILE_INFO:
193 /*MC SPR 1554, added call to request software version and identity param*/
194 em_Read_Data_Parameter(EM_CLASS_MOBILE_DATA, EM_SUBCLASS_SW_VERSION, 1,Mfw_em_cb);
195 em_Read_Data_Parameter(EM_CLASS_MOBILE_DATA,EM_SUBCLASS_ID, 1, Mfw_em_cb);
196 break;
197 case EM_SERVING_CELL_PARAMS:
198 em_Read_Data_Parameter(EM_CLASS_INFRA_DATA, EM_SUBCLASS_SC, 1, Mfw_em_cb);
199 break;
200 case EM_NEIGHBOURING_CELL_PARAMS:
201 em_Read_Data_Parameter(EM_CLASS_INFRA_DATA, EM_SUBCLASS_SC, 1, Mfw_em_cb);
202 em_Read_Data_Parameter(EM_CLASS_INFRA_DATA, EM_SUBCLASS_NC, 1, Mfw_em_cb);
203 break;
204 case EM_LOCATION_PARAMS:
205 em_Read_Data_Parameter(EM_CLASS_INFRA_DATA, EM_SUBCLASS_LOC_PAG, 1, Mfw_em_cb);
206 em_Read_Data_Parameter(EM_CLASS_INFRA_DATA, EM_SUBCLASS_SC, 1, Mfw_em_cb);
207 break;
208 case EM_CIPH_HOP_DTX_PARAMS:
209 em_Read_Data_Parameter(EM_CLASS_INFRA_DATA, EM_SUBCLASS_CIPH_HOP_DTX, 1, Mfw_em_cb);
210 break;
211 case EM_GPRS_PARAMS:
212 em_Read_Data_Parameter(EM_CLASS_INFRA_DATA, EM_SUBCLASS_SC_GPRS, 1, Mfw_em_cb);
213 break;
214 }
215 return TRUE;
216 #endif
217
218
219
220 #ifdef _EM_MMI_MFW_TEST
221 /*Test harness, just returns made-up data to MMI*/
222 if (MfwEmData == NULL)
223 if ((MfwEmData = (MFW_EM_Data*)mfwAlloc(sizeof(MFW_EM_Data))) == NULL)
224 return FALSE;
225 switch(type)
226 {
227 case EM_MOBILE_INFO:
228 { //MfwEmData->MobileInfo.software_version = 0x44;
229 strcpy(MfwEmData->MobileInfo.IMEI, "123456789ABC");
230 strcpy(MfwEmData->MobileInfo.IMSI, "123456789ABC");
231 MfwEmData->MobileInfo.TMSI = 76;
232 Mfw_em_signal(EM_MOBILE_INFO, (void*)&MfwEmData->MobileInfo);
233 }
234 break;
235 case EM_SERVING_CELL_PARAMS:
236 {
237 MfwEmData->SCInfo.arfcn= 0x44;
238 MfwEmData->SCInfo.RSSI= 86;
239 MfwEmData->SCInfo.RXQ = 67;
240 MfwEmData->SCInfo.RLT = 67;
241 Mfw_em_signal(EM_SERVING_CELL_PARAMS, (void*)&MfwEmData->SCInfo);
242 }
243 break;
244 case EM_NEIGHBOURING_CELL_PARAMS:
245 { MfwEmData->NCInfo.NUM= 0x05;
246 strcpy((char*)MfwEmData->NCInfo.arfcn, "WERTYUIOPAS");
247 strcpy((char*)MfwEmData->NCInfo.RSSI, "12345");
248
249 Mfw_em_signal(EM_NEIGHBOURING_CELL_PARAMS, (void*)&MfwEmData->NCInfo);
250
251 }
252 break;
253 case EM_LOCATION_PARAMS:
254 { strcpy((char*)MfwEmData->LocInfo.MCC, "123");
255 strcpy((char*)MfwEmData->LocInfo.MNC, "456");
256 MfwEmData->LocInfo.LAC = 12345;
257 MfwEmData->LocInfo.CI = 12045;
258
259 Mfw_em_signal(EM_LOCATION_PARAMS, (void*)&MfwEmData->LocInfo);
260
261 }
262 break;
263 case EM_GPRS_PARAMS:
264 { MfwEmData->GPRSInfo.ULS= 0;
265 MfwEmData->GPRSInfo.DLS= 0;
266 MfwEmData->GPRSInfo.coding_scheme = 0;
267 Mfw_em_signal(EM_GPRS_PARAMS, (void*)&MfwEmData->GPRSInfo);
268
269 }
270 break;
271 case EM_CIPH_HOP_DTX_PARAMS:
272 { MfwEmData->CHDTXInfo.ciph_status= 0;
273 MfwEmData->CHDTXInfo.hopping_channels= 0;
274 MfwEmData->CHDTXInfo.DTX_status = 1;
275 Mfw_em_signal(EM_CIPH_HOP_DTX_PARAMS, (void*)&MfwEmData->CHDTXInfo);
276
277 }
278 break;
279 }
280 return TRUE;
281 #endif
282 }
283
284 /***********************************************Private functions:********************************/
285 /*
286 +--------------------------------------------------------------------+
287 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
288 | STATE : code ROUTINE : emCommand |
289 +--------------------------------------------------------------------+
290
291 PURPOSE : handle mfw windows command
292
293 */
294
295 static int emCommand (U32 cmd, void *h)
296 {TRACE_EVENT("emCommand()");
297 switch (cmd)
298 {
299 case MfwCmdDelete: /* delete me */
300 if (!h)
301 return 0;
302 em_delete(h);
303 return 1;
304 default:
305 break;
306 }
307
308 return 0;
309 }
310
311 /*
312 +--------------------------------------------------------------------+
313 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
314 | STATE : code ROUTINE : em_delete |
315 +--------------------------------------------------------------------+
316
317 PURPOSE : delete EM event handler
318
319 */
320
321 MfwRes em_delete (MfwHnd h)
322 {
323 TRACE_EVENT("em_delete()");
324
325 if (!h || !((MfwHdr *) h)->data)
326 return MfwResIllHnd;
327
328 if (!mfwRemove((MfwHdr *) h))
329 return MfwResIllHnd;
330
331 mfwFree((U8 *) ((MfwHdr *) h)->data,sizeof(T_MFW_EM));
332 mfwFree((U8 *) h,sizeof(MfwHdr));
333
334 return MfwResOk;
335 }
336 /*
337 +--------------------------------------------------------------------+
338 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
339 | STATE : code ROUTINE : Mfw_em_sign_exec |
340 +--------------------------------------------------------------------+
341
342 PURPOSE : send event to MMI
343
344 */
345 int Mfw_em_sign_exec(T_MFW_HDR * cur_elem, T_MFW_EVENT event,T_MFW_EM_PARA *para)
346 {
347 TRACE_EVENT("Mfw_em_sign_exec()");
348
349 while (cur_elem)
350 {
351 if (cur_elem->type == MfwTypEm)
352 {
353 T_MFW_EM *em_data;
354 em_data = (T_MFW_EM *) cur_elem->data;
355 if (em_data->emask & event)
356 {
357 em_data->event = event;
358 switch (event)
359 {
360 case EM_MOBILE_INFO:
361 memcpy(&em_data->para.MobileInfo,
362 para,sizeof(MFW_EM_Mobile_Info));
363 break;
364
365 case EM_SERVING_CELL_PARAMS:
366 memcpy(&em_data->para.SCInfo,
367 para,sizeof(MFW_EM_Serving_Cell_Parameters));
368 break;
369 case EM_NEIGHBOURING_CELL_PARAMS:
370 memcpy(&em_data->para.NCInfo,
371 para,sizeof(MFW_EM_Neighbour_Cell_Parameters));
372 break;
373
374 case EM_LOCATION_PARAMS:
375 memcpy(&em_data->para.LocInfo,
376 para,sizeof(MFW_EM_Location_Parameters));
377 break;
378 case EM_CIPH_HOP_DTX_PARAMS:
379 memcpy(&em_data->para.CHDTXInfo,
380 para,sizeof(MFW_EM_Ciph_hop_DTX_Parameters));
381 break;
382
383 case EM_GPRS_PARAMS:
384 memcpy(&em_data->para.GPRSInfo,
385 para,sizeof(MFW_EM_GPRS_Parameter));
386 break;
387 }
388 if (em_data->handler)
389 {
390
391 // store current mfw elem
392 current_mfw_elem = cur_elem;
393
394 if ((*(em_data->handler))(em_data->event,
395 (void *) &em_data->para))
396 return TRUE;
397 }
398 }
399 }
400 cur_elem = cur_elem->next;
401 }
402
403 return FALSE;
404
405
406 }
407 /*
408 +--------------------------------------------------------------------+
409 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
410 | STATE : code ROUTINE : Mfw_em_signal |
411 +--------------------------------------------------------------------+
412
413 PURPOSE : sends event to MMi via Mfw_em_sign_exec()
414
415 */
416 void Mfw_em_signal(MfwEvt event, void *para)
417 {
418 UBYTE temp = dspl_Enable(0);
419 TRACE_EVENT ("em_signal()");
420
421 if (mfwSignallingMethod EQ 0)
422 {
423 if (mfwFocus)
424 if (Mfw_em_sign_exec(mfwFocus,event,para))
425 {
426 dspl_Enable(temp);
427 return;
428 }
429 if (mfwRoot)
430 Mfw_em_sign_exec(mfwRoot,event,para);
431 }
432 else
433 {
434 MfwHdr * h = 0;
435
436 /*
437 * Focus set, then start here
438 */
439 if (mfwFocus)
440 h = mfwFocus;
441 /*
442 * Focus not set, then start root
443 */
444 if (!h)
445 h = mfwRoot;
446
447 /*
448 * No elements available, return
449 */
450
451 while (h)
452
453
454 {
455 /*
456 * Signal consumed, then return
457 */
458 if (Mfw_em_sign_exec (h, event, para))
459 {
460 dspl_Enable(temp);
461 return;
462 }
463
464 /*
465 * All windows tried inclusive root
466 */
467 if (h == mfwRoot)
468 {
469 dspl_Enable(temp);
470 return;
471 }
472
473 /*
474 * get parent window
475 */
476 h = mfwParent(mfwParent(h));
477 if(h)
478 h = ((MfwWin * )(h->data))->elems;
479 }
480 Mfw_em_sign_exec (mfwRoot, event, para);
481 }
482 dspl_Enable(temp);
483 return;
484
485
486 }
487 /*
488 +--------------------------------------------------------------------+
489 | PROJECT : MMI-Framework (8417) MODULE : MFW_EM |
490 | STATE : code ROUTINE : Mfw_em_cb |
491 +--------------------------------------------------------------------+
492
493 PURPOSE : Handles events from the ACI EM driver
494
495 */
496 void Mfw_em_cb(T_DRV_SIGNAL_EM* signal)
497 {
498 TRACE_EVENT_P1("Mfw_em_cb, signalType: %d", signal->SignalType);
499
500 switch(signal->SignalType)
501 {
502 case EM_SUBCLASS_SC:
503 { /*copy Serving Cell Information to appropriate data structure*/
504
505 T_EM_SC_INFO_CNF *serv_cell = (T_EM_SC_INFO_CNF*)&signal->UserData.sc;
506
507 MfwEmData->SCInfo.arfcn = serv_cell->arfcn;
508 MfwEmData->SCInfo.RSSI = serv_cell->rxlev;
509 MfwEmData->SCInfo.RXQ = serv_cell->rxqual_f;
510 MfwEmData->SCInfo.RLT = serv_cell->rlt;
511 MfwEmData->SCInfo.C1 = serv_cell->c1;
512 MfwEmData->SCInfo.C2 = serv_cell->c2;
513 MfwEmData->SCInfo.BSIC = serv_cell->bsic;
514 MfwEmData->SCInfo.TAV = serv_cell->tav;
515 MfwEmData->SCInfo.LAC = serv_cell->lac;
516
517 MfwEmData->NCInfo.arfcn[6] = MfwEmData->SCInfo.arfcn;
518 MfwEmData->NCInfo.RSSI[6] = MfwEmData->SCInfo.RSSI;
519 MfwEmData->NCInfo.C2[6] = MfwEmData->SCInfo.C2;
520 MfwEmData->NCInfo.LAC_NC[6] = MfwEmData->SCInfo.LAC;
521 MfwEmData->NCInfo.BSIC_NC[6] = MfwEmData->SCInfo.BSIC;
522
523 /* copy Location Info*/
524 MfwEmData->LocInfo.LAC = serv_cell->lac;
525
526 /*send event to MMI*/
527 Mfw_em_signal(EM_SERVING_CELL_PARAMS, (void*)&MfwEmData->SCInfo);
528 }
529 break;
530 case EM_SUBCLASS_SC_GPRS:
531 { /*MC, SPR 1554 added code to copy NMOinto GPRS data structure*/
532
533 T_EM_SC_GPRS_INFO_CNF *gprs_info = (T_EM_SC_GPRS_INFO_CNF*)&signal->UserData.sc_gprs;
534
535 MfwEmData->GPRSInfo.NMO = gprs_info->nmo;
536 MfwEmData->GPRSInfo.NDTS = gprs_info->tn;
537 MfwEmData->GPRSInfo.RAC = gprs_info->rac;
538 MfwEmData->GPRSInfo.C31 = gprs_info->c31;
539 MfwEmData->GPRSInfo.C32 = gprs_info->c32;
540
541 Mfw_em_signal(EM_GPRS_PARAMS, (void*)&MfwEmData->GPRSInfo);
542 }
543 break;
544 case EM_SUBCLASS_NC:
545 { T_EM_NC_INFO_CNF *neighbour_cell = (T_EM_NC_INFO_CNF*)&signal->UserData.nc;
546 MfwEmData->NCInfo.NUM = neighbour_cell->no_ncells;
547 memcpy(MfwEmData->NCInfo.arfcn, neighbour_cell->arfcn_nc, 6*sizeof(USHORT));
548 memcpy(MfwEmData->NCInfo.RSSI, neighbour_cell->rxlev_nc, 6*sizeof(UBYTE));
549 memcpy(MfwEmData->NCInfo.C2, neighbour_cell->c2_nc, 6*sizeof(SHORT));
550 memcpy(MfwEmData->NCInfo.LAC_NC, neighbour_cell->lac_nc, 6*sizeof(USHORT));
551 memcpy(MfwEmData->NCInfo.BSIC_NC, neighbour_cell->bsic_nc, 6*sizeof(UBYTE));
552 Mfw_em_signal(EM_NEIGHBOURING_CELL_PARAMS, (void*)&MfwEmData->NCInfo);
553 }
554 case EM_SUBCLASS_LOC_PAG:
555 { MfwEmData->LocInfo.LUP = signal->UserData.log_pag.t3212;
556 /*Convert MCC & MNC to ASCII strings from BCD*/
557 utl_BCD2DialStr (signal->UserData.log_pag.mcc, MfwEmData->LocInfo.MCC, 3);
558 utl_BCD2DialStr (signal->UserData.log_pag.mnc, MfwEmData->LocInfo.MNC, 3);
559 Mfw_em_signal(EM_LOCATION_PARAMS, (void*)&MfwEmData->LocInfo);
560 }
561 case EM_SUBCLASS_CIPH_HOP_DTX:
562 { MfwEmData->CHDTXInfo.ciph_status = signal->UserData.cip.ciph_stat;
563 MfwEmData->CHDTXInfo.HSN = signal->UserData.cip.hsn;
564 //!!!!!HOPPING CHANNELS!!!!!!!!!!!!!!
565 /* memcpy(MfwEmData->CHDTXInfo.ma, signal->UserData.cip.hop_chn.ma, 65);
566 if (signal->UserData.cip.hop_chn.v_start)
567 {
568 memcpy(MfwEmData->CHDTXInfo.ma2, signal->UserData.cip.hop_chn.ma2, 65);
569 }*/
570 MfwEmData->CHDTXInfo.DTX_status = signal->UserData.cip.dtx_stat;
571 Mfw_em_signal(EM_CIPH_HOP_DTX_PARAMS, (void*)&MfwEmData->CHDTXInfo);
572 }
573 case EM_SUBCLASS_ID:
574 { /*MC, SPR 1554 added conversion of IMEI and IMSI from numbers to ASCII*/
575
576 int i;
577 /*convert to ASCII digits*/
578 for (i=0; i < 15; i++)
579 {
580 MfwEmData->MobileInfo.IMEI[i]= signal->UserData.id.em_imeisv.ident_dig[i] + ASCII_OFFSET;
581 MfwEmData->MobileInfo.IMSI[i]=signal->UserData.id.em_imsi.ident_dig[i] +ASCII_OFFSET;
582 }
583 MfwEmData->MobileInfo.IMEI[15] = NULL;
584 MfwEmData->MobileInfo.IMSI[15] = NULL;
585
586 MfwEmData->MobileInfo.TMSI = signal->UserData.id.tmsi;
587
588 Mfw_em_signal(EM_MOBILE_INFO, (void*)&MfwEmData->MobileInfo);
589 }
590 case EM_SUBCLASS_SW_VERSION:
591 {
592 T_EM_SW_VER* sw_ver = &signal->UserData.version;
593 memcpy(MfwEmData->MobileInfo.SIM_version, sw_ver->sim, MAX_VER*sizeof(char));
594 memcpy(MfwEmData->MobileInfo.CC_version , sw_ver->cc, MAX_VER*sizeof(char));
595 memcpy(MfwEmData->MobileInfo.SS_version , sw_ver->ss, MAX_VER*sizeof(char));
596 memcpy(MfwEmData->MobileInfo.SMS_version , sw_ver->sms, MAX_VER*sizeof(char));
597 memcpy(MfwEmData->MobileInfo.MM_version, sw_ver->mm, MAX_VER*sizeof(char));
598 memcpy(MfwEmData->MobileInfo.RR_version , sw_ver->rr, MAX_VER*sizeof(char));
599 memcpy(MfwEmData->MobileInfo.DL_version , sw_ver->dl, MAX_VER*sizeof(char));
600 memcpy(MfwEmData->MobileInfo.ALR_version , sw_ver->alr, MAX_VER*sizeof(char));
601 }
602 default:
603 TRACE_EVENT("Unknown EM data type");
604
605 }
606
607 }