Work on layer 3 processes:

- Fixed reference to system informations. (did crash when re-selecting).
- Fix in cell selection state machine. (any re-selection).
- MCC, MNC, LAC change of cell now triggers re-selection.
- Fixed some paging issues. Empty pagings are not displayed anymore. Also paging is now possible when 'camping on any cell'.
This commit is contained in:
Andreas.Eversberg 2010-05-04 09:48:51 +00:00
parent fe1dc19c6e
commit 7f009e41f9
7 changed files with 164 additions and 116 deletions

View File

@ -75,6 +75,7 @@ struct gsm_support {
/* radio */ /* radio */
int8_t min_rxlev_db; int8_t min_rxlev_db;
uint8_t scan_to;
}; };
struct gsm_support_scan_max { struct gsm_support_scan_max {

View File

@ -102,7 +102,7 @@ int mobile_exit(struct osmocom_ms *ms)
int l23_app_init(struct osmocom_ms *ms) int l23_app_init(struct osmocom_ms *ms)
{ {
log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DCC:DMNCC"); log_parse_category_mask(stderr_target, "DCS:DPLMN:DRR:DMM:DCC:DMNCC:DPAG");
gsm48_cc_init(ms); gsm48_cc_init(ms);
gsm_support_init(ms); gsm_support_init(ms);

View File

@ -77,6 +77,14 @@ int l1ctl_tx_ccch_req_(struct osmocom_ms *ms, uint16_t arfcn)
* if the cell is 'suitable' and 'allowable' to 'camp' on. * if the cell is 'suitable' and 'allowable' to 'camp' on.
* *
* This list is also used to generate a list of available networks. * This list is also used to generate a list of available networks.
*
* The states are:
*
* - cs->list[0..1023].xxx for each cell, where
* - flags and rxlev_db are used to store outcome of cell scanning process
* - sysinfo pointing to sysinfo memory, allocated temporarily
* - cs->selected and cs->sel_* states of the current / last selected cell.
*
*/ */
/* PLMN selection process /* PLMN selection process
@ -361,7 +369,8 @@ int gsm322_is_plmn_avail(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc)
int i; int i;
for (i = 0; i <= 1023; i++) { for (i = 0; i <= 1023; i++) {
if (cs->list[i].sysinfo->mcc == mcc if (cs->list[i].sysinfo
&& cs->list[i].sysinfo->mcc == mcc
&& cs->list[i].sysinfo->mnc == mnc) && cs->list[i].sysinfo->mnc == mnc)
return 1; return 1;
} }
@ -569,7 +578,8 @@ static int gsm322_sort_list(struct osmocom_ms *ms)
/* Create a temporary list of all networks */ /* Create a temporary list of all networks */
INIT_LLIST_HEAD(&temp_list); INIT_LLIST_HEAD(&temp_list);
for (i = 0; i <= 1023; i++) { for (i = 0; i <= 1023; i++) {
if (!(cs->list[i].flags & GSM322_CS_FLAG_TEMP_AA)) if (!(cs->list[i].flags & GSM322_CS_FLAG_TEMP_AA)
|| !cs->list[i].sysinfo)
continue; continue;
/* search if network has multiple cells */ /* search if network has multiple cells */
@ -1363,7 +1373,7 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any)
s = cs->list[i].sysinfo; s = cs->list[i].sysinfo;
/* channel has no informations for us */ /* channel has no informations for us */
if ((cs->list[i].flags & mask) != flags) { if (!s || (cs->list[i].flags & mask) != flags) {
continue; continue;
} }
@ -1576,7 +1586,8 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
} }
if (!nmsg) if (!nmsg)
return -ENOMEM; return -ENOMEM;
gsm322_cs_sendmsg(ms, nmsg); gsm322_c_event(ms, nmsg);
msgb_free(nmsg);
return 0; return 0;
} }
@ -1592,8 +1603,9 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
l1ctl_tx_ccch_req_(ms, cs->arfcn); l1ctl_tx_ccch_req_(ms, cs->arfcn);
/* Allocate system information. */ /* Allocate system information. */
cs->list[cs->arfcn].sysinfo = talloc_zero(l23_ctx, if (!cs->list[cs->arfcn].sysinfo)
struct gsm48_sysinfo); cs->list[cs->arfcn].sysinfo = talloc_zero(l23_ctx,
struct gsm48_sysinfo);
if (!cs->list[cs->arfcn].sysinfo) if (!cs->list[cs->arfcn].sysinfo)
exit(-ENOMEM); exit(-ENOMEM);
cs->si = cs->list[cs->arfcn].sysinfo; cs->si = cs->list[cs->arfcn].sysinfo;
@ -1609,8 +1621,7 @@ static int gsm322_cs_store(struct osmocom_ms *ms)
{ {
struct gsm322_cellsel *cs = &ms->cellsel; struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm_subscriber *subscr = &ms->subscr; struct gsm_subscriber *subscr = &ms->subscr;
int i = cs->scan_state & 1023; struct gsm48_sysinfo *s = cs->si;
struct gsm48_sysinfo *s = cs->list[i].sysinfo;
if (cs->state != GSM322_C2_STORED_CELL_SEL if (cs->state != GSM322_C2_STORED_CELL_SEL
&& cs->state != GSM322_C1_NORMAL_CELL_SEL && cs->state != GSM322_C1_NORMAL_CELL_SEL
@ -1625,35 +1636,35 @@ static int gsm322_cs_store(struct osmocom_ms *ms)
} }
/* store sysinfo */ /* store sysinfo */
cs->list[i].flags |= GSM322_CS_FLAG_SYSINFO; cs->list[cs->arfcn].flags |= GSM322_CS_FLAG_SYSINFO;
if (s->cell_barr) if (s->cell_barr)
cs->list[i].flags |= GSM322_CS_FLAG_BARRED; cs->list[cs->arfcn].flags |= GSM322_CS_FLAG_BARRED;
else else
cs->list[i].flags &= ~GSM322_CS_FLAG_BARRED; cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_BARRED;
#if 0 #if 0
cs->list[i].min_db = s->rxlev_acc_min_db; cs->list[cs->arfcn].min_db = s->rxlev_acc_min_db;
cs->list[i].class_barr = s->class_barr; cs->list[cs->arfcn].class_barr = s->class_barr;
cs->list[i].max_pwr = s->ms_txpwr_max_ccch; cs->list[cs->arfcn].max_pwr = s->ms_txpwr_max_ccch;
#endif #endif
/* store selected network */ /* store selected network */
if (s->mcc) { if (s->mcc) {
#if 0 #if 0
cs->list[i].mcc = s->mcc; cs->list[cs->arfcn].mcc = s->mcc;
cs->list[i].mnc = s->mnc; cs->list[cs->arfcn].mnc = s->mnc;
cs->list[i].lac = s->lac; cs->list[cs->arfcn].lac = s->lac;
#endif #endif
if (gsm322_is_forbidden_la(ms, s->mcc, s->mnc, s->lac)) if (gsm322_is_forbidden_la(ms, s->mcc, s->mnc, s->lac))
cs->list[i].flags |= GSM322_CS_FLAG_FORBIDD; cs->list[cs->arfcn].flags |= GSM322_CS_FLAG_FORBIDD;
else else
cs->list[i].flags &= ~GSM322_CS_FLAG_FORBIDD; cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_FORBIDD;
} }
LOGP(DCS, LOGL_INFO, "Scan frequency %d: Cell found. (rxlev=%d " LOGP(DCS, LOGL_INFO, "Scan frequency %d: Cell found. (rxlev=%d "
"mcc=%03d mnc=%02d lac=%04x)\n", i, cs->list[i].rxlev_db, "mcc=%03d mnc=%02d lac=%04x)\n", cs->arfcn,
s->mcc, s->mnc, s->lac); cs->list[cs->arfcn].rxlev_db, s->mcc, s->mnc, s->lac);
/* special prositive case for HPLMN search */ /* special prositive case for HPLMN search */
if (cs->state == GSM322_HPLMN_SEARCH && s->mcc == subscr->mcc if (cs->state == GSM322_HPLMN_SEARCH && s->mcc == subscr->mcc
@ -1802,11 +1813,19 @@ static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
trigger_resel: trigger_resel:
/* mark cell as unscanned */ /* mark cell as unscanned */
cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_SYSINFO; cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_SYSINFO;
/* trigger reselection event */ if (cs->list[cs->arfcn].sysinfo) {
talloc_free(cs->list[cs->arfcn].sysinfo);
cs->list[cs->arfcn].sysinfo = NULL;
}
/* trigger reselection without queueing,
* because other sysinfo message may be queued
* before
*/
nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_RESEL); nmsg = gsm322_msgb_alloc(GSM322_EVENT_CELL_RESEL);
if (!nmsg) if (!nmsg)
return -ENOMEM; return -ENOMEM;
gsm322_cs_sendmsg(ms, nmsg); gsm322_c_event(ms, nmsg);
msgb_free(nmsg);
return 0; return 0;
} }
@ -1818,6 +1837,14 @@ static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
} }
} }
/* check if MCC, MNC, LAC 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;
}
return 0; return 0;
} }
@ -1876,17 +1903,16 @@ static void gsm322_cs_timeout(void *arg)
{ {
struct gsm322_cellsel *cs = arg; struct gsm322_cellsel *cs = arg;
struct osmocom_ms *ms = cs->ms; struct osmocom_ms *ms = cs->ms;
int i = cs->scan_state & 1023;
LOGP(DCS, LOGL_INFO, "Cell selection timer has fired.\n"); LOGP(DCS, LOGL_INFO, "Cell selection timer has fired.\n");
LOGP(DCS, LOGL_INFO, "Scan frequency %d: Cell not found. (rxlev=%d)\n", LOGP(DCS, LOGL_INFO, "Scan frequency %d: Cell not found. (rxlev=%d)\n",
i, cs->list[i].rxlev_db); cs->arfcn, cs->list[cs->arfcn].rxlev_db);
/* remove system information */ /* remove system information */
cs->list[i].flags &= ~GSM322_CS_FLAG_SYSINFO; cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_SYSINFO;
if (cs->list[i].sysinfo) { if (cs->list[cs->arfcn].sysinfo) {
talloc_free(cs->list[i].sysinfo); talloc_free(cs->list[cs->arfcn].sysinfo);
cs->list[i].sysinfo = NULL; cs->list[cs->arfcn].sysinfo = NULL;
} }
/* tune to next cell */ /* tune to next cell */
@ -2053,7 +2079,7 @@ static int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
|| cs->state == GSM322_C8_ANY_CELL_RESEL || cs->state == GSM322_C8_ANY_CELL_RESEL
|| cs->state == GSM322_C5_CHOOSE_CELL || cs->state == GSM322_C5_CHOOSE_CELL
|| cs->state == GSM322_C9_CHOOSE_ANY_CELL) || cs->state == GSM322_C9_CHOOSE_ANY_CELL)
start_cs_timer(cs, 8, 0); start_cs_timer(cs, ms->support.scan_to, 0);
// TODO: timer depends on BCCH config // TODO: timer depends on BCCH config
} }
break; break;
@ -2278,7 +2304,10 @@ if we return from dedicated mode and we have a ba range, we can use that for cel
nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND); nmsg = gsm322_msgb_alloc(GSM322_EVENT_NO_CELL_FOUND);
if (!nmsg) if (!nmsg)
return -ENOMEM; return -ENOMEM;
gsm322_cs_sendmsg(ms, nmsg); gsm322_c_event(ms, nmsg);
msgb_free(nmsg);
return 0;
} }
/* flag all frequencies that are in current band allocation */ /* flag all frequencies that are in current band allocation */
@ -2628,7 +2657,7 @@ static struct cellselstatelist {
SBIT(GSM322_C4_NORMAL_CELL_RESEL) | SBIT(GSM322_C5_CHOOSE_CELL), SBIT(GSM322_C4_NORMAL_CELL_RESEL) | SBIT(GSM322_C5_CHOOSE_CELL),
GSM322_EVENT_CELL_FOUND, gsm322_c_camp_normally}, GSM322_EVENT_CELL_FOUND, gsm322_c_camp_normally},
{SBIT(GSM322_C9_CHOOSE_ANY_CELL) | SBIT(GSM322_C6_ANY_CELL_SEL) | {SBIT(GSM322_C9_CHOOSE_ANY_CELL) | SBIT(GSM322_C6_ANY_CELL_SEL) |
SBIT(GSM322_C4_NORMAL_CELL_RESEL), SBIT(GSM322_C8_ANY_CELL_RESEL),
GSM322_EVENT_CELL_FOUND, gsm322_c_camp_any_cell}, GSM322_EVENT_CELL_FOUND, gsm322_c_camp_any_cell},
{SBIT(GSM322_C1_NORMAL_CELL_SEL) | SBIT(GSM322_C6_ANY_CELL_SEL) | {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) |
@ -2731,17 +2760,18 @@ int gsm322_dump_cs_list(struct osmocom_ms *ms, uint8_t flags)
{ {
struct gsm322_cellsel *cs = &ms->cellsel; struct gsm322_cellsel *cs = &ms->cellsel;
int i, j; int i, j;
struct gsm48_sysinfo *s;
printf("rx-lev |MCC |MNC |forb.LA|barred,0123456789abcdef|" printf("rx-lev |MCC |MNC |forb.LA|barred,0123456789abcdef|"
"min-db |max-pwr\n" "min-db |max-pwr\n"
"-------+-------+-------+-------+-----------------------+" "-------+-------+-------+-------+-----------------------+"
"-------+-------\n"); "-------+-------\n");
for (i = 0; i <= 1023; i++) { for (i = 0; i <= 1023; i++) {
if (!(cs->list[i].flags & flags)) s = cs->list[i].sysinfo;
if (!s || !(cs->list[i].flags & flags))
continue; continue;
printf("%4d |", cs->list[i].rxlev_db); printf("%4d |", cs->list[i].rxlev_db);
if ((cs->list[i].flags & GSM322_CS_FLAG_SYSINFO)) { if ((cs->list[i].flags & GSM322_CS_FLAG_SYSINFO)) {
struct gsm48_sysinfo *s = cs->list[i].sysinfo;
printf("%03d |%02d |", s->mcc, s->mnc); printf("%03d |%02d |", s->mcc, s->mnc);
if ((cs->list[i].flags & GSM322_CS_FLAG_FORBIDD)) if ((cs->list[i].flags & GSM322_CS_FLAG_FORBIDD))
printf("yes |"); printf("yes |");

View File

@ -72,6 +72,7 @@ int gsm48_cc_exit(struct osmocom_ms *ms)
llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) { llist_for_each_entry_safe(trans, trans2, &ms->trans_list, entry) {
if (trans->protocol == GSM48_PDISC_CC) if (trans->protocol == GSM48_PDISC_CC)
LOGP(DCC, LOGL_NOTICE, "Free pendig CC-transaction.\n");
trans_free(trans); trans_free(trans);
} }

View File

@ -725,8 +725,9 @@ static int gsm48_rr_tx_chan_req(struct osmocom_ms *ms, int cause, int paging)
/* ignore paging, if not camping */ /* ignore paging, if not camping */
if (paging if (paging
&& (!cs->selected || cs->state != GSM322_C3_CAMPED_NORMALLY)) { && (!cs->selected || (cs->state != GSM322_C3_CAMPED_NORMALLY
LOGP(DRR, LOGL_INFO, "Paging, but not camping normally.\n"); && cs->state != GSM322_C7_CAMPED_ANY_CELL))) {
LOGP(DRR, LOGL_INFO, "Paging, but not camping, ignore.\n");
return -EINVAL; return -EINVAL;
} }
@ -2051,25 +2052,25 @@ static int gsm_match_mi(struct osmocom_ms *ms, uint8_t *mi)
memcpy(&tmsi, mi+2, 4); memcpy(&tmsi, mi+2, 4);
if (ms->subscr.tmsi == ntohl(tmsi) if (ms->subscr.tmsi == ntohl(tmsi)
&& ms->subscr.tmsi_valid) { && ms->subscr.tmsi_valid) {
LOGP(DRR, LOGL_INFO, "TMSI %08x matches\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n",
ntohl(tmsi)); ntohl(tmsi));
return 1; return 1;
} else } else
LOGP(DRR, LOGL_INFO, "TMSI %08x (not for us)\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(tmsi)); ntohl(tmsi));
break; break;
case GSM_MI_TYPE_IMSI: case GSM_MI_TYPE_IMSI:
gsm48_mi_to_string(imsi, sizeof(imsi), mi + 1, mi[0]); gsm48_mi_to_string(imsi, sizeof(imsi), mi + 1, mi[0]);
if (!strcmp(imsi, ms->subscr.imsi)) { if (!strcmp(imsi, ms->subscr.imsi)) {
LOGP(DRR, LOGL_INFO, "IMSI %s matches\n", imsi); LOGP(DPAG, LOGL_INFO, "IMSI %s matches\n", imsi);
return 1; return 1;
} else } else
LOGP(DRR, LOGL_INFO, "IMSI %s (not for us)\n", imsi); LOGP(DPAG, LOGL_INFO, "IMSI %s (not for us)\n", imsi);
break; break;
default: default:
LOGP(DRR, LOGL_NOTICE, "Paging with unsupported MI type %d.\n", LOGP(DPAG, LOGL_NOTICE, "Paging with unsupported MI type %d.\n",
mi_type); mi_type);
} }
@ -2086,16 +2087,19 @@ static int gsm48_rr_rx_pag_req_1(struct osmocom_ms *ms, struct msgb *msg)
int chan_1, chan_2; int chan_1, chan_2;
uint8_t *mi; uint8_t *mi;
/* empty paging request */
if (payload_len >= 2 && (pa->data[1] & GSM_MI_TYPE_MASK) == 0)
return 0;
/* 3.3.1.1.2: ignore paging while not camping on a cell */ /* 3.3.1.1.2: ignore paging while not camping on a cell */
if (rr->state != GSM48_RR_ST_IDLE if (rr->state != GSM48_RR_ST_IDLE || !cs->selected
|| !cs->selected || cs->state != GSM322_C3_CAMPED_NORMALLY) { || (cs->state != GSM322_C3_CAMPED_NORMALLY
#if 0 && cs->state != GSM322_C7_CAMPED_ANY_CELL)) {
LOGP(DRR, LOGL_INFO, "PAGING ignored, we are not camping " LOGP(DRR, LOGL_INFO, "PAGING ignored, we are not camping "
"normally.\n"); "normally.\n");
#endif
return 0; return 0;
} }
LOGP(DRR, LOGL_INFO, "PAGING REQUEST 1\n"); LOGP(DPAG, LOGL_INFO, "PAGING REQUEST 1\n");
if (payload_len < 2) { if (payload_len < 2) {
short_read: short_read:
@ -2139,13 +2143,14 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
int chan_1, chan_2, chan_3; int chan_1, chan_2, chan_3;
/* 3.3.1.1.2: ignore paging while not camping on a cell */ /* 3.3.1.1.2: ignore paging while not camping on a cell */
if (rr->state != GSM48_RR_ST_IDLE if (rr->state != GSM48_RR_ST_IDLE || !cs->selected
&& cs->state != GSM322_C3_CAMPED_NORMALLY) { || (cs->state != GSM322_C3_CAMPED_NORMALLY
&& cs->state != GSM322_C7_CAMPED_ANY_CELL)) {
LOGP(DRR, LOGL_INFO, "PAGING ignored, we are not camping " LOGP(DRR, LOGL_INFO, "PAGING ignored, we are not camping "
"normally.\n"); "normally.\n");
return 0; return 0;
} }
LOGP(DRR, LOGL_INFO, "PAGING REQUEST 2\n"); LOGP(DPAG, LOGL_INFO, "PAGING REQUEST 2\n");
if (payload_len < 0) { if (payload_len < 0) {
short_read: short_read:
@ -2160,18 +2165,18 @@ static int gsm48_rr_rx_pag_req_2(struct osmocom_ms *ms, struct msgb *msg)
/* first MI */ /* first MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi1) if (ms->subscr.tmsi == ntohl(pa->tmsi1)
&& ms->subscr.tmsi_valid) { && ms->subscr.tmsi_valid) {
LOGP(DRR, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1)); LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1));
return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1); return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
} else } else
LOGP(DRR, LOGL_INFO, "TMSI %08x (not for us)\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi1)); ntohl(pa->tmsi1));
/* second MI */ /* second MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi2) if (ms->subscr.tmsi == ntohl(pa->tmsi2)
&& ms->subscr.tmsi_valid) { && ms->subscr.tmsi_valid) {
LOGP(DRR, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2)); LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2));
return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1); return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
} else } else
LOGP(DRR, LOGL_INFO, "TMSI %08x (not for us)\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi2)); ntohl(pa->tmsi2));
/* third MI */ /* third MI */
mi = pa->data; mi = pa->data;
@ -2198,13 +2203,14 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
int chan_1, chan_2, chan_3, chan_4; int chan_1, chan_2, chan_3, chan_4;
/* 3.3.1.1.2: ignore paging while not camping on a cell */ /* 3.3.1.1.2: ignore paging while not camping on a cell */
if (rr->state != GSM48_RR_ST_IDLE if (rr->state != GSM48_RR_ST_IDLE || !cs->selected
&& cs->state != GSM322_C3_CAMPED_NORMALLY) { || (cs->state != GSM322_C3_CAMPED_NORMALLY
&& cs->state != GSM322_C7_CAMPED_ANY_CELL)) {
LOGP(DRR, LOGL_INFO, "PAGING ignored, we are not camping " LOGP(DRR, LOGL_INFO, "PAGING ignored, we are not camping "
"normally.\n"); "normally.\n");
return 0; return 0;
} }
LOGP(DRR, LOGL_INFO, "PAGING REQUEST 3\n"); LOGP(DPAG, LOGL_INFO, "PAGING REQUEST 3\n");
if (payload_len < 0) { /* must include "channel needed", part of *pa */ if (payload_len < 0) { /* must include "channel needed", part of *pa */
LOGP(DRR, LOGL_NOTICE, "Short read of PAGING REQUEST 3 " LOGP(DRR, LOGL_NOTICE, "Short read of PAGING REQUEST 3 "
@ -2220,34 +2226,34 @@ static int gsm48_rr_rx_pag_req_3(struct osmocom_ms *ms, struct msgb *msg)
/* first MI */ /* first MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi1) if (ms->subscr.tmsi == ntohl(pa->tmsi1)
&& ms->subscr.tmsi_valid) { && ms->subscr.tmsi_valid) {
LOGP(DRR, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1)); LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi1));
return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1); return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_1], 1);
} else } else
LOGP(DRR, LOGL_INFO, "TMSI %08x (not for us)\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi1)); ntohl(pa->tmsi1));
/* second MI */ /* second MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi2) if (ms->subscr.tmsi == ntohl(pa->tmsi2)
&& ms->subscr.tmsi_valid) { && ms->subscr.tmsi_valid) {
LOGP(DRR, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2)); LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi2));
return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1); return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_2], 1);
} else } else
LOGP(DRR, LOGL_INFO, "TMSI %08x (not for us)\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi2)); ntohl(pa->tmsi2));
/* thrid MI */ /* thrid MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi3) if (ms->subscr.tmsi == ntohl(pa->tmsi3)
&& ms->subscr.tmsi_valid) { && ms->subscr.tmsi_valid) {
LOGP(DRR, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi3)); LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi3));
return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1); return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_3], 1);
} else } else
LOGP(DRR, LOGL_INFO, "TMSI %08x (not for us)\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi3)); ntohl(pa->tmsi3));
/* fourth MI */ /* fourth MI */
if (ms->subscr.tmsi == ntohl(pa->tmsi4) if (ms->subscr.tmsi == ntohl(pa->tmsi4)
&& ms->subscr.tmsi_valid) { && ms->subscr.tmsi_valid) {
LOGP(DRR, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi4)); LOGP(DPAG, LOGL_INFO, "TMSI %08x matches\n", ntohl(pa->tmsi4));
return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1); return gsm48_rr_tx_chan_req(ms, gsm48_rr_chan2cause[chan_4], 1);
} else } else
LOGP(DRR, LOGL_INFO, "TMSI %08x (not for us)\n", LOGP(DPAG, LOGL_INFO, "TMSI %08x (not for us)\n",
ntohl(pa->tmsi4)); ntohl(pa->tmsi4));
return 0; return 0;
@ -2997,7 +3003,7 @@ static int gsm48_rr_rx_bcch(struct osmocom_ms *ms, struct msgb *msg)
} }
/* receive CCCH at RR layer */ /* receive CCCH at RR layer */
static int gsm48_rr_rx_ccch(struct osmocom_ms *ms, struct msgb *msg) static int gsm48_rr_rx_pch_agch(struct osmocom_ms *ms, struct msgb *msg)
{ {
struct gsm48_system_information_type_header *sih = msgb_l3(msg); struct gsm48_system_information_type_header *sih = msgb_l3(msg);
struct gsm322_cellsel *cs = &ms->cellsel; struct gsm322_cellsel *cs = &ms->cellsel;
@ -3056,8 +3062,16 @@ static int gsm48_rr_unit_data_ind(struct osmocom_ms *ms, struct msgb *msg)
switch (rllh->chan_nr) { switch (rllh->chan_nr) {
case RSL_CHAN_PCH_AGCH: case RSL_CHAN_PCH_AGCH:
return gsm48_rr_rx_ccch(ms, msg); return gsm48_rr_rx_pch_agch(ms, msg);
case RSL_CHAN_BCCH: case RSL_CHAN_BCCH:
#if 0
#warning testing corrupt frames
{int i;
if (ms->cellsel.state == GSM322_C7_CAMPED_ANY_CELL)
for(i=0;i<msgb_l3len(msg);i++)
msg->l3h[i] = random();
}
#endif
return gsm48_rr_rx_bcch(ms, msg); return gsm48_rr_rx_bcch(ms, msg);
default: default:
LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n", LOGP(DRSL, LOGL_NOTICE, "RSL with chan_nr 0x%02x unknown.\n",

View File

@ -82,6 +82,7 @@ static const struct log_info_cat default_categories[] = {
[DPAG] = { [DPAG] = {
.name = "DPAG", .name = "DPAG",
.description = "Paging", .description = "Paging",
.color = "\033[33m",
.enabled = 1, .loglevel = LOGL_DEBUG, .enabled = 1, .loglevel = LOGL_DEBUG,
}, },
[DLAPDM] = { [DLAPDM] = {

View File

@ -27,85 +27,86 @@
void gsm_support_init(struct osmocom_ms *ms) void gsm_support_init(struct osmocom_ms *ms)
{ {
struct gsm_support *s = &ms->support; struct gsm_support *sup = &ms->support;
int i; int i;
memset(s, 0, sizeof(*s)); memset(sup, 0, sizeof(*sup));
/* rf power capability */ /* rf power capability */
s->pwr_lev_900 = 3; /* CLASS 4: Handheld 2W */ sup->pwr_lev_900 = 3; /* CLASS 4: Handheld 2W */
s->pwr_lev_1800 = 0; /* CLASS 1: Handheld 1W */ sup->pwr_lev_1800 = 0; /* CLASS 1: Handheld 1W */
/* controlled early classmark sending */ /* controlled early classmark sending */
s->es_ind = 0; /* no */ sup->es_ind = 0; /* no */
/* revision level */ /* revision level */
s->rev_lev = 1; /* phase 2 mobile station */ sup->rev_lev = 1; /* phase 2 mobile station */
/* support of VGCS */ /* support of VGCS */
s->vgcs = 0; /* no */ sup->vgcs = 0; /* no */
/* support of VBS */ /* support of VBS */
s->vbs = 0; /* no */ sup->vbs = 0; /* no */
/* support of SMS */ /* support of SMS */
s->sms_ptp = 1; /* yes */ sup->sms_ptp = 1; /* yes */
/* screening indicator */ /* screening indicator */
s->ss_ind = 1; /* phase 2 error handling */ sup->ss_ind = 1; /* phase 2 error handling */
/* pseudo synchronised capability */ /* pseudo synchronised capability */
s->ps_cap = 0; /* no */ sup->ps_cap = 0; /* no */
/* CM service prompt */ /* CM service prompt */
s->cmsp = 0; /* no */ sup->cmsp = 0; /* no */
/* solsa support */ /* solsa support */
s->solsa = 0; /* no */ sup->solsa = 0; /* no */
/* location service support */ /* location service support */
s->lcsva = 0; /* no */ sup->lcsva = 0; /* no */
s->loc_serv = 0; /* no */ sup->loc_serv = 0; /* no */
/* codec supprot */ /* codec supprot */
s->a5_1 = 0; /* currently not */ sup->a5_1 = 0; /* currently not */
s->a5_2 = 0; sup->a5_2 = 0;
s->a5_3 = 0; sup->a5_3 = 0;
s->a5_4 = 0; sup->a5_4 = 0;
s->a5_5 = 0; sup->a5_5 = 0;
s->a5_6 = 0; sup->a5_6 = 0;
s->a5_7 = 0; sup->a5_7 = 0;
/* radio support */ /* radio support */
s->p_gsm = 1; /* P-GSM only */ sup->p_gsm = 1; /* P-GSM only */
s->e_gsm = 0; /* E-GSM */ sup->e_gsm = 0; /* E-GSM */
s->r_gsm = 0; /* R-GSM */ sup->r_gsm = 0; /* R-GSM */
s->r_capa = 0; sup->r_capa = 0;
s->low_capa = 4; /* p,e,r power class */ sup->low_capa = 4; /* p,e,r power class */
s->dcs_1800 = 0; sup->dcs_1800 = 0;
/* set supported frequencies */ /* set supported frequencies */
if (s->e_gsm || s->r_gsm) if (sup->e_gsm || sup->r_gsm)
s->freq_map[0] |= 1; sup->freq_map[0] |= 1;
if (s->p_gsm || s->e_gsm || s->r_gsm) if (sup->p_gsm || sup->e_gsm || sup->r_gsm)
for(i = 1; i <= 124; i++) for(i = 1; i <= 124; i++)
s->freq_map[i >> 3] |= (1 << (i & 7)); sup->freq_map[i >> 3] |= (1 << (i & 7));
if (s->dcs_1800) if (sup->dcs_1800)
for(i = 512; i <= 885; i++) for(i = 512; i <= 885; i++)
s->freq_map[i >> 3] |= (1 << (i & 7)); sup->freq_map[i >> 3] |= (1 << (i & 7));
if (s->e_gsm) if (sup->e_gsm)
for(i = 975; i <= 1023; i++) for(i = 975; i <= 1023; i++)
s->freq_map[i >> 3] |= (1 << (i & 7)); sup->freq_map[i >> 3] |= (1 << (i & 7));
// for(i = 978; i <= 978; i++) // for(i = 978; i <= 978; i++)
// s->freq_map[i >> 3] |= (1 << (i & 7)); // sup->freq_map[i >> 3] |= (1 << (i & 7));
if (s->r_gsm) if (sup->r_gsm)
for(i = 955; i <= 1023; i++) for(i = 955; i <= 1023; i++)
s->freq_map[i >> 3] |= (1 << (i & 7)); sup->freq_map[i >> 3] |= (1 << (i & 7));
s->dcs_capa = 1; /* dcs power class */ sup->dcs_capa = 1; /* dcs power class */
/* multi slot support */ /* multi slot support */
s->ms_sup = 0; /* no */ sup->ms_sup = 0; /* no */
/* ucs2 treatment */ /* ucs2 treatment */
s->ucs2_treat = 0; /* default */ sup->ucs2_treat = 0; /* default */
/* support extended measurements */ /* support extended measurements */
s->ext_meas = 0; /* no */ sup->ext_meas = 0; /* no */
/* support switched measurement capability */ /* support switched measurement capability */
s->meas_cap = 0; /* no */ sup->meas_cap = 0; /* no */
//s->sms_val = ; //sup->sms_val = ;
//s->sm_val = ; //sup->sm_val = ;
/* IMEI */ /* IMEI */
sprintf(s->imei, "000000000000000"); sprintf(sup->imei, "000000000000000");
sprintf(s->imeisv, "0000000000000000"); sprintf(sup->imeisv, "0000000000000000");
/* radio */ /* radio */
s->min_rxlev_db = -106; // TODO sup->min_rxlev_db = -106; // TODO
sup->scan_to = 4; /* how long to wait for all sysinfos (>=4 s) */
} }
/* (3.2.1) maximum channels to scan within each band */ /* (3.2.1) maximum channels to scan within each band */