diff options
author | Andreas.Eversberg <jolly@eversberg.eu> | 2010-05-06 08:48:24 +0000 |
---|---|---|
committer | Andreas.Eversberg <jolly@eversberg.eu> | 2010-05-06 08:48:24 +0000 |
commit | 2b7d2ed446c9252d6dd7c6a834adb9eb40db1880 (patch) | |
tree | 4174018304667fbb1abad3e8fd50b9f581a853e1 /src/host/layer23/src/gsm322.c | |
parent | 7c5b9ea2880ca7e347dd31abedd4418e57493d50 (diff) |
- Fixes on MM, RR, cell selection, plmn search processes.
-> Cell selection now requires only one frequency to be scanned, if BA list
of that PLMN is known.
Diffstat (limited to 'src/host/layer23/src/gsm322.c')
-rwxr-xr-x | src/host/layer23/src/gsm322.c | 171 |
1 files changed, 146 insertions, 25 deletions
diff --git a/src/host/layer23/src/gsm322.c b/src/host/layer23/src/gsm322.c index 2a9f3bdd..909e30e8 100755 --- a/src/host/layer23/src/gsm322.c +++ b/src/host/layer23/src/gsm322.c @@ -44,6 +44,9 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any); static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg); +//#define SINGLE + +#ifdef SINGLE #warning HACK to stay on one channel static int already = 0; int l1ctl_tx_ccch_req_(struct osmocom_ms *ms, uint16_t arfcn) @@ -53,9 +56,12 @@ int l1ctl_tx_ccch_req_(struct osmocom_ms *ms, uint16_t arfcn) already = 1; return l1ctl_tx_ccch_req(ms, arfcn); } - ms->cellsel.ccch_active = 1; + ms->cellsel.ccch_sync = 1; return 0; } +#else +#define l1ctl_tx_ccch_req_ l1ctl_tx_ccch_req +#endif /* * notes @@ -987,6 +993,7 @@ static int gsm322_a_loss_of_radio(struct osmocom_ms *ms, struct msgb *msg) struct gsm322_plmn *plmn = &ms->plmn; struct gsm322_cellsel *cs = &ms->cellsel; int found; + struct msgb *nmsg; /* any PLMN available */ found = gsm322_cs_select(ms, 0); @@ -1008,6 +1015,12 @@ static int gsm322_a_loss_of_radio(struct osmocom_ms *ms, struct msgb *msg) new_a_state(plmn, GSM322_A4_WAIT_FOR_PLMN); + /* Tell cell selection process to handle "no cell found". */ + nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND); + if (!nmsg) + return -ENOMEM; + gsm322_cs_sendmsg(ms, nmsg); + return 0; } @@ -1523,7 +1536,7 @@ static int gsm322_cs_scan(struct osmocom_ms *ms) gsm322_plmn_sendmsg(ms, nmsg); /* re-tune back to current VPLMN */ - cs->ccch_active = 0; + cs->ccch_sync = 0; l1ctl_tx_ccch_req_(ms, cs->arfcn); return 0; @@ -1532,6 +1545,7 @@ static int gsm322_cs_scan(struct osmocom_ms *ms) /* if all frequencies have been searched */ if (!weight) { struct msgb *nmsg; +#if 0 int found, any = 0; LOGP(DCS, LOGL_INFO, "All frequencies scanned.\n"); @@ -1552,7 +1566,7 @@ static int gsm322_cs_scan(struct osmocom_ms *ms) /* tune */ cs->arfcn = found; cs->si = cs->list[cs->arfcn].sysinfo; - cs->ccch_active = 0; + cs->ccch_sync = 0; l1ctl_tx_ccch_req_(ms, cs->arfcn); /* selected PLMN (manual) or any PLMN (auto) */ @@ -1588,20 +1602,23 @@ static int gsm322_cs_scan(struct osmocom_ms *ms) cs->sel_mcc = cs->si->mcc; cs->sel_mnc = cs->si->mnc; cs->sel_lac = cs->si->lac; + cs->sel_id = cs->si->cell_id; /* tell CS process about available cell */ - nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_FOUND); LOGP(DCS, LOGL_INFO, "Cell available.\n"); + nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_FOUND); } else { +#endif /* unset selected cell */ cs->selected = 0; memset(&cs->sel_si, 0, sizeof(cs->sel_si)); - cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0; + cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id + = 0; /* tell CS process about no cell available */ - nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND); LOGP(DCS, LOGL_INFO, "No cell available.\n"); - } + nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND); +// } if (!nmsg) return -ENOMEM; gsm322_c_event(ms, nmsg); @@ -1616,9 +1633,12 @@ static int gsm322_cs_scan(struct osmocom_ms *ms) /* Tune to frequency for a while, to receive broadcasts. */ cs->arfcn = weight & 1023; - LOGP(DCS, LOGL_INFO, "Scanning frequency %d.\n", cs->arfcn); - cs->ccch_active = 0; + LOGP(DCS, LOGL_INFO, "Scanning frequency %d (rxlev %d).\n", cs->arfcn, + cs->list[cs->arfcn].rxlev_db); + cs->ccch_sync = 0; l1ctl_tx_ccch_req_(ms, cs->arfcn); +// cs->tune_retry = 0; + start_cs_timer(cs, ms->support.sync_to, 0); /* Allocate/clean system information. */ if (cs->list[cs->arfcn].sysinfo) @@ -1643,6 +1663,9 @@ static int gsm322_cs_store(struct osmocom_ms *ms) struct gsm322_cellsel *cs = &ms->cellsel; struct gsm_subscriber *subscr = &ms->subscr; struct gsm48_sysinfo *s = cs->si; + struct gsm322_plmn *plmn = &ms->plmn; + struct msgb *nmsg; + int found, any = 0; if (cs->state != GSM322_C2_STORED_CELL_SEL && cs->state != GSM322_C1_NORMAL_CELL_SEL @@ -1691,8 +1714,6 @@ static int gsm322_cs_store(struct osmocom_ms *ms) /* special prositive case for HPLMN search */ if (cs->state == GSM322_HPLMN_SEARCH && s->mcc == subscr->mcc && s->mnc == subscr->mnc) { - struct msgb *nmsg; - nmsg = gsm322_msgb_alloc(GSM322_EVENT_HPLMN_FOUND); LOGP(DCS, LOGL_INFO, "HPLMN cell available.\n"); if (!nmsg) @@ -1702,8 +1723,72 @@ static int gsm322_cs_store(struct osmocom_ms *ms) return 0; } - /* tune to next cell */ - return gsm322_cs_scan(ms); + /* just see, if we search for any cell */ + if (cs->state == GSM322_C6_ANY_CELL_SEL + || cs->state == GSM322_C8_ANY_CELL_RESEL + || cs->state == GSM322_C9_CHOOSE_ANY_CELL) + any = 1; + + found = gsm322_cs_select(ms, any); + + /* if not found */ + if (found < 0) { + LOGP(DCS, LOGL_INFO, "Cell not suitable and allowable.\n"); + /* tune to next cell */ + return gsm322_cs_scan(ms); + } + + LOGP(DCS, LOGL_INFO, "Tune to frequency %d.\n", found); + /* tune */ + cs->arfcn = found; + cs->si = cs->list[cs->arfcn].sysinfo; + cs->ccch_sync = 0; + l1ctl_tx_ccch_req_(ms, cs->arfcn); + + /* selected PLMN (manual) or any PLMN (auto) */ + switch (plmn->mode) { + case PLMN_MODE_AUTO: + if (plmn->state == GSM322_A4_WAIT_FOR_PLMN) { + /* PLMN becomes available */ + nmsg = gsm322_msgb_alloc( + GSM322_EVENT_PLMN_AVAIL); + if (!nmsg) + return -ENOMEM; + gsm322_plmn_sendmsg(ms, nmsg); + } + break; + case PLMN_MODE_MANUAL: + if (plmn->state == GSM322_M3_NOT_ON_PLMN + && gsm322_is_plmn_avail(cs, plmn->mcc, + plmn->mnc)) { + /* PLMN becomes available */ + nmsg = gsm322_msgb_alloc( + GSM322_EVENT_PLMN_AVAIL); + if (!nmsg) + return -ENOMEM; + gsm322_plmn_sendmsg(ms, nmsg); + } + break; + } + + /* set selected cell */ + cs->selected = 1; + cs->sel_arfcn = cs->arfcn; + memcpy(&cs->sel_si, cs->si, sizeof(cs->sel_si)); + cs->sel_mcc = cs->si->mcc; + cs->sel_mnc = cs->si->mnc; + cs->sel_lac = cs->si->lac; + cs->sel_id = cs->si->cell_id; + + /* tell CS process about available cell */ + LOGP(DCS, LOGL_INFO, "Cell available.\n"); + nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_FOUND); + if (!nmsg) + return -ENOMEM; + gsm322_c_event(ms, nmsg); + msgb_free(nmsg); + + return 0; } /* process system information when returing to idle mode */ @@ -1789,12 +1874,18 @@ static int gsm322_store_ba_list(struct gsm322_cellsel *cs, /* process system information during camping on a cell */ static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg) { + struct gsm48_rrlayer *rr = &ms->rrlayer; struct gsm322_cellsel *cs = &ms->cellsel; struct gsm48_sysinfo *s = cs->si; struct gsm_subscriber *subscr = &ms->subscr; struct gsm322_msg *gm = (struct gsm322_msg *) msg->data; struct msgb *nmsg; + if (rr->state != GSM48_RR_ST_IDLE) { + LOGP(DCS, LOGL_INFO, "Ignoring in dedicated mode.\n"); + return -EBUSY; + } + /* Store BA if we have full system info about cells and neigbor cells. * Depending on the extended bit in the channel description, * we require more or less system informations about neighbor cells @@ -1861,13 +1952,18 @@ static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg) } } - /* check if MCC, MNC, LAC changes */ + /* check if MCC, MNC, LAC, cell ID changes */ if (cs->sel_mcc != s->mcc || cs->sel_mnc != s->mnc || cs->sel_lac != s->lac) { LOGP(DCS, LOGL_NOTICE, "Cell changes location area. " "This is not good!\n"); goto trigger_resel; } + if (cs->sel_id != s->cell_id) { + LOGP(DCS, LOGL_NOTICE, "Cell changes cell ID. " + "This is not good!\n"); + goto trigger_resel; + } return 0; } @@ -1929,6 +2025,23 @@ static void gsm322_cs_timeout(void *arg) struct osmocom_ms *ms = cs->ms; LOGP(DCS, LOGL_INFO, "Cell selection timer has fired.\n"); + + /* if we have no lock, we retry */ + if (!cs->ccch_sync) { +#if 0 + if (++cs->tune_retry < 4) { + LOGP(DCS, LOGL_INFO, "No lock, retrying frequency %d.\n", cs->arfcn); + start_cs_timer(cs, ms->support.sync_to, 0); + l1ctl_tx_ccch_req_(ms, cs->arfcn); + return; + } + LOGP(DCS, LOGL_INFO, "No lock, after trying %d times.\n", cs->tune_retry); +#else + LOGP(DCS, LOGL_INFO, "Sync timeout.\n"); +#endif + } else + LOGP(DCS, LOGL_INFO, "Read timeout.\n"); + LOGP(DCS, LOGL_INFO, "Scan frequency %d: Cell not found. (rxlev=%d)\n", cs->arfcn, cs->list[cs->arfcn].rxlev_db); @@ -1950,7 +2063,7 @@ static void gsm322_cs_timeout(void *arg) * power scan process */ -/* search for block of unscanned freqeuncies and start scanning */ +/* search for block of unscanned frequencies and start scanning */ static int gsm322_cs_powerscan(struct osmocom_ms *ms) { struct gsm322_cellsel *cs = &ms->cellsel; @@ -1975,8 +2088,10 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms) } } +#ifdef SINGLE #warning testing if (already) s = -1; +#endif #if 0 cs->list[ms->test_arfcn].rxlev_db = -50; cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER; @@ -2049,7 +2164,7 @@ s = -1; break; } - LOGP(DCS, LOGL_INFO, "Scanning frequecies. (%d..%d)\n", s, e); + LOGP(DCS, LOGL_INFO, "Scanning frequencies. (%d..%d)\n", s, e); /* start scan on radio interface */ cs->powerscan = 1; @@ -2096,9 +2211,15 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal, case S_L1CTL_CCCH_RESP: ms = signal_data; cs = &ms->cellsel; - if (!cs->ccch_active) { + if (!cs->ccch_sync) { LOGP(DCS, LOGL_INFO, "Channel activated.\n"); - cs->ccch_active = 1; + stop_cs_timer(cs); + cs->ccch_sync = 1; + + /* in dedicated mode */ + if (ms->rrlayer.state == GSM48_RR_ST_CONN_PEND) + return gsm48_rr_tx_rand_acc(ms, NULL); + /* set timer for reading BCCH */ if (cs->state == GSM322_C2_STORED_CELL_SEL || cs->state == GSM322_C1_NORMAL_CELL_SEL @@ -2147,7 +2268,7 @@ static int gsm322_c_hplmn_search(struct osmocom_ms *ms, struct msgb *msg) /* unset selected cell */ cs->selected = 0; memset(&cs->sel_si, 0, sizeof(cs->sel_si)); - cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0; + cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0; /* start power scan */ return gsm322_cs_powerscan(ms); @@ -2172,7 +2293,7 @@ static int gsm322_c_stored_cell_sel(struct osmocom_ms *ms, struct gsm322_ba_list /* unset selected cell */ cs->selected = 0; memset(&cs->sel_si, 0, sizeof(cs->sel_si)); - cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0; + cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0; /* start power scan */ return gsm322_cs_powerscan(ms); @@ -2204,7 +2325,7 @@ static int gsm322_c_normal_cell_sel(struct osmocom_ms *ms, struct msgb *msg) /* unset selected cell */ cs->selected = 0; memset(&cs->sel_si, 0, sizeof(cs->sel_si)); - cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0; + cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0; /* start power scan */ return gsm322_cs_powerscan(ms); @@ -2246,7 +2367,7 @@ static int gsm322_c_any_cell_sel(struct osmocom_ms *ms, struct msgb *msg) /* unset selected cell */ cs->selected = 0; memset(&cs->sel_si, 0, sizeof(cs->sel_si)); - cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0; + cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0; /* start power scan */ return gsm322_cs_powerscan(ms); @@ -2366,7 +2487,7 @@ if we return from dedicated mode and we have a ba range, we can use that for cel /* unset selected cell */ cs->selected = 0; memset(&cs->sel_si, 0, sizeof(cs->sel_si)); - cs->sel_mcc = cs->sel_mnc = cs->sel_lac = 0; + cs->sel_mcc = cs->sel_mnc = cs->sel_lac = cs->sel_id = 0; /* start power scan */ return gsm322_cs_powerscan(ms); @@ -2460,7 +2581,7 @@ static int gsm322_c_conn_mode_1(struct osmocom_ms *ms, struct msgb *msg) /* be sure to go to current camping frequency on return */ LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn); - cs->ccch_active = 0; + cs->ccch_sync = 0; l1ctl_tx_ccch_req_(ms, cs->arfcn); cs->si = cs->list[cs->arfcn].sysinfo; @@ -2478,7 +2599,7 @@ static int gsm322_c_conn_mode_2(struct osmocom_ms *ms, struct msgb *msg) /* be sure to go to current camping frequency on return */ LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn); - cs->ccch_active = 0; + cs->ccch_sync = 0; l1ctl_tx_ccch_req_(ms, cs->arfcn); cs->si = cs->list[cs->arfcn].sysinfo; |