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:
parent
fe1dc19c6e
commit
7f009e41f9
|
@ -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 {
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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 |");
|
||||||
|
|
|
@ -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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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",
|
||||||
|
|
|
@ -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] = {
|
||||||
|
|
|
@ -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 */
|
||||||
|
|
Loading…
Reference in New Issue