diff src/g23m-gsm/alr3/alr_cbch.c @ 2:3a14ee9a9843

src/g23m-gsm: same alr2 & alr3 structure as in Selenite
author Mychaela Falconia <falcon@freecalypso.org>
date Fri, 16 Oct 2020 06:29:12 +0000
parents src/g23m-gsm/alr/alr_cbch.c@fa8dc04885d8
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/g23m-gsm/alr3/alr_cbch.c	Fri Oct 16 06:29:12 2020 +0000
@@ -0,0 +1,2250 @@
+/*
++-----------------------------------------------------------------------------
+|  Project :  GSM-PS
+|  Modul   :  ALR_CBCH
++-----------------------------------------------------------------------------
+|  Copyright 2002 Texas Instruments Berlin, AG
+|                 All rights reserved.
+|
+|                 This file is confidential and a trade secret of Texas
+|                 Instruments Berlin, AG
+|                 The receipt of or possession of this file does not convey
+|                 any rights to reproduce or disclose its contents or to
+|                 manufacture, use, or sell anything it may describe, in
+|                 whole, or in part, without the specific written consent of
+|                 Texas Instruments Berlin, AG.
++-----------------------------------------------------------------------------
+|  Purpose :  This Modul defines the SDL process CBCH_control.
++-----------------------------------------------------------------------------
+*/
+
+#ifndef ALR_CBCH_C
+#define ALR_CBCH_C
+
+#define ENTITY_PL
+
+/*==== INCLUDES ===================================================*/
+#include <string.h>
+#include <stdlib.h>
+#include <ctype.h>
+#include "typedefs.h"
+#include "pconst.cdg"
+#include "mconst.cdg"
+#include "message.h"
+#include "ccdapi.h"
+#include "vsi.h"
+#include "custom.h"
+#include "gsm.h"
+#include "prim.h"
+#include "cnf_alr.h"
+#include "mon_alr.h"
+#include "pei.h"
+#include "tok.h"
+
+#include "pcm.h"
+#ifdef GPRS
+#include "alr_gprs.h"
+#endif
+#include "alr.h"
+#include "alr_em.h"
+
+/*==== EXPORT =====================================================*/
+/*==== PRIVAT =====================================================*/
+LOCAL void   cb_read_cbch               (UBYTE  flags);
+LOCAL void   cb_check_ci_lai_plmn       (void);
+LOCAL void   cb_remove_message          (USHORT i);
+LOCAL void   cb_first_block             (UBYTE  status);
+LOCAL UBYTE* cb_create_schedule_entries (UBYTE* msg_ptr, BOOL read_old_msg);
+LOCAL void   cb_create_schedule_map     (UBYTE  old_cb_msg);
+LOCAL UBYTE  cb_check_old_msg           (void);
+LOCAL UBYTE  cb_check_data_coding_scheme(UBYTE  dcs_id);
+LOCAL UBYTE  cb_check_message_id        (USHORT msg_id);
+LOCAL void   cb_store_cbch_msg          (void);
+LOCAL void   cb_error_ind               (void);
+LOCAL void   cb_cbch_message            (UBYTE  length);
+LOCAL void   cb_null_message            (void);
+LOCAL void   cb_schedule_message        (void);
+LOCAL void   cb_next_scheduled_msg      (void);
+LOCAL UBYTE  cb_sat_check_message_id    (USHORT msg_id);
+LOCAL void   cb_sat_cbch_message        (UBYTE length);
+LOCAL void cb_stop_next_blocks (void);
+LOCAL void cb_read_next_3_blocks(void);
+void set_cbch_state( UBYTE extended, UBYTE new_state);
+UBYTE get_cbch_state( UBYTE extended);
+
+#if defined(FF_HOMEZONE)
+LOCAL UBYTE cb_check_homezone (UBYTE length);
+#endif  /* FF_HOMEZONE */
+
+LOCAL void cb_alr_trace_msghead (T_CBMSG_HEADER *ph);
+
+/*
+ * support indication of geographical scope change to MMI
+ * it is important that these defitions match the GS definition from GSM 03.41
+ * the MMI uses this also to compare with real CBCH messages!
+ */
+#define CB_GEOGR_CHANGE_NONE 0x00
+#define CB_GEOGR_CHANGE_CELL 0xC0
+#define CB_GEOGR_CHANGE_LAC  0x80
+#define CB_GEOGR_CHANGE_PLMN 0x40
+
+#define CB_GEOGR_SCOPE_CELLI 0x00
+#define CB_GEOGR_SCOPE_PLMN  0x01
+#define CB_GEOGR_SCOPE_LAC   0x02
+#define CB_GEOGR_SCOPE_CELLN 0x03
+
+#define CBCH_NO_MSG           0
+#define CBCH_NORM_MSG         1
+#define CBCH_SCHEDULE_MSG     2
+#define CBCH_SAT_MSG          3
+#define CBCH_LAST_BLOCK    0x10
+
+#define CBCH_BLOCK_0          0
+#define CBCH_BLOCK_1          1
+#define CBCH_BLOCK_2          2
+#define CBCH_BLOCK_3          3
+#define CBCH_FIRST_SCHED_MSG  8
+#define CBCH_NULL_MSG      0x0F
+#define CBCH_SCHED            2
+
+#define MAX_UPDATE_NO   16
+#define MAX_UPDATE_NO_DIFF    8
+
+#if 1 || defined (WIN32)
+#define TRACING
+#endif
+
+#define CB_SERIAL_NO(ph)            ((USHORT)\
+                                    ((((T_CBMSG_HEADER*)(ph))->serial_no1)<<8)+\
+                                    (((T_CBMSG_HEADER*)(ph))->serial_no2))
+
+#define CB_GS_CODE(ph)              (((UBYTE)(((T_CBMSG_HEADER*)(ph))->serial_no1))>>6)
+
+#define CB_MSG_CODE(ph)             ((USHORT)\
+                                    (((((T_CBMSG_HEADER*)(ph))->serial_no1)&0x3f)<<4)+\
+                                    ((((T_CBMSG_HEADER*)(ph))->serial_no2)>>4))
+
+#define CB_UPDATE_NO(ph)            ((((T_CBMSG_HEADER*)(ph))->serial_no2)&0x0f)
+
+#define CB_MESSAGE_ID(ph)           ((USHORT)\
+                                    ((((T_CBMSG_HEADER*)(ph))->msg_id3)<<8)+\
+                                    (((T_CBMSG_HEADER*)(ph))->msg_id4))
+#if 0
+#define CB_MESSAGE_ID(ph)           ((((USHORT)(((T_CBMSG_HEADER*)(ph))->msg_id3))<<8)+\
+                                      ((USHORT)(((T_CBMSG_HEADER*)(ph))->msg_id4)))
+
+#endif /* 0 */
+#define CB_DCS(ph)                  (((T_CBMSG_HEADER*)(ph))->dcs)
+
+#define CB_PAGE(ph)                 (((T_CBMSG_HEADER*)(ph))->page>>4)
+#define CB_PAGETOTAL(ph)            (((T_CBMSG_HEADER*)(ph))->page&0x0f)
+
+
+#if defined (TRACING)
+#define ALR_TRACE_CB(a)             TRACE_EVENT("CBCH: " a)
+#define ALR_TRACE_CB_MODUS(m)       TRACE_EVENT_P1("CBCH: modus=%d", m)
+#define ALR_TRACE_CB_ERROR(e)       TRACE_EVENT_P1("CBCH: error=%d", e)
+#define ALR_TRACE_CB_BLOCK_NO(b)    TRACE_EVENT_P2("CBCH: block=%02x no=%u", b, b&0x0f)
+#define ALR_TRACE_CB_MSGHEAD(ph)    cb_alr_trace_msghead(ph)
+
+#define ALR_TRACE_CB_MSGID(m)         TRACE_EVENT_P1("CBCH: ID=%u", m)
+#define ALR_TRACE_CB_START_READ(f)    TRACE_EVENT_P1("CBCH: Start Read %d", f)
+#define ALR_TRACE_CB_SCHEDULE(a1,a2)  TRACE_EVENT_P2("CBCH: schedule i=%d result=%d", a1,a2)
+#define ALR_TRACE_CB_HZREQ(a1,a2)     TRACE_EVENT_P2("CBCH: Homezone ID=%u, t=%u", a1,a2)
+#define ALR_TRACE_CB_SCOPE_CHANGE(i,s)  TRACE_EVENT_P2 ("CBCH: Geogr. scope change %u, deleting msg of scope %u",\
+                                          i,s);
+#else  /* TRACING */
+#define ALR_TRACE_CB(a)
+#define ALR_TRACE_CB_MODUS(m)
+#define ALR_TRACE_CB_ERROR(e)
+#define ALR_TRACE_CB_BLOCK_NO(b)
+#define ALR_TRACE_CB_MSGID(m)
+#define ALR_TRACE_CB_START_READ(f)
+#define ALR_TRACE_CB_SCHEDULE(a1,a2)
+#define ALR_TRACE_CB_HZREQ(a1,a2)
+#endif  /* TRACING */
+
+/*==== VARIABLES ==================================================*/
+/*==== FUNCTIONS ==================================================*/
+
+#if 0
+#if 0
+#define TRACE_ALIGN_P(ps,m,t)  TRACE_EVENT_P5(" %08x %3u.%u %08x=%u " \
+                                "T_" #t " " #m, \
+                                (BYTE*)&(m), (BYTE*)&(m)-(BYTE*)ps, \
+                                sizeof (m),
+                                sizeof (m) > 1 ? (USHORT)(m) : (UBYTE)(m), m \
+                              )
+#else
+#define TRACE_ALIGN_P(ps,m,t)  TRACE_EVENT_P4 (" %08x %3u.%u %08x " \
+                                "T_" #t " " #m, \
+                                (BYTE*)&(m), (BYTE*)&(m)-(BYTE*)ps, \
+                                sizeof (m), m\
+                                )
+#endif
+int test_alignment (T_CBMSG_HEADER *ph)
+{
+  TRACE_ALIGN_P (ph, ph->serial_no1, CBMSG_HEADER);
+  TRACE_ALIGN_P (ph, ph->serial_no2, CBMSG_HEADER);
+  TRACE_ALIGN_P (ph, ph->msg_id3, CBMSG_HEADER);
+  TRACE_ALIGN_P (ph, ph->msg_id4, CBMSG_HEADER);
+  TRACE_ALIGN_P (ph, ph->dcs, CBMSG_HEADER);
+  TRACE_ALIGN_P (ph, ph->page, CBMSG_HEADER);
+}
+#endif
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_init                    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Initialize CBCH Control Process.
+*/
+
+GLOBAL void cb_init (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  ALR_TRACE_CB ("cb_init()");
+  alr_data->state[STATE_NORMAL_CBCH] = CBCH_NULL;
+  alr_data->state[STATE_EXT_CBCH] = CBCH_NULL;
+  pcbch->modus   = NOT_PRESENT_8BIT;
+  pcbch->old_cbch_msg.cnt = 0;
+#if defined(FF_HOMEZONE)
+  pcbch->homezone = CBCH_HZ_OFF;
+  pcbch->hz_timeout = 0;
+#endif  /* FF_HOMEZONE */
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_stop                    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Stop CBCH Control Process.
+
+            cb_stop will be called in the following three scenarios - 
+            1. Moving from IDLE to DEDICATED state 
+            2. ALR has received HomeZone information. 
+            3. MMI indicates stop reading CBCH. 
+
+            In all three cases ALR need to forward this to L1.
+            Eventhough the homezone request is pending we need to stop 
+            the CBCH reading.
+*/
+
+GLOBAL void cb_stop (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE normal_cbch, extended_cbch;
+
+  normal_cbch = GET_STATE(STATE_NORMAL_CBCH);
+  extended_cbch = GET_STATE(STATE_EXT_CBCH);
+
+  if ( 
+        (normal_cbch NEQ CBCH_NULL AND normal_cbch NEQ CBCH_IDLE) 
+        OR
+        (extended_cbch NEQ CBCH_NULL AND extended_cbch NEQ CBCH_IDLE) 
+     )
+  {
+    /*
+     * if CBCH process is really active, initialize
+     * CBCH process and stop CBCH process in layer 1.
+     */
+    pcbch->msg_type = CBCH_NO_MSG;
+
+    SET_STATE(STATE_NORMAL_CBCH, CBCH_IDLE);
+    SET_STATE(STATE_EXT_CBCH, CBCH_IDLE);
+
+    ALR_EM_STOP_CBCH_READING;
+
+    ma_cb_stop_cbch_req();
+  }
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_start                   |
++--------------------------------------------------------------------+
+
+  PURPOSE : Re-configure layer 1 and go back to CBCH reading without
+            scheduling information.
+*/
+
+LOCAL void cb_start_no_drx_reading (UBYTE config)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  if (config)
+  {
+    /*
+     * configure layer 1
+     */
+    PALLOC (config_cbch, MPHC_CONFIG_CBCH_REQ);
+
+    /*
+     * copy the stored configuration received earlier from RR and send to layer 1.
+     */
+    memcpy (config_cbch, &pcbch->mphc_config_cbch, sizeof (T_MPHC_CONFIG_CBCH_REQ));
+    ma_cb_config_cbch(config_cbch);
+  }
+
+  /*
+   * start reading in layer 1 for normal and extended CBCH.
+   * The initial mode is no Scheduling information available.
+   */
+  cb_read_cbch (CBCH_NO_SCHED | CBCH_READ_NORM);
+  cb_read_cbch (CBCH_NO_SCHED  | CBCH_READ_EXT);
+
+  SET_STATE(STATE_NORMAL_CBCH, CBCH_NO_DRX);
+  SET_STATE(STATE_EXT_CBCH, CBCH_NO_DRX);
+  
+#if defined(FF_HOMEZONE)
+  if (pcbch->homezone EQ CBCH_HZ_IDLE)
+  {
+    pcbch->homezone = CBCH_HZ_PENDING;
+    /* start timer new */
+    if (pcbch->hz_timeout)
+      TIMERSTART(TIM_HOMEZONE, pcbch->hz_timeout);
+    ALR_TRACE_CB ("HOMEZONE is pending");
+  }
+#endif /* FF_HOMEZONE */
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_start                   |
++--------------------------------------------------------------------+
+
+  PURPOSE : Start CBCH Control Process.
+*/
+
+GLOBAL void cb_start (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  if (    (GET_STATE(STATE_NORMAL_CBCH) EQ CBCH_IDLE)
+      AND (     (pcbch->modus NEQ NOT_PRESENT_8BIT)
+            OR  (pcbch->sat_enabled)
+#if defined(FF_HOMEZONE)
+            OR  (pcbch->homezone EQ CBCH_HZ_IDLE)
+#endif /* FF_HOMEZONE */
+          )
+      )
+  {
+    /*
+     * if a definition of needed message identifiers
+     * and data coding schemes is available, then configure
+     * layer 1
+     */
+    ALR_TRACE_CB ("restart");
+    cb_start_no_drx_reading (TRUE);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : TIL_CBCH                   |
+| STATE   : code                ROUTINE : cb_mph_cbch_req            |
++--------------------------------------------------------------------+
+
+  PURPOSE : Configuration of the layer 1 process for CBCH.
+
+            The compile-switch is not defined with the standard TI-layer 1.
+
+            But there shall be a little modification possible (and it is
+            done by some source code customer of layer 1), which does not
+            need any storing in ALR. Then the compile switch must be set
+
+  REMARK  : Setting of compile switch has problems with function cbch_start ???
+
+*/
+
+GLOBAL void cb_mph_cbch_req  (T_cbch * cbch)
+{
+  GET_INSTANCE_DATA;
+  USHORT i;
+  T_CBCH_DATA      *pcbch = &alr_data->cbch_data;
+  T_cbch_desc      *pcbch_desc = &pcbch->mphc_config_cbch.cbch_desc;
+  T_chan_sel       *pchan_sel = &pcbch_desc->chan_sel;
+  T_cbch_freq_list *pcbch_freq_list = &pcbch->mphc_config_cbch.cbch_freq_list;
+
+  ALR_TRACE_CB ("MPH_CBCH_REQ");
+
+  ALR_EM_CONFIGURE_CBCH_CHANNEL;
+
+#if defined(FF_HOMEZONE)
+  if (pcbch->homezone NEQ CBCH_HZ_OFF)
+    pcbch->homezone = CBCH_HZ_IDLE; /* starts HZ request again */
+#endif /* FF_HOMEZONE */
+
+  /*   check which messages have to be deleted
+   *   even if the new cell has CBCH disabled! We still need to
+   *   to delete the corresponding messages and inform the MMI!
+   */
+  if (pcbch->modus EQ CBCH_ACCEPT)
+    cb_check_ci_lai_plmn ();
+
+  if (cbch->stat EQ STAT_ACT)
+  {
+    /*
+     * A CBCH channel is available
+     */
+
+#if !defined (L1_STORES_CBCH_CONFIG)
+    /*
+     * Layer 1 does not store any CBCH configuration (default)
+     * first set the channel configuration
+     */
+    if (cbch->h EQ H_FREQ)
+    {
+      /*
+       * with frequency hopping, set hopping flag, maio, hsn and hopping list.
+       */
+      pchan_sel->h = HOPPING;
+      pchan_sel->rf_channel.maio = cbch->maio;
+      pchan_sel->rf_channel.hsn  = cbch->hsn;
+
+      i=0;
+      pcbch_freq_list->rf_chan_cnt=0;
+      while ((i < 64) AND (cbch->ma[i] NEQ NOT_PRESENT_16BIT))
+      {
+        pcbch_freq_list->rf_chan_no.radio_freq[i] = ARFCN_TO_L1(cbch->ma[i]);
+        i++;
+        pcbch_freq_list->rf_chan_cnt++;
+      }
+    }
+    else
+    {
+      /*
+       * Layer 1 uses a union definition. This is not applicable for the Condat-SAP model.
+       * Therefore the rf channel number is configured by maio and hsn. In general a Avoid the union !!!
+       */
+      pchan_sel->h = NO_HOPPING;
+      pchan_sel->rf_channel.maio = (UBYTE)(ARFCN_TO_L1(cbch->arfcn) & 0xFF);
+      pchan_sel->rf_channel.hsn  = (UBYTE)((ARFCN_TO_L1(cbch->arfcn) >> 8) & 0xFF);
+      memset (pcbch_freq_list, 0, sizeof (T_cbch_freq_list));
+    }
+
+    /*
+     * configure the CBCH channel type (SDCCH/8 or SDCCH/4)
+     */
+    if (cbch->ch < CH_SDCCH_8_0)
+      pcbch_desc->channel_type = CH_SDCCH_4;
+    else
+      pcbch_desc->channel_type = CH_SDCCH_8;
+
+    pcbch_desc->sub_channel   = 0;    /* not relevant */
+    pcbch_desc->timeslot_no  = cbch->tn;
+    pcbch_desc->tsc          = cbch->tsc;
+
+#else
+    /*
+     * Compile option set: L1 stores actual CBCH configuration.
+     * So it is not necessary to store the configuration in ALR.
+     * Just parse the configuration to Layer 1.
+     */
+    {
+      PALLOC (config_cbch, MPHC_CONFIG_CBCH);
+
+      if (cbch->h EQ H_FREQ)
+      {
+        /*
+         * with frequency hopping, set hopping flag, maio, hsn and hopping list.
+         */
+        config_cbch->cbch_desc.chan_sel.h = HOPPING;
+        config_cbch->cbch_desc.chan_sel.rf_channel.maio = cbch->maio;
+        config_cbch->cbch_desc.chan_sel.rf_channel.hsn  = cbch->hsn;
+
+        i=0;
+        config_cbch->cbch_freq_list.rf_chan_cnt=0;
+        while (cbch->ma[i] NEQ NOT_PRESENT_16BIT AND i < 64)
+        {
+          config_cbch->cbch_freq_list.rf_chan_no.hop_chan[i] = ARFCN_TO_L1(cbch->ma[i]);
+          i++; config_cbch->cbch_freq_list.rf_chan_cnt++;
+        }
+      }
+      else
+      {
+        /*
+         * Layer 1 uses a union definition. This is not applicable for the Condat-SAP model.
+         * Therefore the rf channel number is configured by maio and hsn. In general a Avoid the union !!!
+         */
+        config_cbch->cbch_desc.chan_sel.h = NO_HOPPING;
+        config_cbch->cbch_desc.chan_sel.rf_channel.maio = ARFCN_TO_L1(cbch->arfcn) & 0xFF;
+        config_cbch->cbch_desc.chan_sel.rf_channel.hsn  = (ARFCN_TO_L1(cbch->arfcn) >> 8) & 0xFF;
+        memset (&config_cbch->cbch_freq_list, 0, sizeof (T_cbch_freq_list));
+      }
+
+      /*
+       * configure the CBCH channel type (SDCCH/8 or SDCCH/4)
+       */
+      if (cbch->ch < CH_SDCCH_8_0)
+        config_cbch->cbch_desc.channel_type = CH_SDCCH_4;
+      else
+        config_cbch->cbch_desc.channel_type = CH_SDCCH_8;
+
+      config_cbch->cbch_desc.sub_channel    = 0;    /* not relevant */
+      config_cbch->cbch_desc.timeslot_no    = cbch->tn;
+      config_cbch->cbch_desc.tsc            = cbch->tsc;
+
+      ma_cb_config_cbch(config_cbch);
+    }
+#endif
+
+    if (    (pcbch->modus NEQ NOT_PRESENT_8BIT)
+         OR (pcbch->sat_enabled)
+#if defined(FF_HOMEZONE)
+         OR (pcbch->homezone EQ CBCH_HZ_IDLE)
+#endif /* FF_HOMEZONE */
+       )
+    {
+      /*
+       * MMI has requested data
+       * Start with NO_DRX mode
+       * Read each first CBCH block
+       */
+#if defined (L1_STORES_CBCH_CONFIG)
+      cb_start_no_drx_reading (FALSE);
+#else  /* L1_STORES_CBCH_CONFIG */
+      ALR_TRACE_CB ("switch on, send config");
+      cb_start_no_drx_reading (TRUE);
+#endif  /* L1_STORES_CBCH_CONFIG */
+    }
+    else
+    {
+      UBYTE   *si3 = &alr_data->ma_data.sys_info_3[0];
+      UBYTE   *lac = &alr_data->cbch_data.old_cid_plmn_lac[0];
+
+      ALR_TRACE_CB ("switch on, wait for MMI");
+      /*
+       * wait for MMI request
+       */
+      SET_STATE(STATE_NORMAL_CBCH, CBCH_IDLE);
+      SET_STATE(STATE_EXT_CBCH, CBCH_IDLE);
+      /*
+       * update old_cid_plmn_lac
+       */
+      memcpy (lac, &si3[2], 7);
+    }
+  }
+  else
+  {
+    /*
+     * The new configuration indicates no CBCH, so stop the CBCH process in Layer 1
+     */
+    ALR_TRACE_CB ("switch off");
+
+    cb_stop();
+    SET_STATE(STATE_NORMAL_CBCH, CBCH_NULL);
+    SET_STATE(STATE_EXT_CBCH, CBCH_NULL);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : AKR_CBCH                   |
+| STATE   : code                ROUTINE : cb_mmi_cbch_req            |
++--------------------------------------------------------------------+
+
+  PURPOSE : MMI sends a definition of the expected message identifier
+            and data coding schemes for the CBCH messages.
+
+*/
+
+GLOBAL void cb_mmi_cbch_req (T_MMI_CBCH_REQ *cbch)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  ALR_TRACE_CB ("MMI req");
+
+#if defined(FF_HOMEZONE)
+  if (cbch->modus NEQ CBCH_HOMEZONE)
+  {
+    pcbch->modus = cbch->modus;
+    TRACE_EVENT_P1 ("CBCH: homezone=%u", pcbch->homezone);
+  }
+  else if (cbch->msg_id[0] EQ NOT_PRESENT_16BIT)
+  {
+    /*
+     * switch off automatically homezone request
+     * - homezone state to off
+     * - clear old message
+     * - stop timer
+     */
+     pcbch->msg_hz_id = NOT_PRESENT_16BIT;
+     pcbch->homezone = CBCH_HZ_OFF;
+     TIMERSTOP (TIM_HOMEZONE);
+  }
+  else
+  {
+    /*
+     * switch on automatically homezone request
+     * - set homezone state to idle whatever are before
+     * - set new homezone id
+     * - clear old message
+     */
+    pcbch->msg_hz_id = cbch->msg_id[0];
+    pcbch->dcs_hz_id = cbch->dcs_id[0];
+    pcbch->hz_timeout = cbch->dcs_id[1]*1000;
+    ALR_TRACE_CB_HZREQ (pcbch->msg_hz_id,
+      pcbch->hz_timeout);
+    if (pcbch->homezone EQ CBCH_HZ_OFF)
+    {
+      UBYTE cbch_state = GET_STATE (STATE_NORMAL_CBCH);
+      pcbch->homezone = CBCH_HZ_IDLE;
+      if (cbch_state NEQ CBCH_NULL)
+      {/* CBCH system is prepared */
+        if (cbch_state EQ CBCH_IDLE)
+        { /* start timer only if CBCH system is prepared */
+          TIMERSTART (TIM_HOMEZONE, 1000);
+        }
+        else
+        { /* CBCH system is already active -> wait for HZ message */
+          pcbch->homezone = CBCH_HZ_PENDING;
+          TIMERSTART (TIM_HOMEZONE, pcbch->hz_timeout);
+          ALR_TRACE_CB ("HOMEZONE is pending");
+        }
+      }
+    }
+    return;
+  }
+#else  /* FF_HOMEZONE */
+  pcbch->modus = cbch->modus;
+#endif  /* FF_HOMEZONE */
+  /*
+   * Storing of Parameter and clearing of
+   * the received CB memory
+   */
+  memcpy (&pcbch->msg_id[0], cbch->msg_id, sizeof (pcbch->msg_id));
+  memcpy (&pcbch->dcs_id[0], cbch->dcs_id, sizeof (pcbch->dcs_id));
+
+#if !defined(NTRACE)
+{
+  int i;
+
+  ALR_TRACE_CB_MODUS(cbch->modus);
+
+  for (i=0;
+    (i < MAX_IDENTS) AND (pcbch->msg_id[i] NEQ NOT_PRESENT_16BIT);
+    i++)
+  {
+    TRACE_EVENT_P2 ("CBCH: id[%u]=%u", i, pcbch->msg_id[i]);
+  }
+  for (i=0;
+    (i < MAX_IDENTS) AND (pcbch->dcs_id[i] NEQ NOT_PRESENT_8BIT);
+    i++)
+  {
+    TRACE_EVENT_P2 ("CBCH:dcs[%u]=%u", i, pcbch->dcs_id[i]);
+  }
+}
+#endif /* !NTRACE */
+
+  /* old messages should only be erased when MMI turns CBCH off */
+  if (pcbch->modus EQ MMI_CBCH_STOP)
+  {
+    /* also erases the count of old message */
+    memset (&pcbch->old_cbch_msg, 0, sizeof (T_CB_MSG));
+    memset (&pcbch->msg[0], 0, CBCH_MSG_SIZE);
+  }
+
+  /*
+    TRACE_EVENT_P2 ("CBCH: STATE_MA=%u STATE_CBCH=%u", GET_STATE(STATE_MA), GET_STATE (STATE_CBCH));
+  */
+
+#ifdef GPRS
+  if ((GET_STATE(STATE_MA) EQ MA_IDLE AND !alr_data->gprs_data.pbcch) OR
+      (alr_data->gprs_data.pbcch AND alr_data->gprs_data.pim))
+#else
+  if (GET_STATE(STATE_MA) EQ MA_IDLE)
+#endif
+  {
+    /*
+     * layer 1 is only configured, if ALR is in idle state, else the configuration
+     * is delayed until the cell is selected.
+     */
+    switch (GET_STATE (STATE_NORMAL_CBCH))
+    {
+      case CBCH_NULL:
+        /*
+         * no CBCH channel is available
+         */
+        break;
+
+      case CBCH_IDLE:
+        if (pcbch->modus EQ MMI_CBCH_STOP AND
+            !pcbch->sat_enabled)
+        {
+          /*
+           * CBCH download is not enabled and the MMI indicates stop of
+           * the CBCH channel, then stop CBCH process in layer 1.
+           */
+          cb_stop();
+        }
+        else
+        {
+          /*
+           * new definitions of message identifier or data coding schemes
+           * then re-configure layer 1 and go back to CBCH reading without
+           * scheduling information.
+           */
+          cb_start_no_drx_reading (TRUE);
+        }
+        break;
+
+      default:
+        /*
+         * we already received a MMI CBCH REQ before
+         */
+        if (pcbch->modus EQ MMI_CBCH_STOP AND
+            !pcbch->sat_enabled)
+        {
+          /*
+           * CBCH download is not enabled and the MMI indicates stop of
+           * the CBCH channel, then stop CBCH process in layer 1.
+           */
+          cb_stop();
+          SET_STATE(STATE_NORMAL_CBCH, CBCH_IDLE);
+          SET_STATE(STATE_EXT_CBCH, CBCH_IDLE);
+        }
+        break;
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : TIL_CBCH                   |
+| STATE   : code                ROUTINE : cb_mmi_sat_cbch_req        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reception of a list of identifiers for SIM TOOLKIT
+            CBCH Download.
+
+*/
+
+GLOBAL void cb_mmi_sat_cbch_req (T_MMI_SAT_CBCH_DWNLD_REQ * cbch_req)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  unsigned i;
+  ALR_TRACE_CB ("MMI SAT req");
+
+  /*
+   * clear the list of needed message identifier for CBCH download
+   * and fill it with the definiton of MMI.
+   */
+   memset (pcbch->msg_id_sat, NOT_PRESENT_16BIT,
+           sizeof(pcbch->msg_id_sat));
+   memcpy (pcbch->msg_id_sat, cbch_req->msg_id,
+           sizeof(cbch_req->msg_id[0])*(cbch_req->count));
+
+   /*
+    * CBCH download is disabled
+    */
+  pcbch->sat_enabled = FALSE;
+  for (i = 0; i < cbch_req->count; i++)
+  {
+    if (pcbch->msg_id_sat[i] NEQ NOT_PRESENT_16BIT)
+    {
+      pcbch->sat_enabled = TRUE;
+      break;
+    }
+  }
+  vsi_o_error_ttrace ("HM cb_mmi_sat_cbch_req(), sat_enabled = %d, modus = %d", 
+                      pcbch->sat_enabled, pcbch->modus);
+#ifdef GPRS
+  if ((GET_STATE(STATE_MA) EQ MA_IDLE AND !alr_data->gprs_data.pbcch) OR
+      (alr_data->gprs_data.pbcch AND alr_data->gprs_data.pim))
+#else
+  if (GET_STATE(STATE_MA) EQ MA_IDLE)
+#endif
+  {
+          /*
+           * Current state is compatible with enabling of CBCH reading, 
+           * configure L1 to read CBCH. Otherwise configuration is delayed
+           * until ALR reaches a compatible state.
+           */    
+    switch (GET_STATE (STATE_NORMAL_CBCH))
+    {
+      case CBCH_NULL:
+            /*
+             * No CBCH channel is available.
+             */
+        break;
+
+      default:
+      {
+        if (pcbch->modus EQ MMI_CBCH_STOP AND !pcbch->sat_enabled)
+        {
+            /* No CBCH to read. Stop reading CBCH in L1. */
+          cb_stop();
+        }
+        else
+        {
+
+            /* 
+             * CBCH channel is available. 
+             * Configure layer 1 for catching the CBCH download messages.
+             */
+          PALLOC (config_cbch, MPHC_CONFIG_CBCH_REQ);
+          memcpy (config_cbch, &pcbch->mphc_config_cbch, sizeof (T_MPHC_CONFIG_CBCH_REQ));
+          ma_cb_config_cbch(config_cbch);
+          cb_read_cbch (CBCH_NO_SCHED | CBCH_READ_NORM);
+          cb_read_cbch (CBCH_NO_SCHED | CBCH_READ_EXT);
+          SET_STATE(STATE_NORMAL_CBCH, CBCH_NO_DRX);
+          SET_STATE(STATE_EXT_CBCH, CBCH_NO_DRX);         
+        }
+      }
+      break;
+    } /* End of switch (GET_STATE (STATE_NORMAL_CBCH)) */
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : TIL_CBCH                   |
+| STATE   : code                ROUTINE : cb_data_ind                |
++--------------------------------------------------------------------+
+
+  PURPOSE : A CBCH message is received.
+
+*/
+
+GLOBAL void cb_data_ind (T_MPHC_DATA_IND  *cbch_ind)
+{
+  GET_INSTANCE_DATA;
+  UBYTE block_no;
+  UBYTE block_description;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE * expected_seq_number  = &(pcbch->expected_seq_number[0]);
+
+  /*
+   * check whether the CBCH message has been received on the
+   * normal CBCH channel or the extended CBCH channel
+   */
+  if (cbch_ind->tc >= 4)
+  {
+    pcbch->msg_is_extended = CBCH_READ_EXT;
+    expected_seq_number  = &(pcbch->expected_seq_number[1]);
+  }
+  else if(cbch_ind->tc < 4)
+    pcbch->msg_is_extended = CBCH_READ_NORM;
+
+  if (cbch_ind->error_flag EQ VALID_BLOCK)
+  {
+    /*
+     * if the CBCH block is valid, calculate the block number
+     */
+    block_description = cbch_ind->l2_frame.content[0];
+    block_no = (UBYTE)(block_description & 0x0F);
+    if (block_no < CBCH_NULL_MSG)
+    {
+      ALR_TRACE_CB_BLOCK_NO (block_description);
+    }
+    TRACE_EVENT_P2("expected_block_number = %d, schedule_length =%d", (*expected_seq_number), pcbch->schedule_length[0]);
+    switch(block_no)
+    {
+      case CBCH_BLOCK_0:
+        memcpy (&pcbch->msg[0], &cbch_ind->l2_frame.content[1], CBCH_BLOCK_SIZE);
+#if defined(FF_HOMEZONE)
+        if (!cb_check_homezone ((UBYTE)(CBCH_BLOCK_SIZE*(block_no+1))))
+#endif  /* FF_HOMEZONE */
+          cb_first_block(block_description);
+        break;
+
+      case CBCH_BLOCK_1:
+      case CBCH_BLOCK_2:
+      case CBCH_BLOCK_3:
+       /*
+         * check for sequence number 
+         */
+       if(*expected_seq_number NEQ block_no)
+       {
+         ALR_TRACE_CB("Sequence error");
+         cb_error_ind();        
+       }
+       else
+       {
+         memcpy (&pcbch->msg[CBCH_BLOCK_SIZE*(block_no & 3)],
+          &cbch_ind->l2_frame.content[1], CBCH_BLOCK_SIZE);
+
+         (*expected_seq_number)++;
+         if( *expected_seq_number > CBCH_BLOCK_3 )
+           *expected_seq_number = CBCH_BLOCK_0;
+         
+         
+         if ( (block_description & CBCH_LAST_BLOCK)  OR  (block_no EQ CBCH_BLOCK_3)  )
+         {
+           /*
+             * last block of msg
+             */
+           if(pcbch->msg_type EQ CBCH_NORM_MSG)
+             /*
+               * +1, because parameter is length not offset
+               */
+             cb_cbch_message((UBYTE)(CBCH_BLOCK_SIZE*(block_no+1)));
+           else if(pcbch->msg_type EQ CBCH_SCHEDULE_MSG)
+             cb_schedule_message();
+           else if(pcbch->msg_type EQ CBCH_SAT_MSG)
+             cb_sat_cbch_message((UBYTE)(CBCH_BLOCK_SIZE*(block_no+1)));
+         }
+       }
+       break;
+
+      case CBCH_FIRST_SCHED_MSG:
+        /*
+         * first SCHEDULE block
+         */
+
+        ALR_TRACE_CB ("SCHEDULE");
+        memcpy (&pcbch->msg[0],  &cbch_ind->l2_frame.content[1], CBCH_BLOCK_SIZE);
+        cb_read_next_3_blocks();
+
+        pcbch->msg_type = CBCH_SCHEDULE_MSG;
+        break;
+
+      case CBCH_NULL_MSG:
+        /*
+         * NULL Message
+         */
+
+        /*
+        ALR_TRACE_CB ("null msg");
+        */
+        cb_null_message ();
+        break;
+
+      default:
+        ALR_TRACE_CB ("unknown");
+        cb_error_ind();
+        break;
+    }
+
+    ALR_EM_RECEIVE_CBCH_MESSAGE;
+
+  }
+  else
+  {
+    /*
+     * Invalid block
+     */
+    /*
+    ALR_TRACE_CB_ERROR(cbch_ind->error_flag);
+    */
+
+    pcbch->msg_type = CBCH_NO_MSG;
+    cb_error_ind ();
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_first_block             |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reception of the first CBCH block.
+
+*/
+
+LOCAL void cb_first_block (UBYTE status)
+{
+  GET_INSTANCE_DATA;
+  UBYTE  result;
+  T_CBMSG_HEADER  *p_cbh;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  /*
+   * extract message id and data coding scheme from the message
+   */
+  p_cbh = (T_CBMSG_HEADER*)(&pcbch->msg[0]);
+
+  ALR_TRACE_CB_MSGHEAD (p_cbh);
+
+  /*
+   * check the incoming message:
+   * 1. matches the message identifier
+   * 2. matches the data coding scheme
+   * 3. is this message not received yet
+   */
+  result =  cb_check_message_id (CB_MESSAGE_ID(p_cbh));
+  result += cb_check_data_coding_scheme (CB_DCS(p_cbh));
+  result += cb_check_old_msg ();
+
+  if (result EQ 3)
+  {
+    /*
+     * all checks are passed
+     */
+    if (! pcbch->sat_enabled OR
+        ! cb_sat_check_message_id(CB_MESSAGE_ID(p_cbh)))
+    {
+      /*
+       * it is not a CBCH download message or
+       * CBCH download is not enabled
+       */
+      if (status & CBCH_LAST_BLOCK)
+      {
+        /*
+         * the first is the only block, then forward it
+         * to MMI.
+         */
+        cb_cbch_message (CBCH_BLOCK_SIZE*(CBCH_BLOCK_0+1));
+      }
+      else
+      {
+        /*
+         * store the block and request the three remaining
+         * blocks in layer 1.
+         */
+        pcbch->msg_type = CBCH_NORM_MSG;
+        cb_read_next_3_blocks();
+      }
+    }
+    else
+    {
+      /*
+       * It is a CBCH download message and CBCH download is enabled.
+       */
+      if (status & CBCH_LAST_BLOCK)
+      {
+        /*
+         * the first block is the only block, so forward the
+         * message to MMI.
+         */
+        cb_sat_cbch_message (CBCH_BLOCK_SIZE*(CBCH_BLOCK_0+1));
+      }
+      else
+      {
+        /*
+         * store the data and request the three remaining blocks.
+         */
+        pcbch->msg_type = CBCH_SAT_MSG;
+        cb_read_next_3_blocks();
+      }
+    }
+  }
+  else
+  {
+    /*
+     * the message has not passed the checks.
+     * So it can be only a CBCH download message.
+     */
+    if(! pcbch->sat_enabled OR
+       ! cb_sat_check_message_id(CB_MESSAGE_ID(p_cbh)))
+    {
+      /*
+       * SAT is not enabled or it is not a CBCH download
+       * message. So start reading of next scheduled message.
+       */
+      memset (&pcbch->msg[0], 0, 88);
+      cb_next_scheduled_msg();
+
+    }
+    else
+    {
+      /*
+       * it is CBCH download message and SAT is enabled
+       */
+      if (status & CBCH_LAST_BLOCK)
+      {
+        /*
+         * the first block is the last one, so send the
+         * message to MMI.
+         */
+        cb_sat_cbch_message (CBCH_BLOCK_SIZE*(CBCH_BLOCK_0+1));
+      }
+      else
+      {
+        /*
+         * store the first block and request the remaining three.
+         */
+        pcbch->msg_type = CBCH_SAT_MSG;
+        cb_read_next_3_blocks();
+      }
+    }
+  }
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : TIL_CBCH                   |
+| STATE   : code                ROUTINE : cb_sat_cbch_message        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reception of a complete CBCH message for CBCH download.
+
+*/
+
+LOCAL void cb_sat_cbch_message (UBYTE length)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  PALLOC (mmi_cbch_ind, MMI_SAT_CBCH_DWNLD_IND);
+
+  ALR_EM_CBCH_MESSAGE_COMPLETE;
+
+  TRACE_FUNCTION ("cb_sat_cbch_message()");
+
+  /*
+   * copy the content of the message into the primitive.
+   */
+  memcpy (mmi_cbch_ind->cbch_msg, pcbch->msg, 88);
+  mmi_cbch_ind->cbch_len = length;
+
+  /*
+   * send to MMI
+   */
+  PSENDX(MMI, mmi_cbch_ind);
+
+  /*
+   * prepare for next reception
+   */
+  pcbch->msg_type = CBCH_NO_MSG;
+  pcbch->expected_seq_number[0] = CBCH_BLOCK_0;
+  pcbch->expected_seq_number[1] = CBCH_BLOCK_0;
+  /*
+   * start reading of next scheduled message.
+   */
+  cb_next_scheduled_msg();
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : TIL_CBCH                   |
+| STATE   : code                ROUTINE : cb_schedule_message        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reception of a SCHEDULE message.
+
+*/
+
+LOCAL void cb_schedule_message (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE extended = pcbch->msg_is_extended;
+  UBYTE *p_sched_msg = &pcbch->scheduled_sched_msg[extended];
+
+  ALR_EM_RECEIVE_SCHEDULE_MESSAGE;
+
+  switch ( get_cbch_state(extended) )
+  {
+    case CBCH_NO_DRX:
+      /*
+       * change from NO DRX mode (no knowledge about Scheduling)
+       * to DRX mode.
+       */
+      
+      set_cbch_state (extended, CBCH_DRX);
+      
+
+      /*
+       * check whether it is a scheduled schedule message or not.
+       */
+      if(pcbch->msg[0] EQ 1)
+        *p_sched_msg = 1;
+      else
+        *p_sched_msg = 0;
+
+      /*
+       * create schedule map with new and old messages
+       */
+      cb_create_schedule_map (TRUE);
+
+      /*
+       * forward the schedule map to layer 1.
+       */
+      cb_read_cbch((UBYTE)(CBCH_SCHED | extended));
+
+      break;
+
+    case CBCH_DRX:
+      if (pcbch->msg[0] EQ 1)
+      {
+        /*
+         * scheduled SCHEDULE message
+         */
+         if(*p_sched_msg <= 2)
+            (*p_sched_msg)++;
+
+         if (*p_sched_msg > 1)
+           /*
+            * we have read a full schedule period
+            * so we dont need to read the old messages
+            */
+           cb_create_schedule_map (FALSE);
+         else
+           cb_create_schedule_map (TRUE);
+
+        cb_read_cbch((UBYTE)(CBCH_SCHED | extended));
+      }      
+      break;
+    default:
+      break;
+  }
+  /*
+   * prepare for next reception
+   */
+  pcbch->msg_type = CBCH_NO_MSG;
+  pcbch->expected_seq_number[0] = CBCH_BLOCK_0;
+  pcbch->expected_seq_number[1] = CBCH_BLOCK_0;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_null_message            |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reception of a NULL message.
+
+*/
+LOCAL void cb_null_message (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE extended = pcbch->msg_is_extended;
+
+  ALR_EM_RECEIVE_NULL_MESSAGE;
+
+  switch ( get_cbch_state(extended) )
+  {
+    case CBCH_DRX:
+      if (pcbch->schedule_length[extended] EQ 0)
+      {
+        /*
+         * instead of the scheduled SCHEDULE message
+         * a NULL message has received.
+         * Restarting with NO DRX mode
+         */
+        set_cbch_state (extended, CBCH_NO_DRX);
+        cb_read_cbch ((UBYTE)(CBCH_NO_SCHED | extended));
+      }
+      else
+      {
+        cb_next_scheduled_msg();
+      }
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_error_ind               |
++--------------------------------------------------------------------+
+
+  PURPOSE : Indicates an invalid block.
+                   1) with error_flag =TRUE
+                   2) invalid sequence number
+                   3) out of sequence block
+*/
+
+LOCAL void cb_error_ind (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE extended = pcbch->msg_is_extended;
+                     
+  if( pcbch->expected_seq_number[extended] NEQ CBCH_BLOCK_0)
+  {
+    /*
+      * stop the next blocks
+      */
+    cb_stop_next_blocks();      
+  }
+  switch ( get_cbch_state(extended) )
+  {
+    case CBCH_DRX:
+      if (pcbch->schedule_length[extended] EQ 0)
+      {
+        /*
+         * instead of the scheduled SCHEDULE message
+         * an invalid message has been received.
+         * Restarting with NO DRX mode
+         */
+        set_cbch_state (extended, CBCH_NO_DRX);
+        cb_read_cbch ((UBYTE)(CBCH_NO_SCHED | extended));
+      }
+      else
+        /*
+         * Go back to FIRST DRX mode.
+         */
+      {
+        pcbch->scheduled_sched_msg[extended] = 1;       
+       cb_next_scheduled_msg();
+      }
+      break;
+    default:
+      break;
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_ind                     |
++--------------------------------------------------------------------+
+
+  PURPOSE : Indication of the CBCH message.
+
+*/
+
+LOCAL void cb_ind (UBYTE length)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  PALLOC (mmi_cbch_ind, MMI_CBCH_IND);
+
+  ALR_EM_CBCH_MESSAGE_COMPLETE;
+
+  /*
+   * copy the message content to the primitive.
+   */
+  memcpy (mmi_cbch_ind->cbch_msg, pcbch->msg, CBCH_MSG_SIZE);
+  mmi_cbch_ind->cbch_len = length;
+
+  ma_cb_mmi_cbch_ind(mmi_cbch_ind);
+
+  {
+    T_CBMSG_HEADER *p_cbh = (T_CBMSG_HEADER*)(&pcbch->msg[0]);
+    ALR_TRACE_CB_MSGHEAD (p_cbh);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_read_next_3_blocks         |
++--------------------------------------------------------------------+
+
+  PURPOSE : Starts read of next 3 blocks.
+
+*/
+
+LOCAL void cb_read_next_3_blocks(void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE extended = pcbch->msg_is_extended;
+
+  if( extended EQ CBCH_READ_EXT)
+    ma_cb_info_req (CBCH_EXT_BLOCK234);
+  else
+    ma_cb_info_req (CBCH_NORM_BLOCK234);
+
+  pcbch->expected_seq_number[extended] = CBCH_BLOCK_1;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_stop_next_blocks        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Stop next blocks.
+
+*/
+
+LOCAL void cb_stop_next_blocks (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  /*
+   * stop the next blocks
+   */
+
+  /*
+    * Upper layers / L1 Circuit Switched interfaces
+    * S922.doc , Ver 1.9
+    * Section 11.3 MPHC_CBCH_INFO_REQ 
+    *
+    * This message can be used to update on fly L1 
+    * with new tb_bitmap which then replaces the current one. 
+    * In such a case, 0 in the bitmap means abort any pending reading of TB1/2/3 or TB5/6/7.
+    *
+    * A previous "schedule_length=0" is used to specify "No schedule present".
+    * In such a case, L1 starts reading continuously TB0 for normal CBCH or TB4 for Extended CBCH.
+    */
+  ma_cb_info_req (0);
+  
+  pcbch->msg_type = CBCH_NO_MSG;
+  pcbch->expected_seq_number[0] = CBCH_BLOCK_0;
+  pcbch->expected_seq_number[1] = CBCH_BLOCK_0;
+}
+
+#if defined(FF_HOMEZONE) && defined(INDICATE_HZ_ERROR)
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_ind_hz_err              |
++--------------------------------------------------------------------+
+
+  PURPOSE : Indication of the CBCH message and stop the next blocks.
+
+*/
+
+LOCAL void cb_ind_hz_err (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  PALLOC (mmi_cbch_ind, MMI_CBCH_IND);
+
+  memset (mmi_cbch_ind->cbch_msg, 0xff, CBCH_MSG_SIZE);
+  mmi_cbch_ind->cbch_msg[2] = pcbch->msg_hz_id >> 8;
+  mmi_cbch_ind->cbch_msg[3] = pcbch->msg_hz_id & 0xff;
+  mmi_cbch_ind->cbch_len = 0; /* error indication */
+  ALR_TRACE_CB ("cb_ind_hz_err()");
+
+  ma_cb_mmi_cbch_ind(mmi_cbch_ind);
+}
+#endif /* FF_HOMEZONE */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_cbch_message            |
++--------------------------------------------------------------------+
+
+  PURPOSE : Reception of a complete CBCH message.
+
+*/
+
+LOCAL void cb_cbch_message (UBYTE length)
+{
+  /*
+   * Indicate the message
+   */
+  cb_ind (length);
+  /*
+   * stop the next blocks
+   */
+  cb_stop_next_blocks ();
+  /*
+   * store the cbch message to avoid double reception
+   */
+  cb_store_cbch_msg ();
+  /*
+   * start reading of the next scheduled message
+   */
+  cb_next_scheduled_msg();  
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_store_cbch_msg          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Store key parameter of a CBCH message to avoid
+            forwarding of a CBCH message twice.
+
+*/
+LOCAL void cb_store_cbch_msg (void)
+{
+  GET_INSTANCE_DATA;
+  USHORT x;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  ALR_TRACE_CB ("Store msg");
+
+  /*
+   *  It is not permitted to save the cbch message,
+   *  if the following pattern are in the
+   *  lacation area identification (bcch:sys_info_3) :
+   *                   [4]  0x00
+   *                   [5]  0xF1
+   *                   [6]  0x10
+   *
+   *  that means FTA in testhouse
+   */
+  if (alr_data->ma_data.sys_info_3[4] EQ 0     AND
+      alr_data->ma_data.sys_info_3[5] EQ 0xF1  AND
+      alr_data->ma_data.sys_info_3[6] EQ 0x10)
+    return;
+
+  /*
+   * If storage is full, remove the first one.
+   */
+  if (pcbch->old_cbch_msg.cnt EQ MAX_OLD_CB)
+    cb_remove_message (0);
+
+  /*
+   * store the new one
+   */
+  x = pcbch->old_cbch_msg.cnt++;
+  memcpy (&pcbch->old_cbch_msg.header[x],
+          &pcbch->msg, sizeof (T_CBMSG_HEADER));
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_check_message_id        |
++--------------------------------------------------------------------+
+
+  PURPOSE : Check Message Identifier of the first CBCH block.
+
+*/
+
+LOCAL UBYTE cb_check_message_id (USHORT msg_id)
+{
+  GET_INSTANCE_DATA;
+  USHORT i;
+  UBYTE  result = TRUE;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  /*
+   * if no message identifier are defined for comparision
+   * make a shortcut and return immediately. 
+   * MODUS CBCH_ACCEPT,but no msg_id defined,accept NO messages
+   * MODUS CBCH_IGNORE,but no msg_id define, accept all messages
+   * MODUS CBCH_STOP,but no msg_id defined,  accept NO messages
+   * MODUS CBCH_HOMEZONE,but no msg_id defined, accept NO messages/ 
+   */
+  if ( pcbch->msg_id[0] EQ NOT_PRESENT_16BIT )
+  {
+    if (pcbch->modus EQ CBCH_IGNORE) 
+    {
+      return TRUE;
+    }
+    else
+    {
+      return FALSE;
+    }
+  }
+
+  /*
+   * initialise result
+   * if the msg_id is not found and MMI specified
+   * a positive range(CBCH_ACCEPT) return 0
+   */
+  result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? FALSE : TRUE);
+
+  /*
+   * message identifier are stored as a pair to express a range
+   */
+  for (i=0; i < MAX_IDENTS-1; i+=2)
+  {
+    /*
+     * end of list reached
+     */
+    if (pcbch->msg_id[i] EQ NOT_PRESENT_16BIT)
+      break;
+
+    /*
+     * check whether the message identifier is inside or outside
+     * the range. Result depends on what MMI has requested.
+     */
+    if ((pcbch->msg_id[i]   <= msg_id) AND
+        (pcbch->msg_id[i+1] >= msg_id))
+      result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? TRUE : FALSE);
+  }
+
+  return result;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_sat_check_message_id    |
++--------------------------------------------------------------------+
+
+  PURPOSE : Check Message Identifier of the first CBCH block for CBCH
+            download purposes.
+
+*/
+
+LOCAL UBYTE cb_sat_check_message_id (USHORT msg_id)
+{
+  GET_INSTANCE_DATA;
+  USHORT i;
+  UBYTE  result;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  /*
+   * initialize result
+   */
+  result = FALSE;
+
+  /*
+   * for all stored message identifier of CBCH download
+   */
+  for (i = 0; i < MAX_IDENTS_SAT; i++)
+  {
+    /*
+     * end of list reached
+     */
+    if (pcbch->msg_id_sat[i] EQ NOT_PRESENT_16BIT)
+      break;
+
+    /*
+     * if message identifier matches
+     */
+    if (pcbch->msg_id_sat[i] EQ msg_id)
+    {
+      result = TRUE;
+      break;
+    }
+  }
+
+  return result;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_check_data_coding_scheme|
++--------------------------------------------------------------------+
+
+  PURPOSE : Check Data Coding Scheme of the first CBCH block.
+
+*/
+LOCAL UBYTE cb_check_data_coding_scheme (UBYTE dcs_id)
+{
+  GET_INSTANCE_DATA;
+  USHORT i;
+  UBYTE  result = TRUE;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  /*
+   * if the list is empty, result is positive
+   */
+  if (pcbch->dcs_id [0] EQ NOT_PRESENT_8BIT)
+    return result;
+
+  /*
+   * initialise result
+   * if the dcs_id is not found and MMI specified
+   * a positive range(CBCH_ACCEPT) return 0
+   */
+  result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? 0 : 1);
+
+
+  for (i=0;i<MAX_IDENTS-1;i+=2)
+  {
+    /*
+     * end of list reached
+     */
+    if (pcbch->dcs_id[i] EQ NOT_PRESENT_8BIT)
+      break;
+
+      /*
+       * Data Coding Scheme identifier matches
+       */
+      if (pcbch->dcs_id[i] <= dcs_id AND
+          pcbch->dcs_id[i+1] >= dcs_id)
+        result = (UBYTE)(pcbch->modus EQ CBCH_ACCEPT ? 1 : 0);
+  }
+
+  return result;
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_check_old_msg           |
++--------------------------------------------------------------------+
+
+  PURPOSE : Check against old messages.
+
+*/
+LOCAL UBYTE cb_check_old_msg (void)
+{
+  GET_INSTANCE_DATA;
+  int i;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  T_CBMSG_HEADER  *p_cbh = (T_CBMSG_HEADER*)&pcbch->msg[0];
+
+  ALR_TRACE_CB ("compare with stored msg");
+  for (i=0; i < pcbch->old_cbch_msg.cnt; i++)
+  {
+    ALR_TRACE_CB_MSGHEAD (&pcbch->old_cbch_msg.header[i]);
+
+    if (memcmp (&pcbch->old_cbch_msg.header[i], p_cbh, 6) EQ 0)
+    {
+      return FALSE; /* already stored message */
+    }
+    else
+    {
+      /* if the difference is only in the update number,
+       * then we need to delete the old version of the message (so that the different
+       * versions do not fill up the storage) and we can even abandon the comparison;
+       * a message that is resent with a different update number should only use
+       * one entry in the list; otherwise it may throw out other messages that should be kept;
+       * think of German network that sends every minute a new update; would use up 15 entries
+       *
+       * some change, now check if it is only the update number that has changed
+       * (memcmp covers 4 header bytes: msg_id3,  msg_id4, dcs and page
+       *  => ignore lint warning)
+       */
+      /*lint -e{420} (Warning -- Apparent access beyond array) */
+      if ((CB_GS_CODE(&pcbch->old_cbch_msg.header[i]) == CB_GS_CODE(p_cbh)) AND
+          (CB_MSG_CODE(&pcbch->old_cbch_msg.header[i]) == CB_MSG_CODE(p_cbh)) AND
+          !memcmp (&(((T_CBMSG_HEADER*)&pcbch->old_cbch_msg.header[i])->msg_id3),
+                     &p_cbh->msg_id3, 4)) 
+      { /* all these fields match, therefore the change must have been only in the update number */
+
+        SHORT old_update_nr, new_update_nr;
+        old_update_nr = CB_UPDATE_NO(&pcbch->old_cbch_msg.header[i]);
+        new_update_nr = CB_UPDATE_NO(p_cbh);
+        /*
+          * 3GPP 03 41
+          * Any Update Number eight or less higher (modulo 16) than the last received Update Number 
+          * will be considered more recent, and shall be treated as a new message
+          */          
+        if((!new_update_nr) OR 
+           ((new_update_nr - old_update_nr + MAX_UPDATE_NO) % MAX_UPDATE_NO <= MAX_UPDATE_NO_DIFF))
+        {
+           ALR_TRACE_CB ("change update num, delete old message");
+           /* remove the old message so that we do not use up another entry for this new version of the message */
+           cb_remove_message (i);
+           /* skip out of loop because we found the match  */
+           break;
+        }
+        else
+          return FALSE;
+      }
+    }
+  }
+
+  return TRUE;  /* new message */
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_read_cbch               |
++--------------------------------------------------------------------+
+
+  PURPOSE : Starts reading of the first block of CBCH.
+            The parameter defines if the extended or the normal CBCH
+            should be read and if scheduling should be used.
+
+*/
+
+LOCAL void cb_read_cbch (UBYTE flags)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE extended = (UBYTE)(flags & CBCH_READ_EXT);
+  ULONG first_block = pcbch->schedule_map[extended][0];
+  ULONG second_block = pcbch->schedule_map[extended][1];
+  
+  PALLOC (sched_req, MPHC_CBCH_SCHEDULE_REQ);
+ 
+  ALR_TRACE_CB_START_READ(flags);
+
+  sched_req->cbch_select     = extended;
+
+  ALR_EM_START_CBCH_READING;
+
+  if(flags & CBCH_SCHED)
+  {
+    UBYTE n = pcbch->begin_schedule[extended] -1;
+    
+    sched_req->schedule_length = pcbch->end_schedule[extended] - 
+                                 pcbch->begin_schedule[extended] +1;
+
+    /*
+     * the MPHC SAP uses first_blocks_1 as USHORT although the internal data base 
+     * of ALR uses for convinience an array of 2 ULONG for first_blocks_0 and 
+     * first_blocks_1; ergo: do a cast for first_blocks_1 here
+     */
+
+    if(  pcbch->begin_schedule[extended] EQ 1)
+    {
+      sched_req->first_blocks_0  = first_block;
+      sched_req->first_blocks_1  = (USHORT)second_block;
+    }
+    else if(pcbch->begin_schedule[extended] < 32)
+    {
+      sched_req->first_blocks_0  = (first_block >> n) | ((second_block << (32 - n)));
+      sched_req->first_blocks_1  = (USHORT) (second_block >> n);
+    }
+    else
+    {
+      sched_req->first_blocks_0 = (USHORT)(second_block >> (n - 32));
+      sched_req->first_blocks_1  = 0;      
+    }    
+  }
+  else
+  {
+    sched_req->schedule_length = 0;
+  }
+
+  ma_cb_sched_req(sched_req);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_check_ci_lai_plmn       |
++--------------------------------------------------------------------+
+
+  PURPOSE : Checking the Cell Identity and the Location Area Identification
+            to handle the geographical zone parameter.
+*/
+
+LOCAL void cb_check_ci_lai_plmn (void)
+{
+  GET_INSTANCE_DATA;
+  USHORT  i;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE   keep = 0x00;
+  UBYTE   *si3 = &alr_data->ma_data.sys_info_3[0];
+  UBYTE   *lac = &pcbch->old_cid_plmn_lac[0];
+  UCHAR  gs_scope_change_ind = CB_GEOGR_CHANGE_NONE;
+
+  /*
+   *  it is not permitted to save the cbch message,
+   *  if the following pattern are in the
+   *  location area identification (bcch:sys_info_3) :
+   *                   [4]  0x00
+   *                   [5]  0xF1
+   *                   [6]  0x10
+   *
+   *   that means FTA in testhouse.
+   */
+  if ((si3[4] EQ 0x00) AND
+      (si3[5] EQ 0xF1) AND
+      (si3[6] EQ 0x10)
+     )
+    return;
+
+  if ((si3[4] NEQ lac[2]) OR
+      (si3[5] NEQ lac[3]) OR
+      (si3[6] NEQ lac[4])
+     )
+  {
+    /*
+     *  The PLNM has changed
+     */
+    gs_scope_change_ind = CB_GEOGR_CHANGE_PLMN;
+    pcbch->old_cbch_msg.cnt = 0; /* clear all messages */
+  }
+  else if ((si3[7] NEQ lac[5]) OR
+           (si3[8] NEQ lac[6])
+          )
+  {
+    /*
+     *  The location area identification has changed
+     */
+    keep = CB_GEOGR_SCOPE_PLMN; /* keep PLMN wide messages */
+    gs_scope_change_ind = CB_GEOGR_CHANGE_LAC;
+  }
+  else if ((si3[2] NEQ lac[0]) OR
+           (si3[3] NEQ lac[1])
+          )
+  {
+    /*
+     *  The Cell Identity has changed
+     */
+
+    /* indicate cell change to MMI only if we have received any CBCH broadcast messages */
+    if (pcbch->old_cbch_msg.cnt > 0)
+		  gs_scope_change_ind = CB_GEOGR_CHANGE_CELL;
+    keep = CB_GEOGR_SCOPE_CELLN; /* keep PLMN and Location Area wide messages */
+  }
+
+
+  /*
+   * update old_cid_plmn_lac
+   */
+  memcpy (lac, &si3[2], 7);
+
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_remove_message          |
++--------------------------------------------------------------------+
+
+  PURPOSE : Removes the indicated CBCH message from the internal
+            storage.
+
+*/
+LOCAL void cb_remove_message (USHORT i)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  if ((pcbch->old_cbch_msg.cnt) AND
+      (i < pcbch->old_cbch_msg.cnt))
+  {
+    ALR_TRACE_CB ("remove msg");
+    ALR_TRACE_CB_MSGHEAD (&pcbch->old_cbch_msg.header[i]);
+
+    /*
+     * decrement number of stored messages.
+     */
+    pcbch->old_cbch_msg.cnt--;
+    memmove (&pcbch->old_cbch_msg.header[i],
+             &pcbch->old_cbch_msg.header[i+1],
+             (pcbch->old_cbch_msg.cnt-i) * sizeof(T_CBMSG_HEADER));
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_create_schedule_map     |
++--------------------------------------------------------------------+
+
+  PURPOSE : Creation of a schedule map.
+
+*/
+LOCAL void cb_create_schedule_map (UBYTE old_cb_msg)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE  extended = pcbch->msg_is_extended;
+  UBYTE* msg_ptr;
+
+  /*
+   * Store begin and end slot number
+   */
+  pcbch->begin_schedule [extended] = (UBYTE)(pcbch->msg [0] & 0x3F);
+  pcbch->end_schedule   [extended] = pcbch->msg [1];
+
+  /*
+   * clear schedule bitmap
+   */
+  pcbch->schedule_length[extended] = 0;
+  memset (&pcbch->schedule_map[extended][0], 0,
+        2*sizeof (pcbch->schedule_map[extended][0]));
+  /*
+   * Check all new entries,
+   * msg_ptr to first message description
+   */
+  msg_ptr = &pcbch->msg[8];
+
+  msg_ptr = cb_create_schedule_entries (msg_ptr, 1);
+
+  if (old_cb_msg)
+  {
+    cb_create_schedule_entries (msg_ptr, FALSE);
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_create_schedule_entries |
++--------------------------------------------------------------------+
+
+  PURPOSE : Creation of schedule entries.
+
+*/
+LOCAL UBYTE* cb_create_schedule_entries (UBYTE* msg_ptr, BOOL flag)
+{
+  GET_INSTANCE_DATA;
+  unsigned    i;
+  BOOL        result;
+  UBYTE       x;
+  USHORT      msg_id;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE       extended = pcbch->msg_is_extended;
+
+  pcbch->last_slot_read[extended] = 0;
+  for (i=0; i < pcbch->end_schedule[extended]; i++)
+  {
+    result = (pcbch->msg [2 + ((i+1)>>3)] & (1 <<(8-((i+1)&7))));
+
+    ALR_TRACE_CB_SCHEDULE(i+1,result);
+
+    if ((flag AND result) OR (!flag AND !result))
+    {
+      /*
+       * result and bit are set, that means the msg:
+       *  - was not send during the previous schedule period
+       *  - or the msg was sent unscheduled during the last period
+       *  - or is free of charge, reading advised
+       * result and bit are both not set , that means the msg:
+       *  - the msg doesn't match the above
+       *  - these msgs are read only during the first 2 schedule periods
+       */
+      if (*msg_ptr & 0x80)
+      {
+        /*
+         * First transmission of an SMSCB within the
+         * Schedule Period
+         */
+
+        msg_id = (UBYTE)((*msg_ptr) & 0x7F);
+        msg_ptr++;
+        msg_id = (USHORT)(msg_id + *msg_ptr);
+        if (cb_check_message_id (msg_id))
+        {
+          /*
+           * Message Identifier is expected
+           * then set slot bit in schedule map
+           */
+          pcbch->schedule_map[extended][i>>5] |= 1 << (i&31);
+          if( (i+1) >= pcbch->begin_schedule[extended] )
+          {
+            pcbch->schedule_length[extended]++;
+            pcbch->last_slot_read[extended] = (i+1);
+          }
+        }
+      }
+      else
+      {
+        if ((*msg_ptr & 0xC0) EQ 0)
+        {
+          /*
+           * Retransmission indication
+           * Extract original message slot number
+           */
+          x = (UBYTE)(*msg_ptr & 0x3F);
+          if (x)
+          {
+            x--;
+            if (pcbch->schedule_map[extended][x>>5] & (1 << (x&31)) )
+            {
+              /*
+               * original message will be read, then set also
+               * repetition of message in schedule map
+               */
+              pcbch->schedule_map[extended][i>>5] |= 1 << (i&31);
+              if( (i+1) >= pcbch->begin_schedule[extended] )
+              {
+                pcbch->schedule_length[extended]++;
+                pcbch->last_slot_read[extended] = (i+1);
+              }
+            }
+          }
+        }
+        else
+        {
+          if (*msg_ptr EQ 0x41)
+          {
+            /*
+             * Free Message Slot, reading advised
+             * Set bit in schedule map
+             */
+            pcbch->schedule_map[extended][i>>5] |= 1 << (i&31);
+            if( (i+1) >= pcbch->begin_schedule[extended] )
+            {
+              pcbch->schedule_length[extended]++;
+              pcbch->last_slot_read[extended] = (i+1);
+            }
+          }
+        }
+      }
+      /*
+       * increment message description pointer
+       */
+      msg_ptr++;
+    }
+  }
+  return msg_ptr;
+}
+
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : cb_next_scheduled_msg      |
++--------------------------------------------------------------------+
+
+  PURPOSE : Looks for end of scheduling period.
+
+*/
+LOCAL void cb_next_scheduled_msg(void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+  UBYTE extended = pcbch->msg_is_extended;
+
+  if ((get_cbch_state(extended)) EQ CBCH_DRX )
+  {
+    if( pcbch->schedule_length[extended] EQ 0 )
+    {
+      /*
+        * instead of the scheduled SCHEDULE message
+        * an invalid message has been received.
+        * Restarting with NO DRX mode
+        */
+      set_cbch_state (extended, CBCH_NO_DRX);
+      cb_read_cbch ((UBYTE)(CBCH_NO_SCHED | extended));
+      return;
+    }
+    pcbch->schedule_length[extended]--;
+
+    if(pcbch->schedule_length[extended] EQ 0)
+    {
+     /*
+       * clear schedule map
+       * all message slots have been read
+       *
+       * NO need to reconfigure L1 to re-read schedule message 
+       * that follows slot 48
+       */
+      memset (&pcbch->schedule_map[extended][0], 0,
+        2*sizeof (pcbch->schedule_map[extended][0]));
+      TRACE_EVENT("Scheduled Schedule message expected");
+
+    }
+  }
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : get_cbch_state      |
++--------------------------------------------------------------------+
+
+  PURPOSE : Returns the state of STATE_EXT_CBCH or STATE_NORMAL_CBCH
+                   depending upon the input parameter "extended"
+
+*/
+
+UBYTE get_cbch_state( UBYTE extended)
+{
+  GET_INSTANCE_DATA;
+  if( extended)
+    return GET_STATE(STATE_EXT_CBCH);
+  else
+    return GET_STATE(STATE_NORMAL_CBCH);
+}
+
+/*
++--------------------------------------------------------------------+
+| PROJECT : GSM-PS (6103)       MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE : set_cbch_state      |
++--------------------------------------------------------------------+
+
+  PURPOSE : Sets  the state of STATE_EXT_CBCH or STATE_NORMAL_CBCH
+                   depending upon the input parameter "extended"
+
+*/
+
+void set_cbch_state( UBYTE extended, UBYTE new_state)
+{
+  GET_INSTANCE_DATA;
+  if(extended)
+  {
+    SET_STATE(STATE_EXT_CBCH,new_state);
+  }
+  else
+    SET_STATE(STATE_NORMAL_CBCH,new_state);
+}
+
+
+#if defined(FF_HOMEZONE)
+GLOBAL void cb_tim_homezone (void)
+{
+  GET_INSTANCE_DATA;
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  if (pcbch->homezone EQ CBCH_HZ_IDLE)
+  {
+    if (GET_STATE(STATE_MA) EQ MA_IDLE)
+    {
+      ALR_TRACE_CB ("call cb_start()");
+      cb_start ();
+    }
+    else
+    {
+      TIMERSTART (TIM_HOMEZONE, 1000);
+    }
+  }
+  else if (pcbch->homezone EQ CBCH_HZ_PENDING)
+  {
+    /*
+     * mark as received, indicate error, stop CBCH reading
+     */
+    ALR_TRACE_CB ("cb_ind_hz_err()");
+    pcbch->homezone = CBCH_HZ_RECEIVED;
+#if defined(INDICATE_HZ_ERROR)
+    cb_ind_hz_err ();
+#endif  /* INDICATE_HZ_ERROR */
+    if (    (pcbch->modus EQ NOT_PRESENT_8BIT)
+        AND (!pcbch->sat_enabled))
+      cb_stop ();
+  }
+}
+
+LOCAL UBYTE cb_check_homezone (UBYTE length)
+{
+  GET_INSTANCE_DATA;
+  UBYTE  result = FALSE;/* no special handling of homezone CBCH message */
+  T_CBCH_DATA *pcbch = &alr_data->cbch_data;
+
+  if (pcbch->homezone EQ CBCH_HZ_PENDING)
+  {
+    T_CBMSG_HEADER  *p_cbh;
+    p_cbh = (T_CBMSG_HEADER*)(&pcbch->msg[0]);
+
+    if (    (CB_MESSAGE_ID (p_cbh) EQ pcbch->msg_hz_id)
+        AND (CB_DCS (p_cbh)        EQ pcbch->dcs_hz_id)
+       )
+    {
+      /* one-time request of homezone CBCH message after cell reselection */
+      TIMERSTOP (TIM_HOMEZONE);
+      pcbch->homezone = CBCH_HZ_RECEIVED;
+      ALR_TRACE_CB_MSGHEAD (p_cbh);
+      ALR_TRACE_CB ("homezone msg received");
+      cb_ind (length);
+      result = TRUE;
+
+      if (    (pcbch->modus EQ NOT_PRESENT_8BIT)
+          AND (!pcbch->sat_enabled))
+      {
+        ALR_TRACE_CB ("no other msg req.");
+        cb_stop ();
+      }
+      else
+        cb_stop_next_blocks ();
+    }
+  }
+
+  return result;
+}
+#endif  /* FF_HOMEZONE */
+
+/*
++--------------------------------------------------------------------+
+| PROJECT :                     MODULE  : ALR_CBCH                   |
+| STATE   : code                ROUTINE  : cb_alr_trace_msghead      |
++--------------------------------------------------------------------+
+
+PURPOSE : Function to replace the ALR_TRACE_CB_MSGHEAD macro.
+
+*/
+
+/* Implements measures 2,3,4 */
+LOCAL void cb_alr_trace_msghead (T_CBMSG_HEADER *ph)
+{
+  ALR_TRACE_CB ("cb_alr_trace_msghead()");
+  if (CB_MSG_CODE(ph) < 1000) 
+  {
+    TRACE_EVENT_P7("CBCH ID=%3u, gs=%u, msg=%4u, upd=%u, dcs=%02x, p=%u/%u",
+                    CB_MESSAGE_ID(ph), CB_GS_CODE(ph),
+                    CB_MSG_CODE(ph), CB_UPDATE_NO(ph),
+                    CB_DCS(ph), CB_PAGE(ph), CB_PAGETOTAL(ph));
+  }
+  else
+  {
+    TRACE_EVENT_P7("CBCH ID=%3u, gs=%u, msg=%04x, upd=%u, dcs=%02x, p=%u/%u",
+                    CB_MESSAGE_ID(ph), CB_GS_CODE(ph),
+                    CB_MSG_CODE(ph), CB_UPDATE_NO(ph),
+                    CB_DCS(ph), CB_PAGE(ph), CB_PAGETOTAL(ph));
+  }
+}
+#endif