#include <osmocore/talloc.h>
#include <osmocore/utils.h>
#include <osmocore/gsm48.h>
+#include <osmocore/signal.h>
#include <osmocom/logging.h>
#include <osmocom/l1ctl.h>
#include <osmocom/file.h>
#include <osmocom/osmocom_data.h>
+#include <osmocom/networks.h>
extern void *l23_ctx;
static int gsm322_cs_select(struct osmocom_ms *ms, int any);
static int gsm322_m_switch_on(struct osmocom_ms *ms, struct msgb *msg);
+
+#warning HACK to stay on one channel
+int l1ctl_tx_ccch_req_(struct osmocom_ms *ms, uint16_t arfcn)
+{
+ static int already = 0;
+
+ if (!already) {
+ already = 1;
+ return l1ctl_tx_ccch_req(ms, arfcn);
+ }
+ ms->cellsel.ccch_active = 1;
+ return 0;
+}
+
/*
* notes
*/
return ba_found;
}
+/* search available PLMN */
+int gsm322_is_plmn_avail(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc)
+{
+ int i;
+
+ for (i = 0; i <= 1023; i++) {
+ if (cs->list[i].sysinfo->mcc == mcc
+ && cs->list[i].sysinfo->mnc == mnc)
+ return 1;
+ }
+
+ return 0;
+}
+
+/* del forbidden LA */
/*
* timer
*/
stop_cs_timer(cs);
/* stop scanning of power measurement */
+ if (cs->powerscan) {
#ifdef TODO
- if (cs->powerscan)
stop power scanning
#endif
+ cs->powerscan = 0;
+ }
cs->state = state;
}
/* search if network has multiple cells */
found = NULL;
llist_for_each_entry(temp, &temp_list, entry) {
- if (temp->mcc == cs->list[i].mcc
- && temp->mnc == cs->list[i].mnc)
+ if (temp->mcc == cs->list[i].sysinfo->mcc
+ && temp->mnc == cs->list[i].sysinfo->mnc)
found = temp;
break;
}
temp = talloc_zero(l23_ctx, struct gsm322_plmn_list);
if (!temp)
return -ENOMEM;
- temp->mcc = cs->list[i].mcc;
- temp->mnc = cs->list[i].mnc;
+ temp->mcc = cs->list[i].sysinfo->mcc;
+ temp->mnc = cs->list[i].sysinfo->mnc;
temp->rxlev_db = cs->list[i].rxlev_db;
llist_add_tail(&temp->entry, &temp_list);
}
}
/* select first PLMN in list */
- plmn->mcc = cs->list[found].mcc;
- plmn->mnc = cs->list[found].mnc;
+ plmn->mcc = cs->list[found].sysinfo->mcc;
+ plmn->mnc = cs->list[found].sysinfo->mnc;
- LOGP(DPLMN, LOGL_INFO, "PLMN available (mcc=%03d mnc=%02d)\n",
- plmn->mcc, plmn->mnc);
+ LOGP(DPLMN, LOGL_INFO, "PLMN available (mcc=%03d mnc=%02d %s, %s)\n",
+ plmn->mcc, plmn->mnc,
+ gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
/* indicate New PLMN */
nmsg = gsm322_msgb_alloc(GSM322_EVENT_NEW_PLMN);
}
LOGP(DPLMN, LOGL_INFO, "Selecting PLMN from list. (%02d: mcc=%03d "
- "mnc=%02d\n", plmn->plmn_curr, plmn_first->mcc,
- plmn_first->mnc);
+ "mnc=%02d %s, %s)\n", plmn->plmn_curr, plmn_first->mcc,
+ plmn_first->mnc, gsm_get_mcc(plmn_first->mcc),
+ gsm_get_mnc(plmn_first->mcc, plmn_first->mnc));
/* set current network */
plmn->mcc = plmn_first->mcc;
LOGP(DPLMN, LOGL_INFO, "Selecting PLMN from list. (%02d: mcc=%03d "
- "mnc=%02d\n", plmn->plmn_curr, plmn_next->mcc,
- plmn_next->mnc);
+ "mnc=%02d %s, %s)\n", plmn->plmn_curr, plmn_next->mcc,
+ plmn_next->mnc,
+ gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
/* set next network */
plmn->mcc = plmn_next->mcc;
/* if PLMN in list */
if (found >= 0) {
- LOGP(DPLMN, LOGL_INFO, "PLMN available (mcc=%03d mnc=%02d)\n",
- cs->list[found].mcc, cs->list[found].mnc);
+ LOGP(DPLMN, LOGL_INFO, "PLMN available (mcc=%03d mnc=%02d "
+ "%s, %s)\n", cs->list[found].sysinfo->mcc,
+ cs->list[found].sysinfo->mnc,
+ gsm_get_mcc(cs->list[found].sysinfo->mcc),
+ gsm_get_mnc(cs->list[found].sysinfo->mcc,
+ cs->list[found].sysinfo->mnc));
return gsm322_a_sel_first_plmn(ms, msg);
}
plmn->mcc = subscr->plmn_mcc;
plmn->mnc = subscr->plmn_mnc;
- LOGP(DPLMN, LOGL_INFO, "Use RPLMN (mcc=%03d mnc=%02d)\n",
- plmn->mcc, plmn->mnc);
+ LOGP(DPLMN, LOGL_INFO, "Use RPLMN (mcc=%03d mnc=%02d "
+ "%s, %s)\n", plmn->mcc, plmn->mnc,
+ gsm_get_mcc(plmn->mcc),
+ gsm_get_mnc(plmn->mcc, plmn->mnc));
new_a_state(plmn, GSM322_A1_TRYING_RPLMN);
return 0;
}
+static int gsm322_a_sim_insert(struct osmocom_ms *ms, struct msgb *msg)
+{
+ LOGP(DPLMN, LOGL_INFO, "SIM already inserted when switched on.\n");
+ return 0;
+}
+
/* SIM is removed */
static int gsm322_a_sim_removed(struct osmocom_ms *ms, struct msgb *msg)
{
static int gsm322_a_sel_manual(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm322_plmn *plmn = &ms->plmn;
+ struct msgb *nmsg;
/* restart state machine */
gsm322_a_switch_off(ms, msg);
plmn->mode = PLMN_MODE_MANUAL;
gsm322_m_switch_on(ms, msg);
+ nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_USER_PLMN_SEL);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm48_mmevent_msg(ms, nmsg);
+
return 0;
}
/* if there is a registered PLMN */
if (subscr->plmn_valid) {
+ struct msgb *nmsg;
+
/* select the registered PLMN */
plmn->mcc = subscr->plmn_mcc;
plmn->mnc = subscr->plmn_mnc;
- LOGP(DPLMN, LOGL_INFO, "Use RPLMN (mcc=%03d mnc=%02d)\n",
- plmn->mcc, plmn->mnc);
+ LOGP(DPLMN, LOGL_INFO, "Use RPLMN (mcc=%03d mnc=%02d "
+ "%s, %s)\n", plmn->mcc, plmn->mnc,
+ gsm_get_mcc(plmn->mcc),
+ gsm_get_mnc(plmn->mcc, plmn->mnc));
new_m_state(plmn, GSM322_M1_TRYING_RPLMN);
+ /* indicate New PLMN */
+ nmsg = gsm322_msgb_alloc(GSM322_EVENT_NEW_PLMN);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_cs_sendmsg(ms, nmsg);
+
return 0;
}
return 0;
}
+static int gsm322_m_sim_insert(struct osmocom_ms *ms, struct msgb *msg)
+{
+ LOGP(DPLMN, LOGL_INFO, "SIM already inserted when switched on.\n");
+ return 0;
+}
+
/* SIM is removed */
static int gsm322_m_sim_removed(struct osmocom_ms *ms, struct msgb *msg)
{
static int gsm322_m_plmn_avail(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm322_plmn *plmn = &ms->plmn;
+ struct gsm322_cellsel *cs = &ms->cellsel;
new_m_state(plmn, GSM322_M1_TRYING_RPLMN);
+ if (cs->mcc != plmn->mcc || cs->mnc != plmn->mnc) {
+ struct msgb *nmsg;
+
+ LOGP(DPLMN, LOGL_INFO, "PLMN available, but currently not "
+ "selected, so start selection.\n");
+
+ /* indicate New PLMN */
+ nmsg = gsm322_msgb_alloc(GSM322_EVENT_NEW_PLMN);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_cs_sendmsg(ms, nmsg);
+ }
+
return 0;
}
{
struct gsm322_plmn *plmn = &ms->plmn;
struct gsm322_msg *gm = (struct gsm322_msg *) msg->data;
+ struct msgb *nmsg;
/* use user selection */
plmn->mcc = gm->mcc;
plmn->mnc = gm->mnc;
- LOGP(DPLMN, LOGL_INFO, "User selects PLMN. (mcc=%03d mnc=%02d)\n",
- plmn->mcc, plmn->mnc);
+ LOGP(DPLMN, LOGL_INFO, "User selects PLMN. (mcc=%03d mnc=%02d "
+ "%s, %s)\n", plmn->mcc, plmn->mnc,
+ gsm_get_mcc(plmn->mcc), gsm_get_mnc(plmn->mcc, plmn->mnc));
new_m_state(plmn, GSM322_M4_TRYING_PLMN);
+ /* indicate New PLMN */
+ nmsg = gsm322_msgb_alloc(GSM322_EVENT_NEW_PLMN);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm322_cs_sendmsg(ms, nmsg);
+
return 0;
}
static int gsm322_m_sel_auto(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm322_plmn *plmn = &ms->plmn;
+ struct msgb *nmsg;
/* restart state machine */
gsm322_m_switch_off(ms, msg);
plmn->mode = PLMN_MODE_AUTO;
gsm322_a_switch_on(ms, msg);
+ nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_USER_PLMN_SEL);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm48_mmevent_msg(ms, nmsg);
+
return 0;
}
{
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm_subscriber *subscr = &ms->subscr;
+ struct gsm48_sysinfo *s;
int i, found = -1, power = 0;
uint8_t flags, mask;
uint16_t acc_class;
/* loop through all scanned frequencies and select cell */
for (i = 0; i <= 1023; i++) {
cs->list[i].flags &= ~GSM322_CS_FLAG_TEMP_AA;
+ s = cs->list[i].sysinfo;
/* channel has no informations for us */
if ((cs->list[i].flags & mask) != flags) {
/* check C1 criteria not fullfilled */
// TODO: C1 is also dependant on power class and max power
- if (cs->list[i].rxlev_db < cs->list[i].min_db) {
+ if (cs->list[i].rxlev_db < s->rxlev_acc_min_db) {
LOGP(DCS, LOGL_INFO, "Skip frequency %d: C1 criteria "
"not met. (rxlev=%d < min=%d)\n", i,
- cs->list[i].rxlev_db, cs->list[i].min_db);
+ cs->list[i].rxlev_db, s->rxlev_acc_min_db);
continue;
}
&& (cs->list[i].flags & GSM322_CS_FLAG_FORBIDD)) {
LOGP(DCS, LOGL_INFO, "Skip frequency %d: Cell is in "
"list of forbidden LAs. (mcc=%03d mnc=%02d "
- "lai=%04x)\n", i, cs->list[i].mcc,
- cs->list[i].mnc, cs->list[i].lac);
+ "lai=%04x)\n", i, s->mcc, s->mnc, s->lac);
continue;
}
/* if we have no access to the cell and we don't override */
if (!subscr->acc_barr
- && !(acc_class & (cs->list[i].class_barr ^ 0xffff))) {
+ && !(acc_class & (s->class_barr ^ 0xffff))) {
LOGP(DCS, LOGL_INFO, "Skip frequency %d: Class is "
"barred for out access. (access=%04x "
- "barred=%04x)\n", i, acc_class,
- cs->list[i].class_barr);
+ "barred=%04x)\n", i, acc_class, s->class_barr);
continue;
}
cs->list[i].flags |= GSM322_CS_FLAG_TEMP_AA;
/* if we search a specific PLMN, but it does not match */
- if (!any && (cs->mcc != cs->list[i].mcc
- || cs->mnc != cs->list[i].mnc)) {
+ if (!any && (cs->mcc != s->mcc
+ || cs->mnc != s->mnc)) {
LOGP(DCS, LOGL_INFO, "Skip frequency %d: PLMN of cell "
"does not match target PLMN. (mcc=%03d "
- "mnc=%02d)\n", i, cs->list[i].mcc,
- cs->list[i].mnc);
+ "mnc=%02d)\n", i, s->mcc, s->mnc);
continue;
}
LOGP(DCS, LOGL_INFO, "Cell frequency %d: Cell found, (rxlev=%d "
- "mcc=%03d mnc=%02d lac=%04x)\n", i,
- cs->list[i].rxlev_db, cs->list[i].mcc, cs->list[i].mnc,
- cs->list[i].lac);
+ "mcc=%03d mnc=%02d lac=%04x %s, %s)\n", i,
+ cs->list[i].rxlev_db, s->mcc, s->mnc,
+ s->lac, gsm_get_mcc(s->mcc),
+ gsm_get_mnc(s->mcc, s->mnc));
/* find highest power cell */
if (found < 0 || cs->list[i].rxlev_db > power) {
}
}
+ gsm322_dump_sorted_plmn(ms);
+
if (found >= 0)
LOGP(DCS, LOGL_INFO, "Cell frequency %d selected.\n", found);
static int gsm322_cs_scan(struct osmocom_ms *ms)
{
struct gsm322_cellsel *cs = &ms->cellsel;
- struct gsm_subscriber *subscr = &ms->subscr;
- struct gsm48_sysinfo *s = &ms->sysinfo;
- struct gsm48_rrlayer *rr = &ms->rrlayer;
- int i;
+ int i, j;
uint8_t mask, flags;
- uint32_t max = 0, weight = cs->scan_state;
-
- if (rr->state != GSM48_RR_ST_IDLE) {
- LOGP(DCS, LOGL_FATAL, "This must only happen in IDLE mode, "
- "please fix!\n");
- return -EINVAL;
- }
-
- /* 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)
- return -ENOMEM;
- gsm322_plmn_sendmsg(ms, nmsg);
-
- return 0;
- }
+ uint32_t weight = 0, test = cs->scan_state;
/* search for strongest unscanned cell */
mask = GSM322_CS_FLAG_SUPPORT | GSM322_CS_FLAG_POWER
mask |= GSM322_CS_FLAG_BA;
flags = mask; /* all masked flags are requied */
for (i = 0; i <= 1023; i++) {
+ /* skip if band has enough frequencies scanned (3.2.1) */
+ for (j = 0; gsm_sup_smax[j].max; j++) {
+ if (gsm_sup_smax[j].end > gsm_sup_smax[j].start) {
+ if (gsm_sup_smax[j].start >= i
+ && gsm_sup_smax[j].end <= i)
+ break;
+ } else {
+ if (gsm_sup_smax[j].end <= i
+ || gsm_sup_smax[j].start >= i)
+ break;
+ }
+ }
+ if (gsm_sup_smax[j].max) {
+ if (gsm_sup_smax[j].temp == gsm_sup_smax[j].max)
+ continue;
+ }
+ /* search for unscanned frequency */
if ((cs->list[i].flags & mask) == flags) {
/* weight depends on the power level
* if it is the same, it depends on arfcn
*/
- weight = cs->list[i].rxlev_db + 128;
- weight = (weight << 16) | i;
- if (weight >= cs->scan_state)
+ test = cs->list[i].rxlev_db + 128;
+ test = (test << 16) | i;
+ if (test >= cs->scan_state)
continue;
- if (weight > max)
- max = weight;
+ if (test > weight)
+ weight = test;
}
}
cs->scan_state = weight;
+ if (!weight)
+ gsm322_dump_cs_list(ms);
+
/* special negative case for HPLMN search */
if (cs->state == GSM322_HPLMN_SEARCH && !weight) {
struct msgb *nmsg;
gsm322_plmn_sendmsg(ms, nmsg);
/* re-tune back to current VPLMN */
- l1ctl_tx_ccch_req(ms, cs->arfcn);
+ cs->ccch_active = 0;
+ l1ctl_tx_ccch_req_(ms, cs->arfcn);
return 0;
}
/* if found */
if (found >= 0) {
+ struct gsm322_plmn *plmn = &ms->plmn;
+
LOGP(DCS, LOGL_INFO, "Tune to frequency %d.\n", found);
/* tune */
cs->arfcn = found;
- l1ctl_tx_ccch_req(ms, cs->arfcn);
-
- /* Clear system information. */
- gsm48_sysinfo_init(ms);
+ cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->ccch_active = 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;
+ /* tell CS process about available cell */
nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_FOUND);
+ LOGP(DCS, LOGL_INFO, "Cell available.\n");
} else {
+ /* 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;
+
+ /* tell CS process about no cell available */
nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND);
LOGP(DCS, LOGL_INFO, "No cell available.\n");
}
if (!nmsg)
return -ENOMEM;
- gsm322_plmn_sendmsg(ms, nmsg);
+ gsm322_cs_sendmsg(ms, nmsg);
return 0;
}
/* Tune to frequency for a while, to receive broadcasts. */
cs->arfcn = weight & 1023;
LOGP(DCS, LOGL_INFO, "Scanning frequency %d.\n", cs->arfcn);
- l1ctl_tx_ccch_req(ms, cs->arfcn);
-
- /* Clear system information. */
- gsm48_sysinfo_init(ms);
-
- /* set timer for reading BCCH */
- start_cs_timer(cs, 4, 0); // TODO: timer depends on BCCH config
-
+ cs->ccch_active = 0;
+ l1ctl_tx_ccch_req_(ms, cs->arfcn);
+
+ /* Allocate system information. */
+ cs->list[cs->arfcn].sysinfo = talloc_zero(l23_ctx,
+ struct gsm48_sysinfo);
+ if (!cs->list[cs->arfcn].sysinfo)
+ exit(-ENOMEM);
+ cs->si = cs->list[cs->arfcn].sysinfo;
+
+ /* increase scan counter for each maximum scan range */
+ if (gsm_sup_smax[j].max)
+ gsm_sup_smax[j].temp++;
return 0;
}
static int gsm322_cs_store(struct osmocom_ms *ms)
{
struct gsm322_cellsel *cs = &ms->cellsel;
- struct gsm48_sysinfo *s = &ms->sysinfo;
+ struct gsm_subscriber *subscr = &ms->subscr;
int i = cs->scan_state & 1023;
+ struct gsm48_sysinfo *s = cs->list[i].sysinfo;
if (cs->state != GSM322_C2_STORED_CELL_SEL
&& cs->state != GSM322_C1_NORMAL_CELL_SEL
cs->list[i].flags |= GSM322_CS_FLAG_BARRED;
else
cs->list[i].flags &= ~GSM322_CS_FLAG_BARRED;
+
+#if 0
cs->list[i].min_db = s->rxlev_acc_min_db;
cs->list[i].class_barr = s->class_barr;
cs->list[i].max_pwr = s->ms_txpwr_max_ccch;
+#endif
/* store selected network */
if (s->mcc) {
+#if 0
cs->list[i].mcc = s->mcc;
cs->list[i].mnc = s->mnc;
cs->list[i].lac = s->lac;
+#endif
if (gsm322_is_forbidden_la(ms, s->mcc, s->mnc, s->lac))
cs->list[i].flags |= GSM322_CS_FLAG_FORBIDD;
LOGP(DCS, LOGL_INFO, "Scan frequency %d: Cell found. (rxlev=%d "
"mcc=%03d mnc=%02d lac=%04x)\n", i, cs->list[i].rxlev_db,
- cs->list[i].mcc, cs->list[i].mnc, cs->list[i].lac);
+ s->mcc, s->mnc, s->lac);
+
+ /* 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)
+ return -ENOMEM;
+ gsm322_plmn_sendmsg(ms, nmsg);
+
+ return 0;
+ }
/* tune to next cell */
return gsm322_cs_scan(ms);
struct gsm322_ba_list *gsm322_cs_sysinfo_sacch(struct osmocom_ms *ms)
{
struct gsm322_cellsel *cs = &ms->cellsel;
- struct gsm48_sysinfo *s = &ms->sysinfo;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm322_ba_list *ba = NULL;
int i;
uint8_t freq[128];
freq[i >> 3] |= (1 << (i & 7));
}
if (!!memcmp(freq, ba->freq, sizeof(freq))) {
- LOGP(DCS, LOGL_INFO, "New BA list (mcc=%d mnc=%d).\n",
- ba->mcc, ba->mnc);
+ LOGP(DCS, LOGL_INFO, "New BA list (mcc=%d mnc=%d "
+ "%s, %s).\n", ba->mcc, ba->mnc,
+ gsm_get_mcc(ba->mcc),
+ gsm_get_mnc(ba->mcc, ba->mnc));
memcpy(ba->freq, freq, sizeof(freq));
}
}
return ba;
}
+/* store BA whenever a system informations changes */
+static int gsm322_store_ba_list(struct gsm322_cellsel *cs,
+ struct gsm48_sysinfo *s)
+{
+ struct gsm322_ba_list *ba;
+ int i;
+ uint8_t freq[128];
+
+ /* find or create ba list */
+ ba = gsm322_find_ba_list(cs, s->mcc, s->mnc);
+ if (!ba) {
+ ba = talloc_zero(l23_ctx, struct gsm322_ba_list);
+ if (!ba)
+ return -ENOMEM;
+ ba->mcc = s->mcc;
+ ba->mnc = s->mnc;
+ llist_add_tail(&ba->entry, &cs->ba_list);
+ }
+ /* update ba list */
+ memset(freq, 0, sizeof(freq));
+ freq[cs->arfcn >> 3] |= (1 << (cs->arfcn & 7));
+ for (i = 0; i <= 1023; i++) {
+ if ((s->freq[i].mask &
+ (FREQ_TYPE_SERV | FREQ_TYPE_NCELL)))
+ freq[i >> 3] |= (1 << (i & 7));
+ }
+ if (!!memcmp(freq, ba->freq, sizeof(freq))) {
+ LOGP(DCS, LOGL_INFO, "New BA list (mcc=%d mnc=%d "
+ "%s, %s).\n", ba->mcc, ba->mnc,
+ gsm_get_mcc(ba->mcc),
+ gsm_get_mnc(ba->mcc, ba->mnc));
+ memcpy(ba->freq, freq, sizeof(freq));
+ }
+
+ return 0;
+}
+
/* process system information during camping on a cell */
static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm322_cellsel *cs = &ms->cellsel;
- struct gsm48_sysinfo *s = &ms->sysinfo;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm_subscriber *subscr = &ms->subscr;
struct gsm322_msg *gm = (struct gsm322_msg *) msg->data;
struct msgb *nmsg;
+ /* 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
+ */
+ if (s->mcc
+ && s->mnc
+ && (gm->sysinfo == GSM48_MT_RR_SYSINFO_1
+ || gm->sysinfo == GSM48_MT_RR_SYSINFO_2
+ || gm->sysinfo == GSM48_MT_RR_SYSINFO_2bis
+ || gm->sysinfo == GSM48_MT_RR_SYSINFO_2ter)
+ && s->si1
+ && s->si2
+ && (!s->nb_ext_ind_si2
+ || (s->si2bis && s->nb_ext_ind_si2 && !s->nb_ext_ind_si2bis)
+ || (s->si2bis && s->si2ter && s->nb_ext_ind_si2
+ && s->nb_ext_ind_si2bis)))
+ gsm322_store_ba_list(cs, s);
+
+ /* update sel_si, if all relevant system informations received */
+ if (s->si1 && s->si2 && s->si3
+ && (!s->nb_ext_ind_si2
+ || (s->si2bis && s->nb_ext_ind_si2 && !s->nb_ext_ind_si2bis)
+ || (s->si2bis && s->si2ter && s->nb_ext_ind_si2
+ && s->nb_ext_ind_si2bis))) {
+ if (cs->selected) {
+ LOGP(DCS, LOGL_INFO, "Selected sysinfo is updated.\n");
+ memcpy(&cs->sel_si, s, sizeof(cs->sel_si));
+ }
+ }
+
+ /* check for barred cell */
if (gm->sysinfo == GSM48_MT_RR_SYSINFO_1) {
/* check if cell becomes barred */
if (!subscr->acc_barr && s->cell_barr) {
}
/* check if cell access becomes barred */
if (!((subscr->acc_class & 0xfbff)
- & (cs->list[cs->arfcn].class_barr ^ 0xffff))) {
+ & (s->class_barr ^ 0xffff))) {
LOGP(DCS, LOGL_INFO, "Cell access becomes barred.\n");
goto trigger_resel;
}
static int gsm322_c_scan_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm322_cellsel *cs = &ms->cellsel;
- struct gsm48_rrlayer *rr = &ms->rrlayer;
- struct gsm48_sysinfo *s = &ms->sysinfo;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm322_msg *gm = (struct gsm322_msg *) msg->data;
- struct gsm322_ba_list *ba;
- int i;
- uint8_t freq[128];
-
- if (rr->state != GSM48_RR_ST_IDLE) {
- LOGP(DCS, LOGL_FATAL, "This must only happen in IDLE mode, "
- "please fix!\n");
- return -EINVAL;
- }
/* no sysinfo if we are not done with power scan */
if (cs->powerscan) {
&& (!s->nb_ext_ind_si2
|| (s->si2bis && s->nb_ext_ind_si2 && !s->nb_ext_ind_si2bis)
|| (s->si2bis && s->si2ter && s->nb_ext_ind_si2
- && s->nb_ext_ind_si2bis))) {
- /* find or create ba list */
- ba = gsm322_find_ba_list(cs, s->mcc, s->mnc);
- if (!ba) {
- ba = talloc_zero(l23_ctx, struct gsm322_ba_list);
- if (!ba)
- return -ENOMEM;
- ba->mcc = s->mcc;
- ba->mnc = s->mnc;
- llist_add_tail(&ba->entry, &cs->ba_list);
- }
- /* update ba list */
- memset(freq, 0, sizeof(freq));
- freq[cs->arfcn >> 3] |= (1 << (cs->arfcn & 7));
- for (i = 0; i <= 1023; i++) {
- if ((s->freq[i].mask &
- (FREQ_TYPE_SERV | FREQ_TYPE_NCELL)))
- freq[i >> 3] |= (1 << (i & 7));
- }
- if (!!memcmp(freq, ba->freq, sizeof(freq))) {
- LOGP(DCS, LOGL_INFO, "New BA list (mcc=%d mnc=%d).\n",
- ba->mcc, ba->mnc);
- memcpy(ba->freq, freq, sizeof(freq));
- }
- }
+ && s->nb_ext_ind_si2bis)))
+ gsm322_store_ba_list(cs, s);
/* all relevant system informations received */
if (s->si1 && s->si2 && s->si3
/* stop timer */
stop_cs_timer(cs);
+ gsm48_sysinfo_dump(ms, s);
+
/* store sysinfo and continue scan */
return gsm322_cs_store(ms);
}
/* remove system information */
cs->list[i].flags &= ~GSM322_CS_FLAG_SYSINFO;
+ if (cs->list[i].sysinfo) {
+ talloc_free(cs->list[i].sysinfo);
+ cs->list[i].sysinfo = NULL;
+ }
/* tune to next cell */
gsm322_cs_scan(ms);
static int gsm322_cs_powerscan(struct osmocom_ms *ms)
{
struct gsm322_cellsel *cs = &ms->cellsel;
- struct gsm48_rrlayer *rr = &ms->rrlayer;
int i, s = -1, e;
uint8_t mask, flags;
- if (rr->state != GSM48_RR_ST_IDLE) {
- LOGP(DCS, LOGL_FATAL, "This must only happen in IDLE mode, "
- "please fix!\n");
- return -EINVAL;
- }
-
again:
/* search for first frequency to scan */
mask = GSM322_CS_FLAG_SUPPORT | GSM322_CS_FLAG_POWER;
flags = GSM322_CS_FLAG_SUPPORT;
if (cs->state == GSM322_C2_STORED_CELL_SEL) {
+ LOGP(DCS, LOGL_FATAL, "Scanning power for stored BA list.\n");
mask |= GSM322_CS_FLAG_BA;
flags |= GSM322_CS_FLAG_BA;
- }
+ } else
+ LOGP(DCS, LOGL_FATAL, "Scanning power for all frequencies.\n");
for (i = 0; i <= 1023; i++) {
if ((cs->list[i].flags & mask) == flags) {
s = e = i;
}
}
+#warning testing
+cs->list[10].rxlev_db = -50;
+cs->list[10].flags |= GSM322_CS_FLAG_POWER;
+cs->list[10].flags |= GSM322_CS_FLAG_SIGNAL;
+s = -1;
/* if there is no more frequency, we can tune to that cell */
if (s < 0) {
int found = 0;
~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
+ if (cs->list[i].sysinfo) {
+ talloc_free(
+ cs->list[i].sysinfo);
+ cs->list[i].sysinfo = NULL;
+ }
}
goto again;
}
}
LOGP(DCS, LOGL_INFO, "Found %d frequencies.\n", found);
cs->scan_state = 0xffffffff; /* higher than high */
+ /* clear counter of scanned frequencies of each range */
+ for (i = 0; gsm_sup_smax[i].max; i++)
+ gsm_sup_smax[i].temp = 0;
return gsm322_cs_scan(ms);
}
LOGP(DCS, LOGL_INFO, "Scanning frequecies. (%d..%d)\n", s, e);
-#ifdef TODO
- start scan on radio interface
-
+ /* start scan on radio interface */
cs->powerscan = 1;
-
- also stop on state change
-
-#else
- printf("scan not supported... exitting\n");
- exit(-1);
-#endif
+ return l1ctl_tx_pm_req_range(ms, s, e);
}
-#ifdef TODO
+static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
+ void *handler_data, void *signal_data)
{
+ struct osmocom_ms *ms;
+ struct gsm322_cellsel *cs;
+ struct osmobb_meas_res *mr;
+ int i;
+ int8_t rxlev_db;
- LOGP(DCS, LOGL_INFO, "Found frequency %d.\n", i);
+ if (subsys != SS_L1CTL)
+ return 0;
- /* set power scan flag */
- cs->list[i].flags |= GSM322_CS_FLAG_POWER;
- if (...)
- cs->list[i].flags |= GSM322_CS_FLAG_SIGNAL;
+ switch (signal) {
+ case S_L1CTL_PM_RES:
+ mr = signal_data;
+ ms = mr->ms;
+ cs = &ms->cellsel;
+ if (!cs->powerscan)
+ return -EINVAL;
+ i = mr->band_arfcn & 1023;
+ rxlev_db = mr->rx_lev - 110;
+ cs->list[i].rxlev_db = rxlev_db;
+ cs->list[i].flags |= GSM322_CS_FLAG_POWER;
+ if (rxlev_db >= ms->support.min_rxlev_db) {
+ cs->list[i].flags |= GSM322_CS_FLAG_SIGNAL;
+ LOGP(DCS, LOGL_INFO, "Found signal (frequency %d "
+ "rxlev %d)\n", i, cs->list[i].rxlev_db);
+ }
+ break;
+ case S_L1CTL_PM_DONE:
+ LOGP(DCS, LOGL_INFO, "Done with power scanning range.\n");
+ ms = signal_data;
+ cs = &ms->cellsel;
+ if (!cs->powerscan)
+ return -EINVAL;
+ gsm322_cs_powerscan(ms);
+ break;
+ case S_L1CTL_CCCH_RESP:
+ ms = signal_data;
+ cs = &ms->cellsel;
+ if (!cs->ccch_active) {
+ LOGP(DCS, LOGL_INFO, "Channel activated.\n");
+ cs->ccch_active = 1;
+ /* set timer for reading BCCH */
+ if (cs->state == GSM322_C2_STORED_CELL_SEL
+ || cs->state == GSM322_C1_NORMAL_CELL_SEL
+ || cs->state == GSM322_C6_ANY_CELL_SEL
+ || cs->state == GSM322_C4_NORMAL_CELL_RESEL
+ || cs->state == GSM322_C8_ANY_CELL_RESEL
+ || cs->state == GSM322_C5_CHOOSE_CELL
+ || cs->state == GSM322_C9_CHOOSE_ANY_CELL)
+ start_cs_timer(cs, 8, 0);
+ // TODO: timer depends on BCCH config
+ }
+ break;
+ }
+ return 0;
}
-#endif
/*
* handler for cell selection process
/* mark all frequencies except our own BA to be scanned */
for (i = 0; i <= 1023; i++) {
if ((cs->list[i].flags & GSM322_CS_FLAG_SYSINFO)
- && !(cs->list[i].flags & GSM322_CS_FLAG_BA))
+ && !(cs->list[i].flags & GSM322_CS_FLAG_BA)) {
cs->list[i].flags &= ~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
+ if (cs->list[i].sysinfo) {
+ talloc_free(cs->list[i].sysinfo);
+ cs->list[i].sysinfo = NULL;
+ }
+ }
}
+ /* 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;
+
/* start power scan */
return gsm322_cs_powerscan(ms);
}
cs->list[i].flags &= ~GSM322_CS_FLAG_BA;
}
-#ifdef TODO
- remove this:
-#else
- /* use hacked frequency */
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER;
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_SIGNAL;
- cs->list[ms->test_arfcn].rxlev_db = -40;
-#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;
+
/* start power scan */
return gsm322_cs_powerscan(ms);
}
/* except for stored cell selection state, we weed to rescan ?? */
if (cs->state != GSM322_C2_STORED_CELL_SEL) {
- for (i = 0; i <= 1023; i++)
+ for (i = 0; i <= 1023; i++) {
cs->list[i].flags &= ~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
+ if (cs->list[i].sysinfo) {
+ talloc_free(cs->list[i].sysinfo);
+ cs->list[i].sysinfo = NULL;
+ }
+ }
}
new_c_state(cs, GSM322_C1_NORMAL_CELL_SEL);
-#ifdef TODO
- remove this:
-#else
- /* use hacked frequency */
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER;
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_SIGNAL;
- cs->list[ms->test_arfcn].rxlev_db = -40;
-#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;
/* start power scan */
return gsm322_cs_powerscan(ms);
/* in case we already tried any cell selection, power scan again */
if (cs->state == GSM322_C6_ANY_CELL_SEL) {
- for (i = 0; i <= 1023; i++)
+ struct msgb *nmsg;
+
+ /* tell that we have no cell found */
+ nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_NO_CELL_FOUND);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm48_mmevent_msg(ms, nmsg);
+
+ for (i = 0; i <= 1023; i++) {
cs->list[i].flags &= ~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
+ if (cs->list[i].sysinfo) {
+ talloc_free(cs->list[i].sysinfo);
+ cs->list[i].sysinfo = NULL;
+ }
+ }
} else {
new_c_state(cs, GSM322_C6_ANY_CELL_SEL);
}
cs->mcc = cs->mnc = 0;
-#ifdef TODO
- remove this:
-#else
- /* use hacked frequency */
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER;
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_SIGNAL;
- cs->list[ms->test_arfcn].rxlev_db = -40;
-#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;
/* start power scan */
return gsm322_cs_powerscan(ms);
/* NOTE: We keep our scan info we have so far.
* This may cause a skip in power scan. */
-#ifdef TODO
- remove this:
-#else
- /* use hacked frequency */
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER;
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_SIGNAL;
- cs->list[ms->test_arfcn].rxlev_db = -40;
-#endif
-
/* start power scan */
return gsm322_cs_powerscan(ms);
}
/* NOTE: We keep our scan info we have so far.
* This may cause a skip in power scan. */
-#ifdef TODO
- remove this:
-#else
- /* use hacked frequency */
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER;
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_SIGNAL;
- cs->list[ms->test_arfcn].rxlev_db = -40;
-#endif
-
/* start power scan */
return gsm322_cs_powerscan(ms);
}
int i;
#ifdef TODO
+what we have todo here:
+if we return from dedicated mode and we have a ba range, we can use that for cell reselection
if (message->ranges)
ba = gsm322_cs_ba_range(ms, message->range, message->ranges);
else {
#endif
/* get and update BA of last received sysinfo 5* */
ba = gsm322_cs_sysinfo_sacch(ms);
+ if (!ba)
+ ba = gsm322_find_ba_list(cs, cs->sel_si.mcc,
+ cs->sel_si.mnc);
#ifdef TODO
}
#endif
if (!ba) {
struct msgb *nmsg;
- LOGP(DCS, LOGL_INFO, "No BA list.\n");
+ LOGP(DCS, LOGL_INFO, "No BA list to use.\n");
/* tell CS to start over */
nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND);
cs->list[i].flags &= ~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
+ if (cs->list[i].sysinfo) {
+ talloc_free(cs->list[i].sysinfo);
+ cs->list[i].sysinfo = NULL;
+ }
}
-#ifdef TODO
- remove this:
-#else
- /* use hacked frequency */
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_POWER;
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_SIGNAL;
- cs->list[ms->test_arfcn].rxlev_db = -40;
-#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;
/* start power scan */
return gsm322_cs_powerscan(ms);
struct gsm322_cellsel *cs = &ms->cellsel;
struct msgb *nmsg;
- nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_NEW_LAI);
+ /* tell that we have selected a (new) cell */
+ nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_CELL_SELECTED);
if (!nmsg)
return -ENOMEM;
gsm48_mmevent_msg(ms, nmsg);
static int gsm322_c_camp_any_cell(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm322_cellsel *cs = &ms->cellsel;
+ struct msgb *nmsg;
+
+ /* tell that we have selected a (new) cell */
+ nmsg = gsm48_mmevent_msgb_alloc(GSM48_MM_EVENT_CELL_SELECTED);
+ if (!nmsg)
+ return -ENOMEM;
+ gsm48_mmevent_msg(ms, nmsg);
new_c_state(cs, GSM322_C7_CAMPED_ANY_CELL);
{
struct gsm322_cellsel *cs = &ms->cellsel;
- /* stop camping process */
+ /* check for error */
+ if (!cs->selected)
+ return -EINVAL;
+ cs->arfcn = cs->sel_arfcn;
/* be sure to go to current camping frequency on return */
LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn);
- l1ctl_tx_ccch_req(ms, cs->arfcn);
+ cs->ccch_active = 0;
+ l1ctl_tx_ccch_req_(ms, cs->arfcn);
+ cs->si = cs->list[cs->arfcn].sysinfo;
return 0;
}
{
struct gsm322_cellsel *cs = &ms->cellsel;
- /* stop camping process */
+ /* check for error */
+ if (!cs->selected)
+ return -EINVAL;
+ cs->arfcn = cs->sel_arfcn;
/* be sure to go to current camping frequency on return */
LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn);
- l1ctl_tx_ccch_req(ms, cs->arfcn);
+ cs->ccch_active = 0;
+ l1ctl_tx_ccch_req_(ms, cs->arfcn);
+ cs->si = cs->list[cs->arfcn].sysinfo;
return 0;
}
struct gsm_subscriber *subscr = &ms->subscr;
/* if no SIM is is MS */
- if (!subscr->sim_valid)
+ if (!subscr->sim_valid) {
LOGP(DCS, LOGL_INFO, "Switch on without SIM.\n");
return gsm322_c_any_cell_sel(ms, msg);
+ LOGP(DCS, LOGL_INFO, "Switch on with SIM inserted.\n");
+ }
/* stay in NULL state until PLMN is selected */
GSM322_EVENT_SWITCH_OFF, gsm322_a_switch_off},
{SBIT(GSM322_A6_NO_SIM),
GSM322_EVENT_SIM_INSERT, gsm322_a_switch_on},
+ {ALL_STATES,
+ GSM322_EVENT_SIM_INSERT, gsm322_a_sim_insert},
{ALL_STATES,
GSM322_EVENT_SIM_REMOVE, gsm322_a_sim_removed},
{ALL_STATES,
GSM322_EVENT_SWITCH_OFF, gsm322_m_switch_off},
{SBIT(GSM322_M5_NO_SIM),
GSM322_EVENT_SIM_INSERT, gsm322_m_switch_on},
+ {ALL_STATES,
+ GSM322_EVENT_SIM_INSERT, gsm322_m_sim_insert},
{ALL_STATES,
GSM322_EVENT_SIM_REMOVE, gsm322_m_sim_removed},
{SBIT(GSM322_M1_TRYING_RPLMN),
SBIT(GSM322_C4_NORMAL_CELL_RESEL),
GSM322_EVENT_CELL_FOUND, gsm322_c_camp_any_cell},
{SBIT(GSM322_C1_NORMAL_CELL_SEL) | SBIT(GSM322_C6_ANY_CELL_SEL) |
- SBIT(GSM322_C9_CHOOSE_ANY_CELL) | SBIT(GSM322_C8_ANY_CELL_RESEL),
+ SBIT(GSM322_C9_CHOOSE_ANY_CELL) | SBIT(GSM322_C8_ANY_CELL_RESEL) |
+ SBIT(GSM322_C0_NULL),
GSM322_EVENT_NO_CELL_FOUND, gsm322_c_any_cell_sel},
{SBIT(GSM322_C2_STORED_CELL_SEL) | SBIT(GSM322_C5_CHOOSE_CELL) |
SBIT(GSM322_C4_NORMAL_CELL_RESEL),
GSM322_EVENT_CELL_FOUND, gsm322_c_normal_cell_sel},
{SBIT(GSM322_C1_NORMAL_CELL_SEL) | SBIT(GSM322_C2_STORED_CELL_SEL) |
SBIT(GSM322_C4_NORMAL_CELL_RESEL) | SBIT(GSM322_C5_CHOOSE_CELL) |
- SBIT(GSM322_C9_CHOOSE_ANY_CELL) | SBIT(GSM322_C8_ANY_CELL_RESEL),
+ SBIT(GSM322_C9_CHOOSE_ANY_CELL) | SBIT(GSM322_C8_ANY_CELL_RESEL) |
+ SBIT(GSM322_C6_ANY_CELL_SEL),
GSM322_EVENT_SYSINFO, gsm322_c_scan_sysinfo_bcch},
- {SBIT(GSM322_C3_CAMPED_NORMALLY),
+ {SBIT(GSM322_C3_CAMPED_NORMALLY) | SBIT(GSM322_C7_CAMPED_ANY_CELL),
GSM322_EVENT_SYSINFO, gsm322_c_camp_sysinfo_bcch},
{SBIT(GSM322_C3_CAMPED_NORMALLY),
GSM322_EVENT_HPLMN_SEARCH, gsm322_c_hplmn_search}
&& ((1 << cs->state) & cellselstatelist[i].states))
break;
if (i == CELLSELSLLEN) {
- LOGP(DPLMN, LOGL_NOTICE, "Event unhandled at this state.\n");
+ LOGP(DCS, LOGL_NOTICE, "Event unhandled at this state.\n");
return 0;
}
continue;
printf("%4d |", cs->list[i].rxlev_db);
if ((cs->list[i].flags & GSM322_CS_FLAG_SYSINFO)) {
- printf("%03d |%02d |", cs->list[i].mcc,
- cs->list[i].mnc);
+ struct gsm48_sysinfo *s = cs->list[i].sysinfo;
+ printf("%03d |%02d |", s->mcc, s->mnc);
if ((cs->list[i].flags & GSM322_CS_FLAG_FORBIDD))
printf("yes |");
else
else
printf("no ");
for (j = 0; j < 16; j++) {
- if ((cs->list[i].class_barr & (1 << j)))
+ if ((s->class_barr & (1 << j)))
printf("*");
else
printf(" ");
}
- printf("|%4d |%4d", cs->list[i].min_db,
- cs->list[i].max_pwr);
+ printf("|%4d |%4d\n", s->rxlev_acc_min_db,
+ s->ms_txpwr_max_ccch);
} else
- printf("- |- | |"
- "- |-");
+ printf("n/a |n/a | | "
+ "|n/a |n/a\n");
}
return 0;
OSMOCOM_FILE *fp;
char suffix[] = ".ba";
char filename[sizeof(ms->name) + strlen(suffix) + 1];
-// int i;
+ int i;
struct gsm322_ba_list *ba;
uint8_t buf[4];
INIT_LLIST_HEAD(&plmn->forbidden_la);
INIT_LLIST_HEAD(&cs->ba_list);
-#ifdef TODO
/* set supported frequencies in cell selection list */
for (i = 0; i <= 1023; i++)
- if ((s->freq_map[i >> 3] & (1 << (i & 7))))
+ if ((ms->support.freq_map[i >> 3] & (1 << (i & 7))))
cs->list[i].flags |= GSM322_CS_FLAG_SUPPORT;
-#else
- /* set cell selection list to given test frequency only */
- cs->list[ms->test_arfcn].flags |= GSM322_CS_FLAG_SUPPORT;
-#endif
/* read BA list */
strcpy(filename, ms->name);
strcat(filename, suffix);
fp = osmocom_fopen(filename, "r");
if (fp) {
- while(!feof(fp)) {
+ int rc;
+
+ while(!osmocom_feof(fp)) {
ba = talloc_zero(l23_ctx, struct gsm322_ba_list);
if (!ba)
return -ENOMEM;
- osmocom_fread(buf, 4, 1, fp);
+ rc = osmocom_fread(buf, 4, 1, fp);
+ if (!rc) {
+ talloc_free(ba);
+ break;
+ }
ba->mcc = (buf[0] << 8) | buf[1];
ba->mnc = (buf[2] << 8) | buf[3];
- osmocom_fread(ba->freq, sizeof(ba->freq), 1, fp);
+ rc = osmocom_fread(ba->freq, sizeof(ba->freq), 1, fp);
+ if (!rc) {
+ talloc_free(ba);
+ break;
+ }
llist_add_tail(&ba->entry, &cs->ba_list);
- LOGP(DPLMN, LOGL_INFO, "Read stored BA list (mcc=%d "
- "mnc=%d)\n", ba->mcc, ba->mnc);
+ LOGP(DCS, LOGL_INFO, "Read stored BA list (mcc=%d "
+ "mnc=%d %s, %s)\n", ba->mcc, ba->mnc,
+ gsm_get_mcc(ba->mcc),
+ gsm_get_mnc(ba->mcc, ba->mnc));
}
osmocom_fclose(fp);
} else
- LOGP(DCS, LOGL_NOTICE, "No stored BA list\n");
+ LOGP(DCS, LOGL_INFO, "No stored BA list\n");
+
+ register_signal_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
return 0;
}
char filename[sizeof(ms->name) + strlen(suffix) + 1];
struct gsm322_ba_list *ba;
uint8_t buf[4];
+ int i;
LOGP(DPLMN, LOGL_INFO, "exit PLMN process\n");
LOGP(DCS, LOGL_INFO, "exit Cell Selection process\n");
+ unregister_signal_handler(SS_L1CTL, &gsm322_l1_signal, NULL);
+
/* stop cell selection process (if any) */
new_c_state(cs, GSM322_C0_NULL);
stop_cs_timer(cs);
stop_plmn_timer(plmn);
+ /* flush sysinfo */
+ for (i = 0; i <= 1023; i++) {
+ if (cs->list[i].sysinfo) {
+ talloc_free(cs->list[i].sysinfo);
+ cs->list[i].sysinfo = NULL;
+ }
+ cs->list[i].flags = 0;
+ }
+
/* store BA list */
strcpy(filename, ms->name);
strcat(filename, suffix);
fp = osmocom_fopen(filename, "w");
if (fp) {
+ int rc;
+
llist_for_each_entry(ba, &cs->ba_list, entry) {
buf[0] = ba->mcc >> 8;
- buf[1] = ba->mcc | 0xff;
+ buf[1] = ba->mcc & 0xff;
buf[2] = ba->mnc >> 8;
- buf[3] = ba->mnc | 0xff;
- osmocom_fwrite(buf, 4, 1, fp);
- osmocom_fwrite(ba->freq, sizeof(ba->freq), 1, fp);
- LOGP(DPLMN, LOGL_INFO, "Write stored BA list (mcc=%d "
- "mnc=%d)\n", ba->mcc, ba->mnc);
+ buf[3] = ba->mnc & 0xff;
+ rc = osmocom_fwrite(buf, 4, 1, fp);
+ rc = osmocom_fwrite(ba->freq, sizeof(ba->freq), 1, fp);
+ LOGP(DCS, LOGL_INFO, "Write stored BA list (mcc=%d "
+ "mnc=%d %s, %s)\n", ba->mcc, ba->mnc,
+ gsm_get_mcc(ba->mcc),
+ gsm_get_mnc(ba->mcc, ba->mnc));
}
osmocom_fclose(fp);
} else