comparison src/aci2/alr/alr_cbch.c @ 3:93999a60b835

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