comparison gsm-fw/g23m-gsm/alr/alr_cbch.c @ 673:2f7df7a314f8

gsm-fw/g23m-gsm subtree: initial import from LoCosto source
author Michael Spacefalcon <msokolov@ivan.Harhan.ORG>
date Sun, 28 Sep 2014 23:20:04 +0000
parents
children 029f631b22ff
comparison
equal deleted inserted replaced
672:0dc6f9e8e980 673:2f7df7a314f8
1 /*
2 +-----------------------------------------------------------------------------
3 | Project : GSM-PS
4 | Modul : ALR_CBCH
5 +-----------------------------------------------------------------------------
6 | Copyright 2002 Texas Instruments Berlin, AG
7 | All rights reserved.
8 |
9 | This file is confidential and a trade secret of Texas
10 | Instruments Berlin, AG
11 | The receipt of or possession of this file does not convey
12 | any rights to reproduce or disclose its contents or to
13 | manufacture, use, or sell anything it may describe, in
14 | whole, or in part, without the specific written consent of
15 | Texas Instruments Berlin, AG.
16 +-----------------------------------------------------------------------------
17 | Purpose : This Modul defines the SDL process CBCH_control.
18 +-----------------------------------------------------------------------------
19 */
20
21 #ifndef ALR_CBCH_C
22 #define ALR_CBCH_C
23
24 #define ENTITY_PL
25
26 /*==== INCLUDES ===================================================*/
27 #include <string.h>
28 #include <stdlib.h>
29 #include <ctype.h>
30 #include "typedefs.h"
31 #include "pconst.cdg"
32 #include "mconst.cdg"
33 #include "message.h"
34 #include "ccdapi.h"
35 #include "vsi.h"
36 #include "custom.h"
37 #include "gsm.h"
38 #include "prim.h"
39 #include "cnf_alr.h"
40 #include "mon_alr.h"
41 #include "pei.h"
42 #include "tok.h"
43
44 #include "pcm.h"
45 #ifdef GPRS
46 #include "alr_gprs.h"
47 #endif
48 #include "alr.h"
49 #include "alr_em.h"
50
51 /*==== EXPORT =====================================================*/
52 /*==== PRIVAT =====================================================*/
53 LOCAL void cb_read_cbch (UBYTE flags);
54 LOCAL void cb_check_ci_lai_plmn (void);
55 LOCAL void cb_remove_message (USHORT i);
56 LOCAL void cb_first_block (UBYTE status);
57 LOCAL UBYTE* cb_create_schedule_entries (UBYTE* msg_ptr, BOOL read_old_msg);
58 LOCAL void cb_create_schedule_map (UBYTE old_cb_msg);
59 LOCAL UBYTE cb_check_old_msg (void);
60 LOCAL UBYTE cb_check_data_coding_scheme(UBYTE dcs_id);
61 LOCAL UBYTE cb_check_message_id (USHORT msg_id);
62 LOCAL void cb_store_cbch_msg (void);
63 LOCAL void cb_error_ind (void);
64 LOCAL void cb_cbch_message (UBYTE length);
65 LOCAL void cb_null_message (void);
66 LOCAL void cb_schedule_message (void);
67 LOCAL void cb_next_scheduled_msg (void);
68 LOCAL UBYTE cb_sat_check_message_id (USHORT msg_id);
69 LOCAL void cb_sat_cbch_message (UBYTE length);
70 LOCAL void cb_stop_next_blocks (void);
71 LOCAL void cb_read_next_3_blocks(void);
72 void set_cbch_state( UBYTE extended, UBYTE new_state);
73 UBYTE get_cbch_state( UBYTE extended);
74
75 #if defined(FF_HOMEZONE)
76 LOCAL UBYTE cb_check_homezone (UBYTE length);
77 #endif /* FF_HOMEZONE */
78
79 LOCAL void cb_alr_trace_msghead (T_CBMSG_HEADER *ph);
80
81 /*
82 * support indication of geographical scope change to MMI
83 * it is important that these defitions match the GS definition from GSM 03.41
84 * the MMI uses this also to compare with real CBCH messages!
85 */
86 #define CB_GEOGR_CHANGE_NONE 0x00
87 #define CB_GEOGR_CHANGE_CELL 0xC0
88 #define CB_GEOGR_CHANGE_LAC 0x80
89 #define CB_GEOGR_CHANGE_PLMN 0x40
90
91 #define CB_GEOGR_SCOPE_CELLI 0x00
92 #define CB_GEOGR_SCOPE_PLMN 0x01
93 #define CB_GEOGR_SCOPE_LAC 0x02
94 #define CB_GEOGR_SCOPE_CELLN 0x03
95
96 #define CBCH_NO_MSG 0
97 #define CBCH_NORM_MSG 1
98 #define CBCH_SCHEDULE_MSG 2
99 #define CBCH_SAT_MSG 3
100 #define CBCH_LAST_BLOCK 0x10
101
102 #define CBCH_BLOCK_0 0
103 #define CBCH_BLOCK_1 1
104 #define CBCH_BLOCK_2 2
105 #define CBCH_BLOCK_3 3
106 #define CBCH_FIRST_SCHED_MSG 8
107 #define CBCH_NULL_MSG 0x0F
108 #define CBCH_SCHED 2
109
110 #define MAX_UPDATE_NO 16
111 #define MAX_UPDATE_NO_DIFF 8
112
113 #if 1 || defined (WIN32)
114 #define TRACING
115 #endif
116
117 #define CB_SERIAL_NO(ph) ((USHORT)\
118 ((((T_CBMSG_HEADER*)(ph))->serial_no1)<<8)+\
119 (((T_CBMSG_HEADER*)(ph))->serial_no2))
120
121 #define CB_GS_CODE(ph) (((UBYTE)(((T_CBMSG_HEADER*)(ph))->serial_no1))>>6)
122
123 #define CB_MSG_CODE(ph) ((USHORT)\
124 (((((T_CBMSG_HEADER*)(ph))->serial_no1)&0x3f)<<4)+\
125 ((((T_CBMSG_HEADER*)(ph))->serial_no2)>>4))
126
127 #define CB_UPDATE_NO(ph) ((((T_CBMSG_HEADER*)(ph))->serial_no2)&0x0f)
128
129 #define CB_MESSAGE_ID(ph) ((USHORT)\
130 ((((T_CBMSG_HEADER*)(ph))->msg_id3)<<8)+\
131 (((T_CBMSG_HEADER*)(ph))->msg_id4))
132 #if 0
133 #define CB_MESSAGE_ID(ph) ((((USHORT)(((T_CBMSG_HEADER*)(ph))->msg_id3))<<8)+\
134 ((USHORT)(((T_CBMSG_HEADER*)(ph))->msg_id4)))
135
136 #endif /* 0 */
137 #define CB_DCS(ph) (((T_CBMSG_HEADER*)(ph))->dcs)
138
139 #define CB_PAGE(ph) (((T_CBMSG_HEADER*)(ph))->page>>4)
140 #define CB_PAGETOTAL(ph) (((T_CBMSG_HEADER*)(ph))->page&0x0f)
141
142
143 #if defined (TRACING)
144 #define ALR_TRACE_CB(a) TRACE_EVENT("CBCH: " a)
145 #define ALR_TRACE_CB_MODUS(m) TRACE_EVENT_P1("CBCH: modus=%d", m)
146 #define ALR_TRACE_CB_ERROR(e) TRACE_EVENT_P1("CBCH: error=%d", e)
147 #define ALR_TRACE_CB_BLOCK_NO(b) TRACE_EVENT_P2("CBCH: block=%02x no=%u", b, b&0x0f)
148 #define ALR_TRACE_CB_MSGHEAD(ph) cb_alr_trace_msghead(ph)
149
150 #define ALR_TRACE_CB_MSGID(m) TRACE_EVENT_P1("CBCH: ID=%u", m)
151 #define ALR_TRACE_CB_START_READ(f) TRACE_EVENT_P1("CBCH: Start Read %d", f)
152 #define ALR_TRACE_CB_SCHEDULE(a1,a2) TRACE_EVENT_P2("CBCH: schedule i=%d result=%d", a1,a2)
153 #define ALR_TRACE_CB_HZREQ(a1,a2) TRACE_EVENT_P2("CBCH: Homezone ID=%u, t=%u", a1,a2)
154 #define ALR_TRACE_CB_SCOPE_CHANGE(i,s) TRACE_EVENT_P2 ("CBCH: Geogr. scope change %u, deleting msg of scope %u",\
155 i,s);
156 #else /* TRACING */
157 #define ALR_TRACE_CB(a)
158 #define ALR_TRACE_CB_MODUS(m)
159 #define ALR_TRACE_CB_ERROR(e)
160 #define ALR_TRACE_CB_BLOCK_NO(b)
161 #define ALR_TRACE_CB_MSGID(m)
162 #define ALR_TRACE_CB_START_READ(f)
163 #define ALR_TRACE_CB_SCHEDULE(a1,a2)
164 #define ALR_TRACE_CB_HZREQ(a1,a2)
165 #endif /* TRACING */
166
167 /*==== VARIABLES ==================================================*/
168 /*==== FUNCTIONS ==================================================*/
169
170 #if 0
171 #if 0
172 #define TRACE_ALIGN_P(ps,m,t) TRACE_EVENT_P5(" %08x %3u.%u %08x=%u " \
173 "T_" #t " " #m, \
174 (BYTE*)&(m), (BYTE*)&(m)-(BYTE*)ps, \
175 sizeof (m),
176 sizeof (m) > 1 ? (USHORT)(m) : (UBYTE)(m), m \
177 )
178 #else
179 #define TRACE_ALIGN_P(ps,m,t) TRACE_EVENT_P4 (" %08x %3u.%u %08x " \
180 "T_" #t " " #m, \
181 (BYTE*)&(m), (BYTE*)&(m)-(BYTE*)ps, \
182 sizeof (m), m\
183 )
184 #endif
185 int test_alignment (T_CBMSG_HEADER *ph)
186 {
187 TRACE_ALIGN_P (ph, ph->serial_no1, CBMSG_HEADER);
188 TRACE_ALIGN_P (ph, ph->serial_no2, CBMSG_HEADER);
189 TRACE_ALIGN_P (ph, ph->msg_id3, CBMSG_HEADER);
190 TRACE_ALIGN_P (ph, ph->msg_id4, CBMSG_HEADER);
191 TRACE_ALIGN_P (ph, ph->dcs, CBMSG_HEADER);
192 TRACE_ALIGN_P (ph, ph->page, CBMSG_HEADER);
193 }
194 #endif
195
196 /*
197 +--------------------------------------------------------------------+
198 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
199 | STATE : code ROUTINE : cb_init |
200 +--------------------------------------------------------------------+
201
202 PURPOSE : Initialize CBCH Control Process.
203 */
204
205 GLOBAL void cb_init (void)
206 {
207 GET_INSTANCE_DATA;
208 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
209
210 ALR_TRACE_CB ("cb_init()");
211 alr_data->state[STATE_NORMAL_CBCH] = CBCH_NULL;
212 alr_data->state[STATE_EXT_CBCH] = CBCH_NULL;
213 pcbch->modus = NOT_PRESENT_8BIT;
214 pcbch->old_cbch_msg.cnt = 0;
215 #if defined(FF_HOMEZONE)
216 pcbch->homezone = CBCH_HZ_OFF;
217 pcbch->hz_timeout = 0;
218 #endif /* FF_HOMEZONE */
219 }
220
221 /*
222 +--------------------------------------------------------------------+
223 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
224 | STATE : code ROUTINE : cb_stop |
225 +--------------------------------------------------------------------+
226
227 PURPOSE : Stop CBCH Control Process.
228
229 cb_stop will be called in the following three scenarios -
230 1. Moving from IDLE to DEDICATED state
231 2. ALR has received HomeZone information.
232 3. MMI indicates stop reading CBCH.
233
234 In all three cases ALR need to forward this to L1.
235 Eventhough the homezone request is pending we need to stop
236 the CBCH reading.
237 */
238
239 GLOBAL void cb_stop (void)
240 {
241 GET_INSTANCE_DATA;
242 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
243 UBYTE normal_cbch, extended_cbch;
244
245 normal_cbch = GET_STATE(STATE_NORMAL_CBCH);
246 extended_cbch = GET_STATE(STATE_EXT_CBCH);
247
248 if (
249 (normal_cbch NEQ CBCH_NULL AND normal_cbch NEQ CBCH_IDLE)
250 OR
251 (extended_cbch NEQ CBCH_NULL AND extended_cbch NEQ CBCH_IDLE)
252 )
253 {
254 /*
255 * if CBCH process is really active, initialize
256 * CBCH process and stop CBCH process in layer 1.
257 */
258 pcbch->msg_type = CBCH_NO_MSG;
259
260 SET_STATE(STATE_NORMAL_CBCH, CBCH_IDLE);
261 SET_STATE(STATE_EXT_CBCH, CBCH_IDLE);
262
263 ALR_EM_STOP_CBCH_READING;
264
265 ma_cb_stop_cbch_req();
266 }
267 }
268
269
270 /*
271 +--------------------------------------------------------------------+
272 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
273 | STATE : code ROUTINE : cb_start |
274 +--------------------------------------------------------------------+
275
276 PURPOSE : Re-configure layer 1 and go back to CBCH reading without
277 scheduling information.
278 */
279
280 LOCAL void cb_start_no_drx_reading (UBYTE config)
281 {
282 GET_INSTANCE_DATA;
283 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
284
285 if (config)
286 {
287 /*
288 * configure layer 1
289 */
290 PALLOC (config_cbch, MPHC_CONFIG_CBCH_REQ);
291
292 /*
293 * copy the stored configuration received earlier from RR and send to layer 1.
294 */
295 memcpy (config_cbch, &pcbch->mphc_config_cbch, sizeof (T_MPHC_CONFIG_CBCH_REQ));
296 ma_cb_config_cbch(config_cbch);
297 }
298
299 /*
300 * start reading in layer 1 for normal and extended CBCH.
301 * The initial mode is no Scheduling information available.
302 */
303 cb_read_cbch (CBCH_NO_SCHED | CBCH_READ_NORM);
304 cb_read_cbch (CBCH_NO_SCHED | CBCH_READ_EXT);
305
306 SET_STATE(STATE_NORMAL_CBCH, CBCH_NO_DRX);
307 SET_STATE(STATE_EXT_CBCH, CBCH_NO_DRX);
308
309 #if defined(FF_HOMEZONE)
310 if (pcbch->homezone EQ CBCH_HZ_IDLE)
311 {
312 pcbch->homezone = CBCH_HZ_PENDING;
313 /* start timer new */
314 if (pcbch->hz_timeout)
315 TIMERSTART(TIM_HOMEZONE, pcbch->hz_timeout);
316 ALR_TRACE_CB ("HOMEZONE is pending");
317 }
318 #endif /* FF_HOMEZONE */
319 }
320
321 /*
322 +--------------------------------------------------------------------+
323 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
324 | STATE : code ROUTINE : cb_start |
325 +--------------------------------------------------------------------+
326
327 PURPOSE : Start CBCH Control Process.
328 */
329
330 GLOBAL void cb_start (void)
331 {
332 GET_INSTANCE_DATA;
333 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
334
335 if ( (GET_STATE(STATE_NORMAL_CBCH) EQ CBCH_IDLE)
336 AND ( (pcbch->modus NEQ NOT_PRESENT_8BIT)
337 OR (pcbch->sat_enabled)
338 #if defined(FF_HOMEZONE)
339 OR (pcbch->homezone EQ CBCH_HZ_IDLE)
340 #endif /* FF_HOMEZONE */
341 )
342 )
343 {
344 /*
345 * if a definition of needed message identifiers
346 * and data coding schemes is available, then configure
347 * layer 1
348 */
349 ALR_TRACE_CB ("restart");
350 cb_start_no_drx_reading (TRUE);
351 }
352 }
353
354 /*
355 +--------------------------------------------------------------------+
356 | PROJECT : GSM-PS (6103) MODULE : TIL_CBCH |
357 | STATE : code ROUTINE : cb_mph_cbch_req |
358 +--------------------------------------------------------------------+
359
360 PURPOSE : Configuration of the layer 1 process for CBCH.
361
362 The compile-switch is not defined with the standard TI-layer 1.
363
364 But there shall be a little modification possible (and it is
365 done by some source code customer of layer 1), which does not
366 need any storing in ALR. Then the compile switch must be set
367
368 REMARK : Setting of compile switch has problems with function cbch_start ???
369
370 */
371
372 GLOBAL void cb_mph_cbch_req (T_cbch * cbch)
373 {
374 GET_INSTANCE_DATA;
375 USHORT i;
376 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
377 T_cbch_desc *pcbch_desc = &pcbch->mphc_config_cbch.cbch_desc;
378 T_chan_sel *pchan_sel = &pcbch_desc->chan_sel;
379 T_cbch_freq_list *pcbch_freq_list = &pcbch->mphc_config_cbch.cbch_freq_list;
380
381 ALR_TRACE_CB ("MPH_CBCH_REQ");
382
383 ALR_EM_CONFIGURE_CBCH_CHANNEL;
384
385 #if defined(FF_HOMEZONE)
386 if (pcbch->homezone NEQ CBCH_HZ_OFF)
387 pcbch->homezone = CBCH_HZ_IDLE; /* starts HZ request again */
388 #endif /* FF_HOMEZONE */
389
390 /* check which messages have to be deleted
391 * even if the new cell has CBCH disabled! We still need to
392 * to delete the corresponding messages and inform the MMI!
393 */
394 if (pcbch->modus EQ CBCH_ACCEPT)
395 cb_check_ci_lai_plmn ();
396
397 if (cbch->stat EQ STAT_ACT)
398 {
399 /*
400 * A CBCH channel is available
401 */
402
403 #if !defined (L1_STORES_CBCH_CONFIG)
404 /*
405 * Layer 1 does not store any CBCH configuration (default)
406 * first set the channel configuration
407 */
408 if (cbch->h EQ H_FREQ)
409 {
410 /*
411 * with frequency hopping, set hopping flag, maio, hsn and hopping list.
412 */
413 pchan_sel->h = HOPPING;
414 pchan_sel->rf_channel.maio = cbch->maio;
415 pchan_sel->rf_channel.hsn = cbch->hsn;
416
417 i=0;
418 pcbch_freq_list->rf_chan_cnt=0;
419 while ((i < 64) AND (cbch->ma[i] NEQ NOT_PRESENT_16BIT))
420 {
421 pcbch_freq_list->rf_chan_no.radio_freq[i] = ARFCN_TO_L1(cbch->ma[i]);
422 i++;
423 pcbch_freq_list->rf_chan_cnt++;
424 }
425 }
426 else
427 {
428 /*
429 * Layer 1 uses a union definition. This is not applicable for the Condat-SAP model.
430 * Therefore the rf channel number is configured by maio and hsn. In general a Avoid the union !!!
431 */
432 pchan_sel->h = NO_HOPPING;
433 pchan_sel->rf_channel.maio = (UBYTE)(ARFCN_TO_L1(cbch->arfcn) & 0xFF);
434 pchan_sel->rf_channel.hsn = (UBYTE)((ARFCN_TO_L1(cbch->arfcn) >> 8) & 0xFF);
435 memset (pcbch_freq_list, 0, sizeof (T_cbch_freq_list));
436 }
437
438 /*
439 * configure the CBCH channel type (SDCCH/8 or SDCCH/4)
440 */
441 if (cbch->ch < CH_SDCCH_8_0)
442 pcbch_desc->channel_type = CH_SDCCH_4;
443 else
444 pcbch_desc->channel_type = CH_SDCCH_8;
445
446 pcbch_desc->sub_channel = 0; /* not relevant */
447 pcbch_desc->timeslot_no = cbch->tn;
448 pcbch_desc->tsc = cbch->tsc;
449
450 #else
451 /*
452 * Compile option set: L1 stores actual CBCH configuration.
453 * So it is not necessary to store the configuration in ALR.
454 * Just parse the configuration to Layer 1.
455 */
456 {
457 PALLOC (config_cbch, MPHC_CONFIG_CBCH);
458
459 if (cbch->h EQ H_FREQ)
460 {
461 /*
462 * with frequency hopping, set hopping flag, maio, hsn and hopping list.
463 */
464 config_cbch->cbch_desc.chan_sel.h = HOPPING;
465 config_cbch->cbch_desc.chan_sel.rf_channel.maio = cbch->maio;
466 config_cbch->cbch_desc.chan_sel.rf_channel.hsn = cbch->hsn;
467
468 i=0;
469 config_cbch->cbch_freq_list.rf_chan_cnt=0;
470 while (cbch->ma[i] NEQ NOT_PRESENT_16BIT AND i < 64)
471 {
472 config_cbch->cbch_freq_list.rf_chan_no.hop_chan[i] = ARFCN_TO_L1(cbch->ma[i]);
473 i++; config_cbch->cbch_freq_list.rf_chan_cnt++;
474 }
475 }
476 else
477 {
478 /*
479 * Layer 1 uses a union definition. This is not applicable for the Condat-SAP model.
480 * Therefore the rf channel number is configured by maio and hsn. In general a Avoid the union !!!
481 */
482 config_cbch->cbch_desc.chan_sel.h = NO_HOPPING;
483 config_cbch->cbch_desc.chan_sel.rf_channel.maio = ARFCN_TO_L1(cbch->arfcn) & 0xFF;
484 config_cbch->cbch_desc.chan_sel.rf_channel.hsn = (ARFCN_TO_L1(cbch->arfcn) >> 8) & 0xFF;
485 memset (&config_cbch->cbch_freq_list, 0, sizeof (T_cbch_freq_list));
486 }
487
488 /*
489 * configure the CBCH channel type (SDCCH/8 or SDCCH/4)
490 */
491 if (cbch->ch < CH_SDCCH_8_0)
492 config_cbch->cbch_desc.channel_type = CH_SDCCH_4;
493 else
494 config_cbch->cbch_desc.channel_type = CH_SDCCH_8;
495
496 config_cbch->cbch_desc.sub_channel = 0; /* not relevant */
497 config_cbch->cbch_desc.timeslot_no = cbch->tn;
498 config_cbch->cbch_desc.tsc = cbch->tsc;
499
500 ma_cb_config_cbch(config_cbch);
501 }
502 #endif
503
504 if ( (pcbch->modus NEQ NOT_PRESENT_8BIT)
505 OR (pcbch->sat_enabled)
506 #if defined(FF_HOMEZONE)
507 OR (pcbch->homezone EQ CBCH_HZ_IDLE)
508 #endif /* FF_HOMEZONE */
509 )
510 {
511 /*
512 * MMI has requested data
513 * Start with NO_DRX mode
514 * Read each first CBCH block
515 */
516 #if defined (L1_STORES_CBCH_CONFIG)
517 cb_start_no_drx_reading (FALSE);
518 #else /* L1_STORES_CBCH_CONFIG */
519 ALR_TRACE_CB ("switch on, send config");
520 cb_start_no_drx_reading (TRUE);
521 #endif /* L1_STORES_CBCH_CONFIG */
522 }
523 else
524 {
525 UBYTE *si3 = &alr_data->ma_data.sys_info_3[0];
526 UBYTE *lac = &alr_data->cbch_data.old_cid_plmn_lac[0];
527
528 ALR_TRACE_CB ("switch on, wait for MMI");
529 /*
530 * wait for MMI request
531 */
532 SET_STATE(STATE_NORMAL_CBCH, CBCH_IDLE);
533 SET_STATE(STATE_EXT_CBCH, CBCH_IDLE);
534 /*
535 * update old_cid_plmn_lac
536 */
537 memcpy (lac, &si3[2], 7);
538 }
539 }
540 else
541 {
542 /*
543 * The new configuration indicates no CBCH, so stop the CBCH process in Layer 1
544 */
545 ALR_TRACE_CB ("switch off");
546
547 cb_stop();
548 SET_STATE(STATE_NORMAL_CBCH, CBCH_NULL);
549 SET_STATE(STATE_EXT_CBCH, CBCH_NULL);
550 }
551 }
552
553 /*
554 +--------------------------------------------------------------------+
555 | PROJECT : GSM-PS (6103) MODULE : AKR_CBCH |
556 | STATE : code ROUTINE : cb_mmi_cbch_req |
557 +--------------------------------------------------------------------+
558
559 PURPOSE : MMI sends a definition of the expected message identifier
560 and data coding schemes for the CBCH messages.
561
562 */
563
564 GLOBAL void cb_mmi_cbch_req (T_MMI_CBCH_REQ *cbch)
565 {
566 GET_INSTANCE_DATA;
567 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
568 ALR_TRACE_CB ("MMI req");
569
570 #if defined(FF_HOMEZONE)
571 if (cbch->modus NEQ CBCH_HOMEZONE)
572 {
573 pcbch->modus = cbch->modus;
574 TRACE_EVENT_P1 ("CBCH: homezone=%u", pcbch->homezone);
575 }
576 else if (cbch->msg_id[0] EQ NOT_PRESENT_16BIT)
577 {
578 /*
579 * switch off automatically homezone request
580 * - homezone state to off
581 * - clear old message
582 * - stop timer
583 */
584 pcbch->msg_hz_id = NOT_PRESENT_16BIT;
585 pcbch->homezone = CBCH_HZ_OFF;
586 TIMERSTOP (TIM_HOMEZONE);
587 }
588 else
589 {
590 /*
591 * switch on automatically homezone request
592 * - set homezone state to idle whatever are before
593 * - set new homezone id
594 * - clear old message
595 */
596 pcbch->msg_hz_id = cbch->msg_id[0];
597 pcbch->dcs_hz_id = cbch->dcs_id[0];
598 pcbch->hz_timeout = cbch->dcs_id[1]*1000;
599 ALR_TRACE_CB_HZREQ (pcbch->msg_hz_id,
600 pcbch->hz_timeout);
601 if (pcbch->homezone EQ CBCH_HZ_OFF)
602 {
603 UBYTE cbch_state = GET_STATE (STATE_NORMAL_CBCH);
604 pcbch->homezone = CBCH_HZ_IDLE;
605 if (cbch_state NEQ CBCH_NULL)
606 {/* CBCH system is prepared */
607 if (cbch_state EQ CBCH_IDLE)
608 { /* start timer only if CBCH system is prepared */
609 TIMERSTART (TIM_HOMEZONE, 1000);
610 }
611 else
612 { /* CBCH system is already active -> wait for HZ message */
613 pcbch->homezone = CBCH_HZ_PENDING;
614 TIMERSTART (TIM_HOMEZONE, pcbch->hz_timeout);
615 ALR_TRACE_CB ("HOMEZONE is pending");
616 }
617 }
618 }
619 return;
620 }
621 #else /* FF_HOMEZONE */
622 pcbch->modus = cbch->modus;
623 #endif /* FF_HOMEZONE */
624 /*
625 * Storing of Parameter and clearing of
626 * the received CB memory
627 */
628 memcpy (&pcbch->msg_id[0], cbch->msg_id, sizeof (pcbch->msg_id));
629 memcpy (&pcbch->dcs_id[0], cbch->dcs_id, sizeof (pcbch->dcs_id));
630
631 #if !defined(NTRACE)
632 {
633 int i;
634
635 ALR_TRACE_CB_MODUS(cbch->modus);
636
637 for (i=0;
638 (i < MAX_IDENTS) AND (pcbch->msg_id[i] NEQ NOT_PRESENT_16BIT);
639 i++)
640 {
641 TRACE_EVENT_P2 ("CBCH: id[%u]=%u", i, pcbch->msg_id[i]);
642 }
643 for (i=0;
644 (i < MAX_IDENTS) AND (pcbch->dcs_id[i] NEQ NOT_PRESENT_8BIT);
645 i++)
646 {
647 TRACE_EVENT_P2 ("CBCH:dcs[%u]=%u", i, pcbch->dcs_id[i]);
648 }
649 }
650 #endif /* !NTRACE */
651
652 /* old messages should only be erased when MMI turns CBCH off */
653 if (pcbch->modus EQ MMI_CBCH_STOP)
654 {
655 /* also erases the count of old message */
656 memset (&pcbch->old_cbch_msg, 0, sizeof (T_CB_MSG));
657 memset (&pcbch->msg[0], 0, CBCH_MSG_SIZE);
658 }
659
660 /*
661 TRACE_EVENT_P2 ("CBCH: STATE_MA=%u STATE_CBCH=%u", GET_STATE(STATE_MA), GET_STATE (STATE_CBCH));
662 */
663
664 #ifdef GPRS
665 if ((GET_STATE(STATE_MA) EQ MA_IDLE AND !alr_data->gprs_data.pbcch) OR
666 (alr_data->gprs_data.pbcch AND alr_data->gprs_data.pim))
667 #else
668 if (GET_STATE(STATE_MA) EQ MA_IDLE)
669 #endif
670 {
671 /*
672 * layer 1 is only configured, if ALR is in idle state, else the configuration
673 * is delayed until the cell is selected.
674 */
675 switch (GET_STATE (STATE_NORMAL_CBCH))
676 {
677 case CBCH_NULL:
678 /*
679 * no CBCH channel is available
680 */
681 break;
682
683 case CBCH_IDLE:
684 if (pcbch->modus EQ MMI_CBCH_STOP AND
685 !pcbch->sat_enabled)
686 {
687 /*
688 * CBCH download is not enabled and the MMI indicates stop of
689 * the CBCH channel, then stop CBCH process in layer 1.
690 */
691 cb_stop();
692 }
693 else
694 {
695 /*
696 * new definitions of message identifier or data coding schemes
697 * then re-configure layer 1 and go back to CBCH reading without
698 * scheduling information.
699 */
700 cb_start_no_drx_reading (TRUE);
701 }
702 break;
703
704 default:
705 /*
706 * we already received a MMI CBCH REQ before
707 */
708 if (pcbch->modus EQ MMI_CBCH_STOP AND
709 !pcbch->sat_enabled)
710 {
711 /*
712 * CBCH download is not enabled and the MMI indicates stop of
713 * the CBCH channel, then stop CBCH process in layer 1.
714 */
715 cb_stop();
716 SET_STATE(STATE_NORMAL_CBCH, CBCH_IDLE);
717 SET_STATE(STATE_EXT_CBCH, CBCH_IDLE);
718 }
719 break;
720 }
721 }
722 }
723
724 /*
725 +--------------------------------------------------------------------+
726 | PROJECT : GSM-PS (6103) MODULE : TIL_CBCH |
727 | STATE : code ROUTINE : cb_mmi_sat_cbch_req |
728 +--------------------------------------------------------------------+
729
730 PURPOSE : Reception of a list of identifiers for SIM TOOLKIT
731 CBCH Download.
732
733 */
734
735 GLOBAL void cb_mmi_sat_cbch_req (T_MMI_SAT_CBCH_DWNLD_REQ * cbch_req)
736 {
737 GET_INSTANCE_DATA;
738 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
739 unsigned i;
740 ALR_TRACE_CB ("MMI SAT req");
741
742 /*
743 * clear the list of needed message identifier for CBCH download
744 * and fill it with the definiton of MMI.
745 */
746 memset (pcbch->msg_id_sat, NOT_PRESENT_16BIT,
747 sizeof(pcbch->msg_id_sat));
748 memcpy (pcbch->msg_id_sat, cbch_req->msg_id,
749 sizeof(cbch_req->msg_id[0])*(cbch_req->count));
750
751 /*
752 * CBCH download is disabled
753 */
754 pcbch->sat_enabled = FALSE;
755 for (i = 0; i < cbch_req->count; i++)
756 {
757 if (pcbch->msg_id_sat[i] NEQ NOT_PRESENT_16BIT)
758 {
759 pcbch->sat_enabled = TRUE;
760 break;
761 }
762 }
763 vsi_o_error_ttrace ("HM cb_mmi_sat_cbch_req(), sat_enabled = %d, modus = %d",
764 pcbch->sat_enabled, pcbch->modus);
765 #ifdef GPRS
766 if ((GET_STATE(STATE_MA) EQ MA_IDLE AND !alr_data->gprs_data.pbcch) OR
767 (alr_data->gprs_data.pbcch AND alr_data->gprs_data.pim))
768 #else
769 if (GET_STATE(STATE_MA) EQ MA_IDLE)
770 #endif
771 {
772 /*
773 * Current state is compatible with enabling of CBCH reading,
774 * configure L1 to read CBCH. Otherwise configuration is delayed
775 * until ALR reaches a compatible state.
776 */
777 switch (GET_STATE (STATE_NORMAL_CBCH))
778 {
779 case CBCH_NULL:
780 /*
781 * No CBCH channel is available.
782 */
783 break;
784
785 default:
786 {
787 if (pcbch->modus EQ MMI_CBCH_STOP AND !pcbch->sat_enabled)
788 {
789 /* No CBCH to read. Stop reading CBCH in L1. */
790 cb_stop();
791 }
792 else
793 {
794
795 /*
796 * CBCH channel is available.
797 * Configure layer 1 for catching the CBCH download messages.
798 */
799 PALLOC (config_cbch, MPHC_CONFIG_CBCH_REQ);
800 memcpy (config_cbch, &pcbch->mphc_config_cbch, sizeof (T_MPHC_CONFIG_CBCH_REQ));
801 ma_cb_config_cbch(config_cbch);
802 cb_read_cbch (CBCH_NO_SCHED | CBCH_READ_NORM);
803 cb_read_cbch (CBCH_NO_SCHED | CBCH_READ_EXT);
804 SET_STATE(STATE_NORMAL_CBCH, CBCH_NO_DRX);
805 SET_STATE(STATE_EXT_CBCH, CBCH_NO_DRX);
806 }
807 }
808 break;
809 } /* End of switch (GET_STATE (STATE_NORMAL_CBCH)) */
810 }
811 }
812
813 /*
814 +--------------------------------------------------------------------+
815 | PROJECT : GSM-PS (6103) MODULE : TIL_CBCH |
816 | STATE : code ROUTINE : cb_data_ind |
817 +--------------------------------------------------------------------+
818
819 PURPOSE : A CBCH message is received.
820
821 */
822
823 GLOBAL void cb_data_ind (T_MPHC_DATA_IND *cbch_ind)
824 {
825 GET_INSTANCE_DATA;
826 UBYTE block_no;
827 UBYTE block_description;
828 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
829 UBYTE * expected_seq_number = &(pcbch->expected_seq_number[0]);
830
831 /*
832 * check whether the CBCH message has been received on the
833 * normal CBCH channel or the extended CBCH channel
834 */
835 if (cbch_ind->tc >= 4)
836 {
837 pcbch->msg_is_extended = CBCH_READ_EXT;
838 expected_seq_number = &(pcbch->expected_seq_number[1]);
839 }
840 else if(cbch_ind->tc < 4)
841 pcbch->msg_is_extended = CBCH_READ_NORM;
842
843 if (cbch_ind->error_flag EQ VALID_BLOCK)
844 {
845 /*
846 * if the CBCH block is valid, calculate the block number
847 */
848 block_description = cbch_ind->l2_frame.content[0];
849 block_no = (UBYTE)(block_description & 0x0F);
850 if (block_no < CBCH_NULL_MSG)
851 {
852 ALR_TRACE_CB_BLOCK_NO (block_description);
853 }
854 TRACE_EVENT_P2("expected_block_number = %d, schedule_length =%d", (*expected_seq_number), pcbch->schedule_length[0]);
855 switch(block_no)
856 {
857 case CBCH_BLOCK_0:
858 memcpy (&pcbch->msg[0], &cbch_ind->l2_frame.content[1], CBCH_BLOCK_SIZE);
859 #if defined(FF_HOMEZONE)
860 if (!cb_check_homezone ((UBYTE)(CBCH_BLOCK_SIZE*(block_no+1))))
861 #endif /* FF_HOMEZONE */
862 cb_first_block(block_description);
863 break;
864
865 case CBCH_BLOCK_1:
866 case CBCH_BLOCK_2:
867 case CBCH_BLOCK_3:
868 /*
869 * check for sequence number
870 */
871 if(*expected_seq_number NEQ block_no)
872 {
873 ALR_TRACE_CB("Sequence error");
874 cb_error_ind();
875 }
876 else
877 {
878 memcpy (&pcbch->msg[CBCH_BLOCK_SIZE*(block_no & 3)],
879 &cbch_ind->l2_frame.content[1], CBCH_BLOCK_SIZE);
880
881 (*expected_seq_number)++;
882 if( *expected_seq_number > CBCH_BLOCK_3 )
883 *expected_seq_number = CBCH_BLOCK_0;
884
885
886 if ( (block_description & CBCH_LAST_BLOCK) OR (block_no EQ CBCH_BLOCK_3) )
887 {
888 /*
889 * last block of msg
890 */
891 if(pcbch->msg_type EQ CBCH_NORM_MSG)
892 /*
893 * +1, because parameter is length not offset
894 */
895 cb_cbch_message((UBYTE)(CBCH_BLOCK_SIZE*(block_no+1)));
896 else if(pcbch->msg_type EQ CBCH_SCHEDULE_MSG)
897 cb_schedule_message();
898 else if(pcbch->msg_type EQ CBCH_SAT_MSG)
899 cb_sat_cbch_message((UBYTE)(CBCH_BLOCK_SIZE*(block_no+1)));
900 }
901 }
902 break;
903
904 case CBCH_FIRST_SCHED_MSG:
905 /*
906 * first SCHEDULE block
907 */
908
909 ALR_TRACE_CB ("SCHEDULE");
910 memcpy (&pcbch->msg[0], &cbch_ind->l2_frame.content[1], CBCH_BLOCK_SIZE);
911 cb_read_next_3_blocks();
912
913 pcbch->msg_type = CBCH_SCHEDULE_MSG;
914 break;
915
916 case CBCH_NULL_MSG:
917 /*
918 * NULL Message
919 */
920
921 /*
922 ALR_TRACE_CB ("null msg");
923 */
924 cb_null_message ();
925 break;
926
927 default:
928 ALR_TRACE_CB ("unknown");
929 cb_error_ind();
930 break;
931 }
932
933 ALR_EM_RECEIVE_CBCH_MESSAGE;
934
935 }
936 else
937 {
938 /*
939 * Invalid block
940 */
941 /*
942 ALR_TRACE_CB_ERROR(cbch_ind->error_flag);
943 */
944
945 pcbch->msg_type = CBCH_NO_MSG;
946 cb_error_ind ();
947 }
948 }
949
950 /*
951 +--------------------------------------------------------------------+
952 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
953 | STATE : code ROUTINE : cb_first_block |
954 +--------------------------------------------------------------------+
955
956 PURPOSE : Reception of the first CBCH block.
957
958 */
959
960 LOCAL void cb_first_block (UBYTE status)
961 {
962 GET_INSTANCE_DATA;
963 UBYTE result;
964 T_CBMSG_HEADER *p_cbh;
965 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
966
967 /*
968 * extract message id and data coding scheme from the message
969 */
970 p_cbh = (T_CBMSG_HEADER*)(&pcbch->msg[0]);
971
972 ALR_TRACE_CB_MSGHEAD (p_cbh);
973
974 /*
975 * check the incoming message:
976 * 1. matches the message identifier
977 * 2. matches the data coding scheme
978 * 3. is this message not received yet
979 */
980 result = cb_check_message_id (CB_MESSAGE_ID(p_cbh));
981 result += cb_check_data_coding_scheme (CB_DCS(p_cbh));
982 result += cb_check_old_msg ();
983
984 if (result EQ 3)
985 {
986 /*
987 * all checks are passed
988 */
989 if (! pcbch->sat_enabled OR
990 ! cb_sat_check_message_id(CB_MESSAGE_ID(p_cbh)))
991 {
992 /*
993 * it is not a CBCH download message or
994 * CBCH download is not enabled
995 */
996 if (status & CBCH_LAST_BLOCK)
997 {
998 /*
999 * the first is the only block, then forward it
1000 * to MMI.
1001 */
1002 cb_cbch_message (CBCH_BLOCK_SIZE*(CBCH_BLOCK_0+1));
1003 }
1004 else
1005 {
1006 /*
1007 * store the block and request the three remaining
1008 * blocks in layer 1.
1009 */
1010 pcbch->msg_type = CBCH_NORM_MSG;
1011 cb_read_next_3_blocks();
1012 }
1013 }
1014 else
1015 {
1016 /*
1017 * It is a CBCH download message and CBCH download is enabled.
1018 */
1019 if (status & CBCH_LAST_BLOCK)
1020 {
1021 /*
1022 * the first block is the only block, so forward the
1023 * message to MMI.
1024 */
1025 cb_sat_cbch_message (CBCH_BLOCK_SIZE*(CBCH_BLOCK_0+1));
1026 }
1027 else
1028 {
1029 /*
1030 * store the data and request the three remaining blocks.
1031 */
1032 pcbch->msg_type = CBCH_SAT_MSG;
1033 cb_read_next_3_blocks();
1034 }
1035 }
1036 }
1037 else
1038 {
1039 /*
1040 * the message has not passed the checks.
1041 * So it can be only a CBCH download message.
1042 */
1043 if(! pcbch->sat_enabled OR
1044 ! cb_sat_check_message_id(CB_MESSAGE_ID(p_cbh)))
1045 {
1046 /*
1047 * SAT is not enabled or it is not a CBCH download
1048 * message. So start reading of next scheduled message.
1049 */
1050 memset (&pcbch->msg[0], 0, 88);
1051 cb_next_scheduled_msg();
1052
1053 }
1054 else
1055 {
1056 /*
1057 * it is CBCH download message and SAT is enabled
1058 */
1059 if (status & CBCH_LAST_BLOCK)
1060 {
1061 /*
1062 * the first block is the last one, so send the
1063 * message to MMI.
1064 */
1065 cb_sat_cbch_message (CBCH_BLOCK_SIZE*(CBCH_BLOCK_0+1));
1066 }
1067 else
1068 {
1069 /*
1070 * store the first block and request the remaining three.
1071 */
1072 pcbch->msg_type = CBCH_SAT_MSG;
1073 cb_read_next_3_blocks();
1074 }
1075 }
1076 }
1077 }
1078
1079
1080 /*
1081 +--------------------------------------------------------------------+
1082 | PROJECT : GSM-PS (6103) MODULE : TIL_CBCH |
1083 | STATE : code ROUTINE : cb_sat_cbch_message |
1084 +--------------------------------------------------------------------+
1085
1086 PURPOSE : Reception of a complete CBCH message for CBCH download.
1087
1088 */
1089
1090 LOCAL void cb_sat_cbch_message (UBYTE length)
1091 {
1092 GET_INSTANCE_DATA;
1093 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1094 PALLOC (mmi_cbch_ind, MMI_SAT_CBCH_DWNLD_IND);
1095
1096 ALR_EM_CBCH_MESSAGE_COMPLETE;
1097
1098 TRACE_FUNCTION ("cb_sat_cbch_message()");
1099
1100 /*
1101 * copy the content of the message into the primitive.
1102 */
1103 memcpy (mmi_cbch_ind->cbch_msg, pcbch->msg, 88);
1104 mmi_cbch_ind->cbch_len = length;
1105
1106 /*
1107 * send to MMI
1108 */
1109 PSENDX(MMI, mmi_cbch_ind);
1110
1111 /*
1112 * prepare for next reception
1113 */
1114 pcbch->msg_type = CBCH_NO_MSG;
1115 pcbch->expected_seq_number[0] = CBCH_BLOCK_0;
1116 pcbch->expected_seq_number[1] = CBCH_BLOCK_0;
1117 /*
1118 * start reading of next scheduled message.
1119 */
1120 cb_next_scheduled_msg();
1121 }
1122
1123 /*
1124 +--------------------------------------------------------------------+
1125 | PROJECT : GSM-PS (6103) MODULE : TIL_CBCH |
1126 | STATE : code ROUTINE : cb_schedule_message |
1127 +--------------------------------------------------------------------+
1128
1129 PURPOSE : Reception of a SCHEDULE message.
1130
1131 */
1132
1133 LOCAL void cb_schedule_message (void)
1134 {
1135 GET_INSTANCE_DATA;
1136 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1137 UBYTE extended = pcbch->msg_is_extended;
1138 UBYTE *p_sched_msg = &pcbch->scheduled_sched_msg[extended];
1139
1140 ALR_EM_RECEIVE_SCHEDULE_MESSAGE;
1141
1142 switch ( get_cbch_state(extended) )
1143 {
1144 case CBCH_NO_DRX:
1145 /*
1146 * change from NO DRX mode (no knowledge about Scheduling)
1147 * to DRX mode.
1148 */
1149
1150 set_cbch_state (extended, CBCH_DRX);
1151
1152
1153 /*
1154 * check whether it is a scheduled schedule message or not.
1155 */
1156 if(pcbch->msg[0] EQ 1)
1157 *p_sched_msg = 1;
1158 else
1159 *p_sched_msg = 0;
1160
1161 /*
1162 * create schedule map with new and old messages
1163 */
1164 cb_create_schedule_map (TRUE);
1165
1166 /*
1167 * forward the schedule map to layer 1.
1168 */
1169 cb_read_cbch((UBYTE)(CBCH_SCHED | extended));
1170
1171 break;
1172
1173 case CBCH_DRX:
1174 if (pcbch->msg[0] EQ 1)
1175 {
1176 /*
1177 * scheduled SCHEDULE message
1178 */
1179 if(*p_sched_msg <= 2)
1180 (*p_sched_msg)++;
1181
1182 if (*p_sched_msg > 1)
1183 /*
1184 * we have read a full schedule period
1185 * so we dont need to read the old messages
1186 */
1187 cb_create_schedule_map (FALSE);
1188 else
1189 cb_create_schedule_map (TRUE);
1190
1191 cb_read_cbch((UBYTE)(CBCH_SCHED | extended));
1192 }
1193 break;
1194 default:
1195 break;
1196 }
1197 /*
1198 * prepare for next reception
1199 */
1200 pcbch->msg_type = CBCH_NO_MSG;
1201 pcbch->expected_seq_number[0] = CBCH_BLOCK_0;
1202 pcbch->expected_seq_number[1] = CBCH_BLOCK_0;
1203 }
1204
1205 /*
1206 +--------------------------------------------------------------------+
1207 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1208 | STATE : code ROUTINE : cb_null_message |
1209 +--------------------------------------------------------------------+
1210
1211 PURPOSE : Reception of a NULL message.
1212
1213 */
1214 LOCAL void cb_null_message (void)
1215 {
1216 GET_INSTANCE_DATA;
1217 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1218 UBYTE extended = pcbch->msg_is_extended;
1219
1220 ALR_EM_RECEIVE_NULL_MESSAGE;
1221
1222 switch ( get_cbch_state(extended) )
1223 {
1224 case CBCH_DRX:
1225 if (pcbch->schedule_length[extended] EQ 0)
1226 {
1227 /*
1228 * instead of the scheduled SCHEDULE message
1229 * a NULL message has received.
1230 * Restarting with NO DRX mode
1231 */
1232 set_cbch_state (extended, CBCH_NO_DRX);
1233 cb_read_cbch ((UBYTE)(CBCH_NO_SCHED | extended));
1234 }
1235 else
1236 {
1237 cb_next_scheduled_msg();
1238 }
1239 break;
1240 }
1241 }
1242
1243 /*
1244 +--------------------------------------------------------------------+
1245 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1246 | STATE : code ROUTINE : cb_error_ind |
1247 +--------------------------------------------------------------------+
1248
1249 PURPOSE : Indicates an invalid block.
1250 1) with error_flag =TRUE
1251 2) invalid sequence number
1252 3) out of sequence block
1253 */
1254
1255 LOCAL void cb_error_ind (void)
1256 {
1257 GET_INSTANCE_DATA;
1258 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1259 UBYTE extended = pcbch->msg_is_extended;
1260
1261 if( pcbch->expected_seq_number[extended] NEQ CBCH_BLOCK_0)
1262 {
1263 /*
1264 * stop the next blocks
1265 */
1266 cb_stop_next_blocks();
1267 }
1268 switch ( get_cbch_state(extended) )
1269 {
1270 case CBCH_DRX:
1271 if (pcbch->schedule_length[extended] EQ 0)
1272 {
1273 /*
1274 * instead of the scheduled SCHEDULE message
1275 * an invalid message has been received.
1276 * Restarting with NO DRX mode
1277 */
1278 set_cbch_state (extended, CBCH_NO_DRX);
1279 cb_read_cbch ((UBYTE)(CBCH_NO_SCHED | extended));
1280 }
1281 else
1282 /*
1283 * Go back to FIRST DRX mode.
1284 */
1285 {
1286 pcbch->scheduled_sched_msg[extended] = 1;
1287 cb_next_scheduled_msg();
1288 }
1289 break;
1290 default:
1291 break;
1292 }
1293 }
1294
1295 /*
1296 +--------------------------------------------------------------------+
1297 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1298 | STATE : code ROUTINE : cb_ind |
1299 +--------------------------------------------------------------------+
1300
1301 PURPOSE : Indication of the CBCH message.
1302
1303 */
1304
1305 LOCAL void cb_ind (UBYTE length)
1306 {
1307 GET_INSTANCE_DATA;
1308 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1309 PALLOC (mmi_cbch_ind, MMI_CBCH_IND);
1310
1311 ALR_EM_CBCH_MESSAGE_COMPLETE;
1312
1313 /*
1314 * copy the message content to the primitive.
1315 */
1316 memcpy (mmi_cbch_ind->cbch_msg, pcbch->msg, CBCH_MSG_SIZE);
1317 mmi_cbch_ind->cbch_len = length;
1318
1319 ma_cb_mmi_cbch_ind(mmi_cbch_ind);
1320
1321 {
1322 T_CBMSG_HEADER *p_cbh = (T_CBMSG_HEADER*)(&pcbch->msg[0]);
1323 ALR_TRACE_CB_MSGHEAD (p_cbh);
1324 }
1325 }
1326
1327 /*
1328 +--------------------------------------------------------------------+
1329 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1330 | STATE : code ROUTINE : cb_read_next_3_blocks |
1331 +--------------------------------------------------------------------+
1332
1333 PURPOSE : Starts read of next 3 blocks.
1334
1335 */
1336
1337 LOCAL void cb_read_next_3_blocks(void)
1338 {
1339 GET_INSTANCE_DATA;
1340 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1341 UBYTE extended = pcbch->msg_is_extended;
1342
1343 if( extended EQ CBCH_READ_EXT)
1344 ma_cb_info_req (CBCH_EXT_BLOCK234);
1345 else
1346 ma_cb_info_req (CBCH_NORM_BLOCK234);
1347
1348 pcbch->expected_seq_number[extended] = CBCH_BLOCK_1;
1349 }
1350
1351 /*
1352 +--------------------------------------------------------------------+
1353 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1354 | STATE : code ROUTINE : cb_stop_next_blocks |
1355 +--------------------------------------------------------------------+
1356
1357 PURPOSE : Stop next blocks.
1358
1359 */
1360
1361 LOCAL void cb_stop_next_blocks (void)
1362 {
1363 GET_INSTANCE_DATA;
1364 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1365 /*
1366 * stop the next blocks
1367 */
1368
1369 /*
1370 * Upper layers / L1 Circuit Switched interfaces
1371 * S922.doc , Ver 1.9
1372 * Section 11.3 MPHC_CBCH_INFO_REQ
1373 *
1374 * This message can be used to update on fly L1
1375 * with new tb_bitmap which then replaces the current one.
1376 * In such a case, 0 in the bitmap means abort any pending reading of TB1/2/3 or TB5/6/7.
1377 *
1378 * A previous "schedule_length=0" is used to specify "No schedule present".
1379 * In such a case, L1 starts reading continuously TB0 for normal CBCH or TB4 for Extended CBCH.
1380 */
1381 ma_cb_info_req (0);
1382
1383 pcbch->msg_type = CBCH_NO_MSG;
1384 pcbch->expected_seq_number[0] = CBCH_BLOCK_0;
1385 pcbch->expected_seq_number[1] = CBCH_BLOCK_0;
1386 }
1387
1388 #if defined(FF_HOMEZONE) && defined(INDICATE_HZ_ERROR)
1389
1390 /*
1391 +--------------------------------------------------------------------+
1392 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1393 | STATE : code ROUTINE : cb_ind_hz_err |
1394 +--------------------------------------------------------------------+
1395
1396 PURPOSE : Indication of the CBCH message and stop the next blocks.
1397
1398 */
1399
1400 LOCAL void cb_ind_hz_err (void)
1401 {
1402 GET_INSTANCE_DATA;
1403 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1404 PALLOC (mmi_cbch_ind, MMI_CBCH_IND);
1405
1406 memset (mmi_cbch_ind->cbch_msg, 0xff, CBCH_MSG_SIZE);
1407 mmi_cbch_ind->cbch_msg[2] = pcbch->msg_hz_id >> 8;
1408 mmi_cbch_ind->cbch_msg[3] = pcbch->msg_hz_id & 0xff;
1409 mmi_cbch_ind->cbch_len = 0; /* error indication */
1410 ALR_TRACE_CB ("cb_ind_hz_err()");
1411
1412 ma_cb_mmi_cbch_ind(mmi_cbch_ind);
1413 }
1414 #endif /* FF_HOMEZONE */
1415
1416 /*
1417 +--------------------------------------------------------------------+
1418 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1419 | STATE : code ROUTINE : cb_cbch_message |
1420 +--------------------------------------------------------------------+
1421
1422 PURPOSE : Reception of a complete CBCH message.
1423
1424 */
1425
1426 LOCAL void cb_cbch_message (UBYTE length)
1427 {
1428 /*
1429 * Indicate the message
1430 */
1431 cb_ind (length);
1432 /*
1433 * stop the next blocks
1434 */
1435 cb_stop_next_blocks ();
1436 /*
1437 * store the cbch message to avoid double reception
1438 */
1439 cb_store_cbch_msg ();
1440 /*
1441 * start reading of the next scheduled message
1442 */
1443 cb_next_scheduled_msg();
1444 }
1445
1446 /*
1447 +--------------------------------------------------------------------+
1448 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1449 | STATE : code ROUTINE : cb_store_cbch_msg |
1450 +--------------------------------------------------------------------+
1451
1452 PURPOSE : Store key parameter of a CBCH message to avoid
1453 forwarding of a CBCH message twice.
1454
1455 */
1456 LOCAL void cb_store_cbch_msg (void)
1457 {
1458 GET_INSTANCE_DATA;
1459 USHORT x;
1460 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1461
1462 ALR_TRACE_CB ("Store msg");
1463
1464 /*
1465 * It is not permitted to save the cbch message,
1466 * if the following pattern are in the
1467 * lacation area identification (bcch:sys_info_3) :
1468 * [4] 0x00
1469 * [5] 0xF1
1470 * [6] 0x10
1471 *
1472 * that means FTA in testhouse
1473 */
1474 if (alr_data->ma_data.sys_info_3[4] EQ 0 AND
1475 alr_data->ma_data.sys_info_3[5] EQ 0xF1 AND
1476 alr_data->ma_data.sys_info_3[6] EQ 0x10)
1477 return;
1478
1479 /*
1480 * If storage is full, remove the first one.
1481 */
1482 if (pcbch->old_cbch_msg.cnt EQ MAX_OLD_CB)
1483 cb_remove_message (0);
1484
1485 /*
1486 * store the new one
1487 */
1488 x = pcbch->old_cbch_msg.cnt++;
1489 memcpy (&pcbch->old_cbch_msg.header[x],
1490 &pcbch->msg, sizeof (T_CBMSG_HEADER));
1491 }
1492
1493 /*
1494 +--------------------------------------------------------------------+
1495 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1496 | STATE : code ROUTINE : cb_check_message_id |
1497 +--------------------------------------------------------------------+
1498
1499 PURPOSE : Check Message Identifier of the first CBCH block.
1500
1501 */
1502
1503 LOCAL UBYTE cb_check_message_id (USHORT msg_id)
1504 {
1505 GET_INSTANCE_DATA;
1506 USHORT i;
1507 UBYTE result = TRUE;
1508 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1509
1510 /*
1511 * if no message identifier are defined for comparision
1512 * make a shortcut and return immediately.
1513 * MODUS CBCH_ACCEPT,but no msg_id defined,accept NO messages
1514 * MODUS CBCH_IGNORE,but no msg_id define, accept all messages
1515 * MODUS CBCH_STOP,but no msg_id defined, accept NO messages
1516 * MODUS CBCH_HOMEZONE,but no msg_id defined, accept NO messages/
1517 */
1518 if ( pcbch->msg_id[0] EQ NOT_PRESENT_16BIT )
1519 {
1520 if (pcbch->modus EQ CBCH_IGNORE)
1521 {
1522 return TRUE;
1523 }
1524 else
1525 {
1526 return FALSE;
1527 }
1528 }
1529
1530 /*
1531 * initialise result
1532 * if the msg_id is not found and MMI specified
1533 * a positive range(CBCH_ACCEPT) return 0
1534 */
1535 result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? FALSE : TRUE);
1536
1537 /*
1538 * message identifier are stored as a pair to express a range
1539 */
1540 for (i=0; i < MAX_IDENTS-1; i+=2)
1541 {
1542 /*
1543 * end of list reached
1544 */
1545 if (pcbch->msg_id[i] EQ NOT_PRESENT_16BIT)
1546 break;
1547
1548 /*
1549 * check whether the message identifier is inside or outside
1550 * the range. Result depends on what MMI has requested.
1551 */
1552 if ((pcbch->msg_id[i] <= msg_id) AND
1553 (pcbch->msg_id[i+1] >= msg_id))
1554 result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? TRUE : FALSE);
1555 }
1556
1557 return result;
1558 }
1559
1560
1561 /*
1562 +--------------------------------------------------------------------+
1563 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1564 | STATE : code ROUTINE : cb_sat_check_message_id |
1565 +--------------------------------------------------------------------+
1566
1567 PURPOSE : Check Message Identifier of the first CBCH block for CBCH
1568 download purposes.
1569
1570 */
1571
1572 LOCAL UBYTE cb_sat_check_message_id (USHORT msg_id)
1573 {
1574 GET_INSTANCE_DATA;
1575 USHORT i;
1576 UBYTE result;
1577 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1578 /*
1579 * initialize result
1580 */
1581 result = FALSE;
1582
1583 /*
1584 * for all stored message identifier of CBCH download
1585 */
1586 for (i = 0; i < MAX_IDENTS_SAT; i++)
1587 {
1588 /*
1589 * end of list reached
1590 */
1591 if (pcbch->msg_id_sat[i] EQ NOT_PRESENT_16BIT)
1592 break;
1593
1594 /*
1595 * if message identifier matches
1596 */
1597 if (pcbch->msg_id_sat[i] EQ msg_id)
1598 {
1599 result = TRUE;
1600 break;
1601 }
1602 }
1603
1604 return result;
1605 }
1606
1607 /*
1608 +--------------------------------------------------------------------+
1609 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1610 | STATE : code ROUTINE : cb_check_data_coding_scheme|
1611 +--------------------------------------------------------------------+
1612
1613 PURPOSE : Check Data Coding Scheme of the first CBCH block.
1614
1615 */
1616 LOCAL UBYTE cb_check_data_coding_scheme (UBYTE dcs_id)
1617 {
1618 GET_INSTANCE_DATA;
1619 USHORT i;
1620 UBYTE result = TRUE;
1621 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1622
1623 /*
1624 * if the list is empty, result is positive
1625 */
1626 if (pcbch->dcs_id [0] EQ NOT_PRESENT_8BIT)
1627 return result;
1628
1629 /*
1630 * initialise result
1631 * if the dcs_id is not found and MMI specified
1632 * a positive range(CBCH_ACCEPT) return 0
1633 */
1634 result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? 0 : 1);
1635
1636
1637 for (i=0;i<MAX_IDENTS-1;i+=2)
1638 {
1639 /*
1640 * end of list reached
1641 */
1642 if (pcbch->dcs_id[i] EQ NOT_PRESENT_8BIT)
1643 break;
1644
1645 /*
1646 * Data Coding Scheme identifier matches
1647 */
1648 if (pcbch->dcs_id[i] <= dcs_id AND
1649 pcbch->dcs_id[i+1] >= dcs_id)
1650 result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? 1 : 0);
1651 }
1652
1653 return result;
1654 }
1655
1656 /*
1657 +--------------------------------------------------------------------+
1658 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1659 | STATE : code ROUTINE : cb_check_old_msg |
1660 +--------------------------------------------------------------------+
1661
1662 PURPOSE : Check against old messages.
1663
1664 */
1665 LOCAL UBYTE cb_check_old_msg (void)
1666 {
1667 GET_INSTANCE_DATA;
1668 int i;
1669 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1670 T_CBMSG_HEADER *p_cbh = (T_CBMSG_HEADER*)&pcbch->msg[0];
1671
1672 ALR_TRACE_CB ("compare with stored msg");
1673 for (i=0; i < pcbch->old_cbch_msg.cnt; i++)
1674 {
1675 ALR_TRACE_CB_MSGHEAD (&pcbch->old_cbch_msg.header[i]);
1676
1677 if (memcmp (&pcbch->old_cbch_msg.header[i], p_cbh, 6) EQ 0)
1678 {
1679 return FALSE; /* already stored message */
1680 }
1681 else
1682 {
1683 /* if the difference is only in the update number,
1684 * then we need to delete the old version of the message (so that the different
1685 * versions do not fill up the storage) and we can even abandon the comparison;
1686 * a message that is resent with a different update number should only use
1687 * one entry in the list; otherwise it may throw out other messages that should be kept;
1688 * think of German network that sends every minute a new update; would use up 15 entries
1689 *
1690 * some change, now check if it is only the update number that has changed
1691 * (memcmp covers 4 header bytes: msg_id3, msg_id4, dcs and page
1692 * => ignore lint warning)
1693 */
1694 /*lint -e{420} (Warning -- Apparent access beyond array) */
1695 if ((CB_GS_CODE(&pcbch->old_cbch_msg.header[i]) == CB_GS_CODE(p_cbh)) AND
1696 (CB_MSG_CODE(&pcbch->old_cbch_msg.header[i]) == CB_MSG_CODE(p_cbh)) AND
1697 !memcmp (&(((T_CBMSG_HEADER*)&pcbch->old_cbch_msg.header[i])->msg_id3),
1698 &p_cbh->msg_id3, 4))
1699 { /* all these fields match, therefore the change must have been only in the update number */
1700
1701 SHORT old_update_nr, new_update_nr;
1702 old_update_nr = CB_UPDATE_NO(&pcbch->old_cbch_msg.header[i]);
1703 new_update_nr = CB_UPDATE_NO(p_cbh);
1704 /*
1705 * 3GPP 03 41
1706 * Any Update Number eight or less higher (modulo 16) than the last received Update Number
1707 * will be considered more recent, and shall be treated as a new message
1708 */
1709 if((!new_update_nr) OR
1710 ((new_update_nr - old_update_nr + MAX_UPDATE_NO) % MAX_UPDATE_NO <= MAX_UPDATE_NO_DIFF))
1711 {
1712 ALR_TRACE_CB ("change update num, delete old message");
1713 /* remove the old message so that we do not use up another entry for this new version of the message */
1714 cb_remove_message (i);
1715 /* skip out of loop because we found the match */
1716 break;
1717 }
1718 else
1719 return FALSE;
1720 }
1721 }
1722 }
1723
1724 return TRUE; /* new message */
1725 }
1726
1727 /*
1728 +--------------------------------------------------------------------+
1729 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1730 | STATE : code ROUTINE : cb_read_cbch |
1731 +--------------------------------------------------------------------+
1732
1733 PURPOSE : Starts reading of the first block of CBCH.
1734 The parameter defines if the extended or the normal CBCH
1735 should be read and if scheduling should be used.
1736
1737 */
1738
1739 LOCAL void cb_read_cbch (UBYTE flags)
1740 {
1741 GET_INSTANCE_DATA;
1742 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1743 UBYTE extended = (UBYTE)(flags & CBCH_READ_EXT);
1744 ULONG first_block = pcbch->schedule_map[extended][0];
1745 ULONG second_block = pcbch->schedule_map[extended][1];
1746
1747 PALLOC (sched_req, MPHC_CBCH_SCHEDULE_REQ);
1748
1749 ALR_TRACE_CB_START_READ(flags);
1750
1751 sched_req->cbch_select = extended;
1752
1753 ALR_EM_START_CBCH_READING;
1754
1755 if(flags & CBCH_SCHED)
1756 {
1757 UBYTE n = pcbch->begin_schedule[extended] -1;
1758
1759 sched_req->schedule_length = pcbch->end_schedule[extended] -
1760 pcbch->begin_schedule[extended] +1;
1761
1762 /*
1763 * the MPHC SAP uses first_blocks_1 as USHORT although the internal data base
1764 * of ALR uses for convinience an array of 2 ULONG for first_blocks_0 and
1765 * first_blocks_1; ergo: do a cast for first_blocks_1 here
1766 */
1767
1768 if( pcbch->begin_schedule[extended] EQ 1)
1769 {
1770 sched_req->first_blocks_0 = first_block;
1771 sched_req->first_blocks_1 = (USHORT)second_block;
1772 }
1773 else if(pcbch->begin_schedule[extended] < 32)
1774 {
1775 sched_req->first_blocks_0 = (first_block >> n) | ((second_block << (32 - n)));
1776 sched_req->first_blocks_1 = (USHORT) (second_block >> n);
1777 }
1778 else
1779 {
1780 sched_req->first_blocks_0 = (USHORT)(second_block >> (n - 32));
1781 sched_req->first_blocks_1 = 0;
1782 }
1783 }
1784 else
1785 {
1786 sched_req->schedule_length = 0;
1787 }
1788
1789 ma_cb_sched_req(sched_req);
1790 }
1791
1792 /*
1793 +--------------------------------------------------------------------+
1794 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1795 | STATE : code ROUTINE : cb_check_ci_lai_plmn |
1796 +--------------------------------------------------------------------+
1797
1798 PURPOSE : Checking the Cell Identity and the Location Area Identification
1799 to handle the geographical zone parameter.
1800 */
1801
1802 LOCAL void cb_check_ci_lai_plmn (void)
1803 {
1804 GET_INSTANCE_DATA;
1805 USHORT i;
1806 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1807 UBYTE keep = 0x00;
1808 UBYTE *si3 = &alr_data->ma_data.sys_info_3[0];
1809 UBYTE *lac = &pcbch->old_cid_plmn_lac[0];
1810 UCHAR gs_scope_change_ind = CB_GEOGR_CHANGE_NONE;
1811
1812 /*
1813 * it is not permitted to save the cbch message,
1814 * if the following pattern are in the
1815 * location area identification (bcch:sys_info_3) :
1816 * [4] 0x00
1817 * [5] 0xF1
1818 * [6] 0x10
1819 *
1820 * that means FTA in testhouse.
1821 */
1822 if ((si3[4] EQ 0x00) AND
1823 (si3[5] EQ 0xF1) AND
1824 (si3[6] EQ 0x10)
1825 )
1826 return;
1827
1828 if ((si3[4] NEQ lac[2]) OR
1829 (si3[5] NEQ lac[3]) OR
1830 (si3[6] NEQ lac[4])
1831 )
1832 {
1833 /*
1834 * The PLNM has changed
1835 */
1836 gs_scope_change_ind = CB_GEOGR_CHANGE_PLMN;
1837 pcbch->old_cbch_msg.cnt = 0; /* clear all messages */
1838 }
1839 else if ((si3[7] NEQ lac[5]) OR
1840 (si3[8] NEQ lac[6])
1841 )
1842 {
1843 /*
1844 * The location area identification has changed
1845 */
1846 keep = CB_GEOGR_SCOPE_PLMN; /* keep PLMN wide messages */
1847 gs_scope_change_ind = CB_GEOGR_CHANGE_LAC;
1848 }
1849 else if ((si3[2] NEQ lac[0]) OR
1850 (si3[3] NEQ lac[1])
1851 )
1852 {
1853 /*
1854 * The Cell Identity has changed
1855 */
1856
1857 /* indicate cell change to MMI only if we have received any CBCH broadcast messages */
1858 if (pcbch->old_cbch_msg.cnt > 0)
1859 gs_scope_change_ind = CB_GEOGR_CHANGE_CELL;
1860 keep = CB_GEOGR_SCOPE_CELLN; /* keep PLMN and Location Area wide messages */
1861 }
1862
1863
1864 /*
1865 * update old_cid_plmn_lac
1866 */
1867 memcpy (lac, &si3[2], 7);
1868
1869 }
1870
1871 /*
1872 +--------------------------------------------------------------------+
1873 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1874 | STATE : code ROUTINE : cb_remove_message |
1875 +--------------------------------------------------------------------+
1876
1877 PURPOSE : Removes the indicated CBCH message from the internal
1878 storage.
1879
1880 */
1881 LOCAL void cb_remove_message (USHORT i)
1882 {
1883 GET_INSTANCE_DATA;
1884 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1885
1886 if ((pcbch->old_cbch_msg.cnt) AND
1887 (i < pcbch->old_cbch_msg.cnt))
1888 {
1889 ALR_TRACE_CB ("remove msg");
1890 ALR_TRACE_CB_MSGHEAD (&pcbch->old_cbch_msg.header[i]);
1891
1892 /*
1893 * decrement number of stored messages.
1894 */
1895 pcbch->old_cbch_msg.cnt--;
1896 memmove (&pcbch->old_cbch_msg.header[i],
1897 &pcbch->old_cbch_msg.header[i+1],
1898 (pcbch->old_cbch_msg.cnt-i) * sizeof(T_CBMSG_HEADER));
1899 }
1900 }
1901
1902 /*
1903 +--------------------------------------------------------------------+
1904 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1905 | STATE : code ROUTINE : cb_create_schedule_map |
1906 +--------------------------------------------------------------------+
1907
1908 PURPOSE : Creation of a schedule map.
1909
1910 */
1911 LOCAL void cb_create_schedule_map (UBYTE old_cb_msg)
1912 {
1913 GET_INSTANCE_DATA;
1914 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1915 UBYTE extended = pcbch->msg_is_extended;
1916 UBYTE* msg_ptr;
1917
1918 /*
1919 * Store begin and end slot number
1920 */
1921 pcbch->begin_schedule [extended] = (UBYTE)(pcbch->msg [0] & 0x3F);
1922 pcbch->end_schedule [extended] = pcbch->msg [1];
1923
1924 /*
1925 * clear schedule bitmap
1926 */
1927 pcbch->schedule_length[extended] = 0;
1928 memset (&pcbch->schedule_map[extended][0], 0,
1929 2*sizeof (pcbch->schedule_map[extended][0]));
1930 /*
1931 * Check all new entries,
1932 * msg_ptr to first message description
1933 */
1934 msg_ptr = &pcbch->msg[8];
1935
1936 msg_ptr = cb_create_schedule_entries (msg_ptr, 1);
1937
1938 if (old_cb_msg)
1939 {
1940 cb_create_schedule_entries (msg_ptr, FALSE);
1941 }
1942 }
1943
1944 /*
1945 +--------------------------------------------------------------------+
1946 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
1947 | STATE : code ROUTINE : cb_create_schedule_entries |
1948 +--------------------------------------------------------------------+
1949
1950 PURPOSE : Creation of schedule entries.
1951
1952 */
1953 LOCAL UBYTE* cb_create_schedule_entries (UBYTE* msg_ptr, BOOL flag)
1954 {
1955 GET_INSTANCE_DATA;
1956 unsigned i;
1957 BOOL result;
1958 UBYTE x;
1959 USHORT msg_id;
1960 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
1961 UBYTE extended = pcbch->msg_is_extended;
1962
1963 pcbch->last_slot_read[extended] = 0;
1964 for (i=0; i < pcbch->end_schedule[extended]; i++)
1965 {
1966 result = (pcbch->msg [2 + ((i+1)>>3)] & (1 <<(8-((i+1)&7))));
1967
1968 ALR_TRACE_CB_SCHEDULE(i+1,result);
1969
1970 if ((flag AND result) OR (!flag AND !result))
1971 {
1972 /*
1973 * result and bit are set, that means the msg:
1974 * - was not send during the previous schedule period
1975 * - or the msg was sent unscheduled during the last period
1976 * - or is free of charge, reading advised
1977 * result and bit are both not set , that means the msg:
1978 * - the msg doesn't match the above
1979 * - these msgs are read only during the first 2 schedule periods
1980 */
1981 if (*msg_ptr & 0x80)
1982 {
1983 /*
1984 * First transmission of an SMSCB within the
1985 * Schedule Period
1986 */
1987
1988 msg_id = (UBYTE)((*msg_ptr) & 0x7F);
1989 msg_ptr++;
1990 msg_id = (USHORT)(msg_id + *msg_ptr);
1991 if (cb_check_message_id (msg_id))
1992 {
1993 /*
1994 * Message Identifier is expected
1995 * then set slot bit in schedule map
1996 */
1997 pcbch->schedule_map[extended][i>>5] |= 1 << (i&31);
1998 if( (i+1) >= pcbch->begin_schedule[extended] )
1999 {
2000 pcbch->schedule_length[extended]++;
2001 pcbch->last_slot_read[extended] = (i+1);
2002 }
2003 }
2004 }
2005 else
2006 {
2007 if ((*msg_ptr & 0xC0) EQ 0)
2008 {
2009 /*
2010 * Retransmission indication
2011 * Extract original message slot number
2012 */
2013 x = (UBYTE)(*msg_ptr & 0x3F);
2014 if (x)
2015 {
2016 x--;
2017 if (pcbch->schedule_map[extended][x>>5] & (1 << (x&31)) )
2018 {
2019 /*
2020 * original message will be read, then set also
2021 * repetition of message in schedule map
2022 */
2023 pcbch->schedule_map[extended][i>>5] |= 1 << (i&31);
2024 if( (i+1) >= pcbch->begin_schedule[extended] )
2025 {
2026 pcbch->schedule_length[extended]++;
2027 pcbch->last_slot_read[extended] = (i+1);
2028 }
2029 }
2030 }
2031 }
2032 else
2033 {
2034 if (*msg_ptr EQ 0x41)
2035 {
2036 /*
2037 * Free Message Slot, reading advised
2038 * Set bit in schedule map
2039 */
2040 pcbch->schedule_map[extended][i>>5] |= 1 << (i&31);
2041 if( (i+1) >= pcbch->begin_schedule[extended] )
2042 {
2043 pcbch->schedule_length[extended]++;
2044 pcbch->last_slot_read[extended] = (i+1);
2045 }
2046 }
2047 }
2048 }
2049 /*
2050 * increment message description pointer
2051 */
2052 msg_ptr++;
2053 }
2054 }
2055 return msg_ptr;
2056 }
2057
2058
2059 /*
2060 +--------------------------------------------------------------------+
2061 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
2062 | STATE : code ROUTINE : cb_next_scheduled_msg |
2063 +--------------------------------------------------------------------+
2064
2065 PURPOSE : Looks for end of scheduling period.
2066
2067 */
2068 LOCAL void cb_next_scheduled_msg(void)
2069 {
2070 GET_INSTANCE_DATA;
2071 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
2072 UBYTE extended = pcbch->msg_is_extended;
2073
2074 if ((get_cbch_state(extended)) EQ CBCH_DRX )
2075 {
2076 if( pcbch->schedule_length[extended] EQ 0 )
2077 {
2078 /*
2079 * instead of the scheduled SCHEDULE message
2080 * an invalid message has been received.
2081 * Restarting with NO DRX mode
2082 */
2083 set_cbch_state (extended, CBCH_NO_DRX);
2084 cb_read_cbch ((UBYTE)(CBCH_NO_SCHED | extended));
2085 return;
2086 }
2087 pcbch->schedule_length[extended]--;
2088
2089 if(pcbch->schedule_length[extended] EQ 0)
2090 {
2091 /*
2092 * clear schedule map
2093 * all message slots have been read
2094 *
2095 * NO need to reconfigure L1 to re-read schedule message
2096 * that follows slot 48
2097 */
2098 memset (&pcbch->schedule_map[extended][0], 0,
2099 2*sizeof (pcbch->schedule_map[extended][0]));
2100 TRACE_EVENT("Scheduled Schedule message expected");
2101
2102 }
2103 }
2104 }
2105
2106 /*
2107 +--------------------------------------------------------------------+
2108 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
2109 | STATE : code ROUTINE : get_cbch_state |
2110 +--------------------------------------------------------------------+
2111
2112 PURPOSE : Returns the state of STATE_EXT_CBCH or STATE_NORMAL_CBCH
2113 depending upon the input parameter "extended"
2114
2115 */
2116
2117 UBYTE get_cbch_state( UBYTE extended)
2118 {
2119 GET_INSTANCE_DATA;
2120 if( extended)
2121 return GET_STATE(STATE_EXT_CBCH);
2122 else
2123 return GET_STATE(STATE_NORMAL_CBCH);
2124 }
2125
2126 /*
2127 +--------------------------------------------------------------------+
2128 | PROJECT : GSM-PS (6103) MODULE : ALR_CBCH |
2129 | STATE : code ROUTINE : set_cbch_state |
2130 +--------------------------------------------------------------------+
2131
2132 PURPOSE : Sets the state of STATE_EXT_CBCH or STATE_NORMAL_CBCH
2133 depending upon the input parameter "extended"
2134
2135 */
2136
2137 void set_cbch_state( UBYTE extended, UBYTE new_state)
2138 {
2139 GET_INSTANCE_DATA;
2140 if(extended)
2141 {
2142 SET_STATE(STATE_EXT_CBCH,new_state);
2143 }
2144 else
2145 SET_STATE(STATE_NORMAL_CBCH,new_state);
2146 }
2147
2148
2149 #if defined(FF_HOMEZONE)
2150 GLOBAL void cb_tim_homezone (void)
2151 {
2152 GET_INSTANCE_DATA;
2153 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
2154
2155 if (pcbch->homezone EQ CBCH_HZ_IDLE)
2156 {
2157 if (GET_STATE(STATE_MA) EQ MA_IDLE)
2158 {
2159 ALR_TRACE_CB ("call cb_start()");
2160 cb_start ();
2161 }
2162 else
2163 {
2164 TIMERSTART (TIM_HOMEZONE, 1000);
2165 }
2166 }
2167 else if (pcbch->homezone EQ CBCH_HZ_PENDING)
2168 {
2169 /*
2170 * mark as received, indicate error, stop CBCH reading
2171 */
2172 ALR_TRACE_CB ("cb_ind_hz_err()");
2173 pcbch->homezone = CBCH_HZ_RECEIVED;
2174 #if defined(INDICATE_HZ_ERROR)
2175 cb_ind_hz_err ();
2176 #endif /* INDICATE_HZ_ERROR */
2177 if ( (pcbch->modus EQ NOT_PRESENT_8BIT)
2178 AND (!pcbch->sat_enabled))
2179 cb_stop ();
2180 }
2181 }
2182
2183 LOCAL UBYTE cb_check_homezone (UBYTE length)
2184 {
2185 GET_INSTANCE_DATA;
2186 UBYTE result = FALSE;/* no special handling of homezone CBCH message */
2187 T_CBCH_DATA *pcbch = &alr_data->cbch_data;
2188
2189 if (pcbch->homezone EQ CBCH_HZ_PENDING)
2190 {
2191 T_CBMSG_HEADER *p_cbh;
2192 p_cbh = (T_CBMSG_HEADER*)(&pcbch->msg[0]);
2193
2194 if ( (CB_MESSAGE_ID (p_cbh) EQ pcbch->msg_hz_id)
2195 AND (CB_DCS (p_cbh) EQ pcbch->dcs_hz_id)
2196 )
2197 {
2198 /* one-time request of homezone CBCH message after cell reselection */
2199 TIMERSTOP (TIM_HOMEZONE);
2200 pcbch->homezone = CBCH_HZ_RECEIVED;
2201 ALR_TRACE_CB_MSGHEAD (p_cbh);
2202 ALR_TRACE_CB ("homezone msg received");
2203 cb_ind (length);
2204 result = TRUE;
2205
2206 if ( (pcbch->modus EQ NOT_PRESENT_8BIT)
2207 AND (!pcbch->sat_enabled))
2208 {
2209 ALR_TRACE_CB ("no other msg req.");
2210 cb_stop ();
2211 }
2212 else
2213 cb_stop_next_blocks ();
2214 }
2215 }
2216
2217 return result;
2218 }
2219 #endif /* FF_HOMEZONE */
2220
2221 /*
2222 +--------------------------------------------------------------------+
2223 | PROJECT : MODULE : ALR_CBCH |
2224 | STATE : code ROUTINE : cb_alr_trace_msghead |
2225 +--------------------------------------------------------------------+
2226
2227 PURPOSE : Function to replace the ALR_TRACE_CB_MSGHEAD macro.
2228
2229 */
2230
2231 /* Implements measures 2,3,4 */
2232 LOCAL void cb_alr_trace_msghead (T_CBMSG_HEADER *ph)
2233 {
2234 ALR_TRACE_CB ("cb_alr_trace_msghead()");
2235 if (CB_MSG_CODE(ph) < 1000)
2236 {
2237 TRACE_EVENT_P7("CBCH ID=%3u, gs=%u, msg=%4u, upd=%u, dcs=%02x, p=%u/%u",
2238 CB_MESSAGE_ID(ph), CB_GS_CODE(ph),
2239 CB_MSG_CODE(ph), CB_UPDATE_NO(ph),
2240 CB_DCS(ph), CB_PAGE(ph), CB_PAGETOTAL(ph));
2241 }
2242 else
2243 {
2244 TRACE_EVENT_P7("CBCH ID=%3u, gs=%u, msg=%04x, upd=%u, dcs=%02x, p=%u/%u",
2245 CB_MESSAGE_ID(ph), CB_GS_CODE(ph),
2246 CB_MSG_CODE(ph), CB_UPDATE_NO(ph),
2247 CB_DCS(ph), CB_PAGE(ph), CB_PAGETOTAL(ph));
2248 }
2249 }
2250 #endif