comparison g23m-gsm/alr/alr_cbch.c @ 0:75a11d740a02

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