summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/host/gsmmap/gsmmap.c3
-rw-r--r--src/host/layer23/include/osmocom/bb/common/sysinfo.h10
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm322.h10
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h1
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/settings.h23
-rw-r--r--src/host/layer23/include/osmocom/bb/mobile/support.h22
-rw-r--r--src/host/layer23/src/common/sysinfo.c85
-rw-r--r--src/host/layer23/src/mobile/app_mobile.c1
-rw-r--r--src/host/layer23/src/mobile/gsm322.c395
-rw-r--r--src/host/layer23/src/mobile/gsm48_mm.c29
-rw-r--r--src/host/layer23/src/mobile/gsm48_rr.c206
-rw-r--r--src/host/layer23/src/mobile/settings.c41
-rw-r--r--src/host/layer23/src/mobile/support.c109
-rw-r--r--src/host/layer23/src/mobile/vty_interface.c155
14 files changed, 790 insertions, 300 deletions
diff --git a/src/host/gsmmap/gsmmap.c b/src/host/gsmmap/gsmmap.c
index 01f3670c..588a65ed 100644
--- a/src/host/gsmmap/gsmmap.c
+++ b/src/host/gsmmap/gsmmap.c
@@ -431,7 +431,8 @@ void kml_cell(FILE *outfp, struct node_cell *cell)
gsm_get_mcc(cell->s.mcc),
gsm_get_mnc(cell->s.mcc, cell->s.mnc));
fprintf(outfp, "\t\t\t\t\t\t<description>\n");
- gsm48_sysinfo_dump(&cell->s, cell->sysinfo.arfcn, print_si, outfp);
+ gsm48_sysinfo_dump(&cell->s, cell->sysinfo.arfcn, print_si, outfp,
+ NULL);
fprintf(outfp, "\t\t\t\t\t\t</description>\n");
fprintf(outfp, "\t\t\t\t\t\t<LookAt>\n");
fprintf(outfp, "\t\t\t\t\t\t\t<longitude>%.8f</longitude>\n",
diff --git a/src/host/layer23/include/osmocom/bb/common/sysinfo.h b/src/host/layer23/include/osmocom/bb/common/sysinfo.h
index e5db54f4..0498e919 100644
--- a/src/host/layer23/include/osmocom/bb/common/sysinfo.h
+++ b/src/host/layer23/include/osmocom/bb/common/sysinfo.h
@@ -49,6 +49,11 @@ struct gsm48_sysinfo {
uint8_t cell_barr; /* 1 = barred */
uint16_t class_barr; /* bit 10 is emergency */
+ /* si1 rest */
+ uint8_t nch;
+ uint8_t nch_position;
+ uint8_t band_ind; /* set for DCS */
+
/* si3 rest */
uint8_t sp;
uint8_t sp_cbq;
@@ -114,8 +119,11 @@ struct gsm48_sysinfo {
uint16_t nb_class_barr; /* bit 10 is emergency */
};
+char *gsm_print_arfcn(uint16_t arfcn);
+uint8_t gsm_refer_pcs(uint16_t arfcn, struct gsm48_sysinfo *s);
int gsm48_sysinfo_dump(struct gsm48_sysinfo *s, uint16_t arfcn,
- void (*print)(void *, const char *, ...), void *priv);
+ void (*print)(void *, const char *, ...), void *priv,
+ uint8_t *freq_map);
int gsm48_decode_lai(struct gsm48_loc_area_id *lai, uint16_t *mcc,
uint16_t *mnc, uint16_t *lac);
int gsm48_decode_chan_h0(struct gsm48_chan_desc *cd, uint8_t *tsc,
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm322.h b/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
index c93e8faa..d94e368d 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm322.h
@@ -82,10 +82,10 @@ struct gsm322_la_list {
struct gsm322_ba_list {
struct llist_head entry;
uint16_t mcc, mnc;
- /* Band allocation for 1024 frequencies.
+ /* Band allocation for 1024+299 frequencies.
* First bit of first index is frequency 0.
*/
- uint8_t freq[128];
+ uint8_t freq[128+38];
};
#define GSM322_CS_FLAG_SUPPORT 0x01 /* frequency is supported by radio */
@@ -143,12 +143,14 @@ struct gsm322_cellsel {
struct osmo_timer_list timer;
uint16_t mcc, mnc; /* current network to search for */
- struct gsm322_cs_list list[1024]; /* cell selection list per freq. */
+ struct gsm322_cs_list list[1024+299];
+ /* cell selection list per frequency. */
uint8_t powerscan; /* currently scanning for power */
uint32_t scan_state; /* special state of current scan */
uint8_t ccch_state; /* special state of current ccch */
uint16_t arfcn; /* current tuned idle mode arfcn */
+ int arfci; /* list index of frequency above */
uint8_t ccch_mode; /* curren CCCH_MODE_* */
struct gsm48_sysinfo *si; /* current sysinfo */
@@ -170,6 +172,8 @@ struct gsm322_msg {
#define GSM322_ALLOC_SIZE sizeof(struct gsm322_msg)
#define GSM322_ALLOC_HEADROOM 0
+uint16_t index2arfcn(int index);
+int arfcn2index(uint16_t arfcn);
int gsm322_init(struct osmocom_ms *ms);
int gsm322_exit(struct osmocom_ms *ms);
struct msgb *gsm322_msgb_alloc(int msg_type);
diff --git a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
index 021b78d8..1cfe401f 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h
@@ -207,6 +207,7 @@ struct gsm48_mm_conn {
int state;
};
+uint8_t gsm48_current_pwr_lev(struct gsm_settings *set, uint16_t arfcn);
int gsm48_mm_init(struct osmocom_ms *ms);
int gsm48_mm_exit(struct osmocom_ms *ms);
struct msgb *gsm48_mmr_msgb_alloc(int msg_type);
diff --git a/src/host/layer23/include/osmocom/bb/mobile/settings.h b/src/host/layer23/include/osmocom/bb/mobile/settings.h
index f666f378..7fa60894 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/settings.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/settings.h
@@ -62,8 +62,16 @@ struct gsm_settings {
uint8_t e_gsm;
uint8_t r_gsm;
uint8_t dcs;
+ uint8_t gsm_850;
+ uint8_t pcs;
+ uint8_t gsm_480;
+ uint8_t gsm_450;
uint8_t class_900;
uint8_t class_dcs;
+ uint8_t class_850;
+ uint8_t class_pcs;
+ uint8_t class_400;
+ uint8_t freq_map[128+38];
uint8_t full_v1;
uint8_t full_v2;
uint8_t full_v3;
@@ -77,6 +85,20 @@ struct gsm_settings {
/* dialing */
struct llist_head abbrev;
+
+ /* EDGE / UMTS / CDMA */
+ uint8_t edge_ms_sup;
+ uint8_t edge_psk_sup;
+ uint8_t edge_psk_uplink;
+ uint8_t class_900_edge;
+ uint8_t class_dcs_pcs_edge;
+ uint8_t umts_fdd;
+ uint8_t umts_tdd;
+ uint8_t cdma_2000;
+ uint8_t dtm;
+ uint8_t class_dtm;
+ uint8_t dtm_mac;
+ uint8_t dtm_egprs;
};
struct gsm_settings_abbrev {
@@ -86,6 +108,7 @@ struct gsm_settings_abbrev {
char name[32];
};
+int gsm_settings_arfcn(struct osmocom_ms *ms);
int gsm_settings_init(struct osmocom_ms *ms);
int gsm_settings_exit(struct osmocom_ms *ms);
char *gsm_check_imei(const char *imei, const char *sv);
diff --git a/src/host/layer23/include/osmocom/bb/mobile/support.h b/src/host/layer23/include/osmocom/bb/mobile/support.h
index cbe6e19b..035e10a3 100644
--- a/src/host/layer23/include/osmocom/bb/mobile/support.h
+++ b/src/host/layer23/include/osmocom/bb/mobile/support.h
@@ -50,9 +50,15 @@ struct gsm_support {
uint8_t e_gsm;
uint8_t r_gsm;
uint8_t dcs;
+ uint8_t gsm_850;
+ uint8_t pcs;
+ uint8_t gsm_480;
+ uint8_t gsm_450;
uint8_t class_900;
uint8_t class_dcs;
- uint8_t freq_map[128];
+ uint8_t class_850;
+ uint8_t class_pcs;
+ uint8_t class_400;
/* multi slot support */
uint8_t ms_sup;
/* ucs2 treatment */
@@ -84,6 +90,20 @@ struct gsm_support {
uint8_t full_v3;
uint8_t half_v1;
uint8_t half_v3;
+
+ /* EDGE / UMTS / CDMA */
+ uint8_t edge_ms_sup;
+ uint8_t edge_psk_sup;
+ uint8_t edge_psk_uplink;
+ uint8_t class_900_edge;
+ uint8_t class_dcs_pcs_edge;
+ uint8_t umts_fdd;
+ uint8_t umts_tdd;
+ uint8_t cdma_2000;
+ uint8_t dtm;
+ uint8_t class_dtm;
+ uint8_t dtm_mac;
+ uint8_t dtm_egprs;
};
struct gsm_support_scan_max {
diff --git a/src/host/layer23/src/common/sysinfo.c b/src/host/layer23/src/common/sysinfo.c
index 5827d756..92a0516d 100644
--- a/src/host/layer23/src/common/sysinfo.c
+++ b/src/host/layer23/src/common/sysinfo.c
@@ -37,14 +37,47 @@
* dumping
*/
+// FIXME: move to libosmocore
+char *gsm_print_arfcn(uint16_t arfcn)
+{
+ static char text[10];
+
+ sprintf(text, "%d", arfcn & 1023);
+ if ((arfcn & ARFCN_PCS))
+ strcat(text, "(PCS)");
+ else if (arfcn >= 512 && arfcn <= 885)
+ strcat(text, "(DCS)");
+
+ return text;
+}
+
+/* check if the cell 'talks' about DCS (0) or PCS (1) */
+uint8_t gsm_refer_pcs(uint16_t arfcn, struct gsm48_sysinfo *s)
+{
+ /* If ARFCN is PCS band, the cell refers to PCS */
+ if ((arfcn & ARFCN_PCS))
+ return 1;
+
+ /* If no SI1 is available, we assume DCS. Be sure to call this
+ * function only if SI 1 is available. */
+ if (!s->si1)
+ return 0;
+
+ /* If band indicator indicates PCS band, the cell refers to PCSThe */
+ return s->band_ind;
+}
+
int gsm48_sysinfo_dump(struct gsm48_sysinfo *s, uint16_t arfcn,
- void (*print)(void *, const char *, ...), void *priv)
+ void (*print)(void *, const char *, ...), void *priv, uint8_t *freq_map)
{
char buffer[81];
- int i, j, k;
+ int i, j, k, index;
+ int refer_pcs = gsm_refer_pcs(arfcn, s);
/* available sysinfos */
- print(priv, "ARFCN = %d\n", arfcn);
+ print(priv, "ARFCN = %s channels 512+ refer to %s\n",
+ gsm_print_arfcn(arfcn),
+ (refer_pcs) ? "PCS (1900)" : "DCS (1800)");
print(priv, "Available SYSTEM INFORMATIONS =");
if (s->si1)
print(priv, " 1");
@@ -142,13 +175,11 @@ int gsm48_sysinfo_dump(struct gsm48_sysinfo *s, uint16_t arfcn,
/* frequency map */
for (i = 0; i < 1024; i += 64) {
- if (i < 10)
- sprintf(buffer, " %d ", i);
- else if (i < 100)
- sprintf(buffer, " %d ", i);
- else
- sprintf(buffer, " %d ", i);
+ sprintf(buffer, " %3d ", i);
for (j = 0; j < 64; j++) {
+ index = i+j;
+ if (refer_pcs && index >= 512 && index <= 885)
+ index = index-512+1024;
if ((s->freq[i+j].mask & FREQ_TYPE_SERV))
buffer[j + 5] = 'S';
else if ((s->freq[i+j].mask & FREQ_TYPE_NCELL)
@@ -158,9 +189,14 @@ int gsm48_sysinfo_dump(struct gsm48_sysinfo *s, uint16_t arfcn,
buffer[j + 5] = 'n';
else if ((s->freq[i+j].mask & FREQ_TYPE_REP))
buffer[j + 5] = 'r';
- else
+ else if (!freq_map || (freq_map[index >> 3]
+ & (1 << (index & 7))))
buffer[j + 5] = '.';
+ else
+ buffer[j + 5] = ' ';
}
+ for (; j < 64; j++)
+ buffer[j + 5] = ' ';
sprintf(buffer + 69, " %d", i + 63);
print(priv, "%s\n", buffer);
}
@@ -461,6 +497,22 @@ static int gsm48_decode_rach_ctl_neigh(struct gsm48_sysinfo *s,
static int gsm48_decode_si1_rest(struct gsm48_sysinfo *s, uint8_t *si,
uint8_t len)
{
+ struct bitvec bv;
+
+ memset(&bv, 0, sizeof(bv));
+ bv.data_len = len;
+ bv.data = si;
+
+ /* Optional Selection Parameters */
+ if (bitvec_get_bit_high(&bv) == H) {
+ s->nch = 1;
+ s->nch_position = bitvec_get_uint(&bv, 5);
+ } else
+ s->nch = 0;
+ if (bitvec_get_bit_high(&bv) == H)
+ s->band_ind = 1;
+ else
+ s->band_ind = 0;
return 0;
}
@@ -481,23 +533,30 @@ static int gsm48_decode_si3_rest(struct gsm48_sysinfo *s, uint8_t *si,
s->sp_cro = bitvec_get_uint(&bv, 6);
s->sp_to = bitvec_get_uint(&bv, 3);
s->sp_pt = bitvec_get_uint(&bv, 5);
- }
+ } else
+ s->sp = 0;
/* Optional Power Offset */
if (bitvec_get_bit_high(&bv) == H) {
s->po = 1;
s->po_value = bitvec_get_uint(&bv, 3);
- }
+ } else
+ s->po = 0;
/* System Onformation 2ter Indicator */
if (bitvec_get_bit_high(&bv) == H)
s->si2ter_ind = 1;
+ else
+ s->si2ter_ind = 0;
/* Early Classark Sending Control */
if (bitvec_get_bit_high(&bv) == H)
s->ecsm = 1;
+ else
+ s->ecsm = 0;
/* Scheduling if and where */
if (bitvec_get_bit_high(&bv) == H) {
s->sched = 1;
s->sched_where = bitvec_get_uint(&bv, 3);
- }
+ } else
+ s->sched = 0;
/* GPRS Indicator */
s->gi_ra_colour = bitvec_get_uint(&bv, 3);
s->gi_si13_pos = bitvec_get_uint(&bv, 1);
diff --git a/src/host/layer23/src/mobile/app_mobile.c b/src/host/layer23/src/mobile/app_mobile.c
index e37ac989..1dc585a5 100644
--- a/src/host/layer23/src/mobile/app_mobile.c
+++ b/src/host/layer23/src/mobile/app_mobile.c
@@ -159,6 +159,7 @@ int mobile_init(struct osmocom_ms *ms)
{
int rc;
+ gsm_settings_arfcn(ms);
lapdm_init(&ms->l2_entity.lapdm_dcch, ms);
lapdm_init(&ms->l2_entity.lapdm_acch, ms);
gsm_sim_init(ms);
diff --git a/src/host/layer23/src/mobile/gsm322.c b/src/host/layer23/src/mobile/gsm322.c
index 2bd4f9c7..bcf3c781 100644
--- a/src/host/layer23/src/mobile/gsm322.c
+++ b/src/host/layer23/src/mobile/gsm322.c
@@ -39,6 +39,8 @@
#include <osmocom/bb/mobile/vty.h>
#include <osmocom/bb/mobile/app_mobile.h>
+const char *ba_version = "osmocom BA V1\n";
+
extern void *l23_ctx;
static void gsm322_cs_timeout(void *arg);
@@ -74,7 +76,7 @@ int hack;
*
* The states are:
*
- * - cs->list[0..1023].xxx for each cell, where
+ * - cs->list[0..(1023+299)].xxx for each cell, where
* - flags and rxlev 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.
@@ -103,7 +105,7 @@ int hack;
*
* uint16_t mcc
* uint16_t mcc
- * uint8_t freq[128];
+ * uint8_t freq[128+38];
* where frequency 0 is bit 0 of first byte
*
* If not end-of-file, the next BA list is stored.
@@ -127,7 +129,7 @@ int hack;
* The "forbidden LAs for roaming" list stores all location areas where roaming
* was not allowed.
*
- * * cs->list[1024]
+ * * cs->list[1024+299]
*
* This list stores measurements and cell informations during cell selection
* process. It can be used to speed up repeated cell selection.
@@ -222,6 +224,20 @@ int gsm322_cs_sendmsg(struct osmocom_ms *ms, struct msgb *msg)
* support
*/
+uint16_t index2arfcn(int index)
+{
+ if (index >= 1024)
+ return (index-1024+512) | ARFCN_PCS;
+ return index;
+}
+
+int arfcn2index(uint16_t arfcn)
+{
+ if ((arfcn & ARFCN_PCS))
+ return (arfcn & 1023)-512+1024;
+ return arfcn & 1023;
+}
+
char *gsm_print_rxlev(uint8_t rxlev)
{
static char string[5];
@@ -242,20 +258,22 @@ static int gsm322_sync_to_cell(struct gsm322_cellsel *cs)
cs->ccch_state = GSM322_CCCH_ST_INIT;
if (s && s->si3) {
if (s->ccch_conf == 1) {
- LOGP(DCS, LOGL_INFO, "Sync to ARFCN=%d rxlev=%s "
- "(Sysinfo, ccch mode COMB)\n", cs->arfcn,
- gsm_print_rxlev(cs->list[cs->arfcn].rxlev));
+ LOGP(DCS, LOGL_INFO, "Sync to ARFCN=%s rxlev=%s "
+ "(Sysinfo, ccch mode COMB)\n",
+ gsm_print_arfcn(cs->arfcn),
+ gsm_print_rxlev(cs->list[cs->arfci].rxlev));
cs->ccch_mode = CCCH_MODE_COMBINED;
} else {
- LOGP(DCS, LOGL_INFO, "Sync to ARFCN=%d rxlev=%s "
- "(Sysinfo, ccch mode NON-COMB)\n", cs->arfcn,
- gsm_print_rxlev(cs->list[cs->arfcn].rxlev));
+ LOGP(DCS, LOGL_INFO, "Sync to ARFCN=%s rxlev=%s "
+ "(Sysinfo, ccch mode NON-COMB)\n",
+ gsm_print_arfcn(cs->arfcn),
+ gsm_print_rxlev(cs->list[cs->arfci].rxlev));
cs->ccch_mode = CCCH_MODE_NON_COMBINED;
}
} else {
- LOGP(DCS, LOGL_INFO, "Sync to ARFCN=%d rxlev=%s (No sysinfo "
- "yet, ccch mode NONE)\n", cs->arfcn,
- gsm_print_rxlev(cs->list[cs->arfcn].rxlev));
+ LOGP(DCS, LOGL_INFO, "Sync to ARFCN=%s rxlev=%s (No sysinfo "
+ "yet, ccch mode NONE)\n", gsm_print_arfcn(cs->arfcn),
+ gsm_print_rxlev(cs->list[cs->arfci].rxlev));
cs->ccch_mode = CCCH_MODE_NONE;
}
@@ -289,8 +307,8 @@ static void print_dcs(void *priv, const char *fmt, ...)
va_end(args);
if (buffer[0])
-// LOGP(DCS, LOGL_INFO, "%s", buffer);
- printf("%s", buffer);
+ LOGP(DCS, LOGL_INFO, "%s", buffer);
+// printf("%s", buffer);
}
/* del forbidden LA */
@@ -374,7 +392,7 @@ int gsm322_is_plmn_avail(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc)
{
int i;
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if (cs->list[i].sysinfo
&& cs->list[i].sysinfo->mcc == mcc
&& cs->list[i].sysinfo->mnc == mnc)
@@ -389,7 +407,7 @@ int gsm322_is_hplmn_avail(struct gsm322_cellsel *cs, char *imsi)
{
int i;
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if (cs->list[i].sysinfo
&& gsm_match_mnc(cs->list[i].sysinfo->mcc,
cs->list[i].sysinfo->mnc, imsi))
@@ -598,7 +616,7 @@ static int gsm322_sort_list(struct osmocom_ms *ms)
/* Create a temporary list of all networks */
INIT_LLIST_HEAD(&temp_list);
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if (!(cs->list[i].flags & GSM322_CS_FLAG_TEMP_AA)
|| !cs->list[i].sysinfo)
continue;
@@ -1523,7 +1541,7 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any, int plmn_allowed)
flags = mask; /* all masked flags are requied */
/* loop through all scanned frequencies and select cell */
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
cs->list[i].flags &= ~GSM322_CS_FLAG_TEMP_AA;
s = cs->list[i].sysinfo;
@@ -1536,8 +1554,9 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any, int plmn_allowed)
// TODO: C1 is also dependant on power class and max power
if (rxlev2dbm(cs->list[i].rxlev) < s->rxlev_acc_min_db
&& !set->stick) {
- LOGP(DCS, LOGL_INFO, "Skip frequency %d: C1 criteria "
- "not met. (rxlev %s < min %d)\n", i,
+ LOGP(DCS, LOGL_INFO, "Skip ARFCN %s: C1 criteria "
+ "not met. (rxlev %s < min %d)\n",
+ gsm_print_arfcn(index2arfcn(i)),
gsm_print_rxlev(cs->list[i].rxlev),
s->rxlev_acc_min_db);
continue;
@@ -1546,16 +1565,18 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any, int plmn_allowed)
/* if cell is barred and we don't override */
if (!subscr->acc_barr
&& (cs->list[i].flags & GSM322_CS_FLAG_BARRED)) {
- LOGP(DCS, LOGL_INFO, "Skip frequency %d: Cell is "
- "barred.\n", i);
+ LOGP(DCS, LOGL_INFO, "Skip ARFCN %s: Cell is "
+ "barred.\n", gsm_print_arfcn(index2arfcn(i)));
continue;
}
/* if cell is in list of forbidden LAs */
if ((cs->list[i].flags & GSM322_CS_FLAG_FORBIDD)) {
- LOGP(DCS, LOGL_INFO, "Skip frequency %d: Cell is in "
+ LOGP(DCS, LOGL_INFO, "Skip ARFCN %s: Cell is in "
"list of forbidden LAs. (mcc=%s mnc=%s "
- "lai=%04x)\n", i, gsm_print_mcc(s->mcc),
+ "lai=%04x)\n",
+ gsm_print_arfcn(index2arfcn(i)),
+ gsm_print_mcc(s->mcc),
gsm_print_mnc(s->mnc), s->lac);
continue;
}
@@ -1563,8 +1584,9 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any, int plmn_allowed)
/* if cell is in list of forbidden PLMNs */
if (plmn_allowed && gsm_subscr_is_forbidden_plmn(subscr,
s->mcc, s->mnc)) {
- LOGP(DCS, LOGL_INFO, "Skip frequency %d: Cell is in "
- "list of forbidden PLMNs. (mcc=%s mnc=%s)\n", i,
+ LOGP(DCS, LOGL_INFO, "Skip ARFCN %s: Cell is in "
+ "list of forbidden PLMNs. (mcc=%s mnc=%s)\n",
+ gsm_print_arfcn(index2arfcn(i)),
gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc));
continue;
}
@@ -1572,9 +1594,11 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any, int plmn_allowed)
/* if we have no access to the cell and we don't override */
if (!subscr->acc_barr
&& !(acc_class & (s->class_barr ^ 0xffff))) {
- LOGP(DCS, LOGL_INFO, "Skip frequency %d: Class is "
+ LOGP(DCS, LOGL_INFO, "Skip ARFCN %s: Class is "
"barred for out access. (access=%04x "
- "barred=%04x)\n", i, acc_class, s->class_barr);
+ "barred=%04x)\n",
+ gsm_print_arfcn(index2arfcn(i)),
+ acc_class, s->class_barr);
continue;
}
@@ -1584,15 +1608,17 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any, int plmn_allowed)
/* if we search a specific PLMN, but it does not match */
if (!any && cs->mcc && (cs->mcc != s->mcc
|| cs->mnc != s->mnc)) {
- LOGP(DCS, LOGL_INFO, "Skip frequency %d: PLMN of cell "
+ LOGP(DCS, LOGL_INFO, "Skip ARFCN %s: PLMN of cell "
"does not match target PLMN. (mcc=%s "
- "mnc=%s)\n", i, gsm_print_mcc(s->mcc),
+ "mnc=%s)\n", gsm_print_arfcn(index2arfcn(i)),
+ gsm_print_mcc(s->mcc),
gsm_print_mnc(s->mnc));
continue;
}
- LOGP(DCS, LOGL_INFO, "Cell frequency %d: Cell found, (rxlev=%s "
- "mcc=%s mnc=%s lac=%04x %s, %s)\n", i,
+ LOGP(DCS, LOGL_INFO, "Cell ARFCN %s: Cell found, (rxlev=%s "
+ "mcc=%s mnc=%s lac=%04x %s, %s)\n",
+ gsm_print_arfcn(index2arfcn(i)),
gsm_print_rxlev(cs->list[i].rxlev),
gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc), s->lac,
gsm_get_mcc(s->mcc), gsm_get_mnc(s->mcc, s->mnc));
@@ -1605,7 +1631,8 @@ static int gsm322_cs_select(struct osmocom_ms *ms, int any, int plmn_allowed)
}
if (found >= 0)
- LOGP(DCS, LOGL_INFO, "Cell frequency %d selected.\n", found);
+ LOGP(DCS, LOGL_INFO, "Cell ARFCN %s selected.\n",
+ gsm_print_arfcn(index2arfcn(found)));
return found;
}
@@ -1628,7 +1655,7 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
|| cs->state == GSM322_C5_CHOOSE_CELL)
mask |= GSM322_CS_FLAG_BA;
flags = mask; /* all masked flags are requied */
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
#ifndef SKIP_MAX_PER_BAND
/* skip if band has enough frequencies scanned (3.2.1) */
for (j = 0; gsm_sup_smax[j].max; j++) {
@@ -1698,9 +1725,10 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
new_c_state(cs, GSM322_C3_CAMPED_NORMALLY);
cs->arfcn = cs->sel_arfcn;
- LOGP(DCS, LOGL_INFO, "Tuning back to frequency %d (rxlev "
- "%s).\n", cs->arfcn,
- gsm_print_rxlev(cs->list[cs->arfcn].rxlev));
+ cs->arfci = arfcn2index(cs->arfcn);
+ LOGP(DCS, LOGL_INFO, "Tuning back to frequency %s (rxlev "
+ "%s).\n", gsm_print_arfcn(cs->arfcn),
+ gsm_print_rxlev(cs->list[cs->arfci].rxlev));
hack = 1;
gsm322_sync_to_cell(cs);
@@ -1727,10 +1755,12 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
if (found >= 0) {
struct gsm322_plmn *plmn = &ms->plmn;
- LOGP(DCS, LOGL_INFO, "Tune to frequency %d.\n", found);
+ LOGP(DCS, LOGL_INFO, "Tune to frequency index %d.\n",
+ found);
/* tune */
- cs->arfcn = found;
- cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->arfci = found;
+ cs->arfcn = index2arfcn(cs->arfci);
+ cs->si = cs->list[cs->arfci].sysinfo;
hack = 1;
gsm322_sync_to_cell(cs);
@@ -1794,23 +1824,25 @@ static int gsm322_cs_scan(struct osmocom_ms *ms)
*/
/* Tune to frequency for a while, to receive broadcasts. */
- cs->arfcn = weight & 1023;
- LOGP(DCS, LOGL_DEBUG, "Scanning frequency %d (rxlev %s).\n", cs->arfcn,
- gsm_print_rxlev(cs->list[cs->arfcn].rxlev));
+ cs->arfci = weight & 0xffff;
+ cs->arfcn = index2arfcn(cs->arfci);
+ LOGP(DCS, LOGL_DEBUG, "Scanning frequency %s (rxlev %s).\n",
+ gsm_print_arfcn(cs->arfcn),
+ gsm_print_rxlev(cs->list[cs->arfci].rxlev));
hack = 1;
gsm322_sync_to_cell(cs);
/* Allocate/clean system information. */
- cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_SYSINFO;
- if (cs->list[cs->arfcn].sysinfo)
- memset(cs->list[cs->arfcn].sysinfo, 0,
+ cs->list[cs->arfci].flags &= ~GSM322_CS_FLAG_SYSINFO;
+ if (cs->list[cs->arfci].sysinfo)
+ memset(cs->list[cs->arfci].sysinfo, 0,
sizeof(struct gsm48_sysinfo));
else
- cs->list[cs->arfcn].sysinfo = talloc_zero(l23_ctx,
+ cs->list[cs->arfci].sysinfo = talloc_zero(l23_ctx,
struct gsm48_sysinfo);
- if (!cs->list[cs->arfcn].sysinfo)
+ if (!cs->list[cs->arfci].sysinfo)
exit(-ENOMEM);
- cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->si = cs->list[cs->arfci].sysinfo;
/* increase scan counter for each maximum scan range */
#ifndef SKIP_MAX_PER_BAND
@@ -1849,37 +1881,37 @@ static int gsm322_cs_store(struct osmocom_ms *ms)
}
/* store sysinfo */
- cs->list[cs->arfcn].flags |= GSM322_CS_FLAG_SYSINFO;
+ cs->list[cs->arfci].flags |= GSM322_CS_FLAG_SYSINFO;
if (s->cell_barr
- && !(cs->list[cs->arfcn].sysinfo && cs->list[cs->arfcn].sysinfo->sp &&
- cs->list[cs->arfcn].sysinfo->sp_cbq))
- cs->list[cs->arfcn].flags |= GSM322_CS_FLAG_BARRED;
+ && !(cs->list[cs->arfci].sysinfo && cs->list[cs->arfci].sysinfo->sp &&
+ cs->list[cs->arfci].sysinfo->sp_cbq))
+ cs->list[cs->arfci].flags |= GSM322_CS_FLAG_BARRED;
else
- cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_BARRED;
+ cs->list[cs->arfci].flags &= ~GSM322_CS_FLAG_BARRED;
#if 0
- cs->list[cs->arfcn].min_db = s->rxlev_acc_min_db;
- cs->list[cs->arfcn].class_barr = s->class_barr;
- cs->list[cs->arfcn].max_pwr = s->ms_txpwr_max_ccch;
+ cs->list[cs->arfci].min_db = s->rxlev_acc_min_db;
+ cs->list[cs->arfci].class_barr = s->class_barr;
+ cs->list[cs->arfci].max_pwr = s->ms_txpwr_max_ccch;
#endif
/* store selected network */
if (s->mcc) {
#if 0
- cs->list[cs->arfcn].mcc = s->mcc;
- cs->list[cs->arfcn].mnc = s->mnc;
- cs->list[cs->arfcn].lac = s->lac;
+ cs->list[cs->arfci].mcc = s->mcc;
+ cs->list[cs->arfci].mnc = s->mnc;
+ cs->list[cs->arfci].lac = s->lac;
#endif
if (gsm322_is_forbidden_la(ms, s->mcc, s->mnc, s->lac))
- cs->list[cs->arfcn].flags |= GSM322_CS_FLAG_FORBIDD;
+ cs->list[cs->arfci].flags |= GSM322_CS_FLAG_FORBIDD;
else
- cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_FORBIDD;
+ cs->list[cs->arfci].flags &= ~GSM322_CS_FLAG_FORBIDD;
}
- LOGP(DCS, LOGL_DEBUG, "Scan frequency %d: Cell found. (rxlev %s "
- "mcc %s mnc %s lac %04x)\n", cs->arfcn,
- gsm_print_rxlev(cs->list[cs->arfcn].rxlev),
+ LOGP(DCS, LOGL_DEBUG, "Scan frequency %s: Cell found. (rxlev %s "
+ "mcc %s mnc %s lac %04x)\n", gsm_print_arfcn(cs->arfcn),
+ gsm_print_rxlev(cs->list[cs->arfci].rxlev),
gsm_print_mcc(s->mcc), gsm_print_mnc(s->mnc), s->lac);
/* special case for PLMN search */
@@ -1922,8 +1954,9 @@ static int gsm322_cs_store(struct osmocom_ms *ms)
LOGP(DCS, LOGL_INFO, "Tune to frequency %d.\n", found);
/* tune */
- cs->arfcn = found;
- cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->arfci = found;
+ cs->arfcn = index2arfcn(cs->arfci);
+ cs->si = cs->list[cs->arfci].sysinfo;
hack = 1;
gsm322_sync_to_cell(cs);
@@ -1977,8 +2010,8 @@ struct gsm322_ba_list *gsm322_cs_sysinfo_sacch(struct osmocom_ms *ms)
struct gsm322_cellsel *cs = &ms->cellsel;
struct gsm48_sysinfo *s;
struct gsm322_ba_list *ba = NULL;
- int i;
- uint8_t freq[128];
+ int i, refer_pcs;
+ uint8_t freq[128+38];
if (!cs) {
LOGP(DCS, LOGL_INFO, "No BA, because no cell selected\n");
@@ -2003,11 +2036,16 @@ struct gsm322_ba_list *gsm322_cs_sysinfo_sacch(struct osmocom_ms *ms)
llist_add_tail(&ba->entry, &cs->ba_list);
}
/* update (add) ba list */
+ refer_pcs = gsm_refer_pcs(cs->arfcn, s);
memset(freq, 0, sizeof(freq));
for (i = 0; i <= 1023; i++) {
if ((s->freq[i].mask & (FREQ_TYPE_SERV
- | FREQ_TYPE_NCELL | FREQ_TYPE_REP)))
- freq[i >> 3] |= (1 << (i & 7));
+ | FREQ_TYPE_NCELL | FREQ_TYPE_REP))) {
+ if (refer_pcs && i >= 512 && i <= 810)
+ freq[(i-512+1024) >> 3] |= (1 << (i&7));
+ else
+ freq[i >> 3] |= (1 << (i & 7));
+ }
}
if (!!memcmp(freq, ba->freq, sizeof(freq))) {
LOGP(DCS, LOGL_INFO, "New BA list (mcc=%s mnc=%s "
@@ -2026,8 +2064,8 @@ 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];
+ int i, refer_pcs;
+ uint8_t freq[128+38];
/* find or create ba list */
ba = gsm322_find_ba_list(cs, s->mcc, s->mnc);
@@ -2040,12 +2078,17 @@ static int gsm322_store_ba_list(struct gsm322_cellsel *cs,
llist_add_tail(&ba->entry, &cs->ba_list);
}
/* update ba list */
+ refer_pcs = gsm_refer_pcs(cs->arfcn, s);
memset(freq, 0, sizeof(freq));
- freq[cs->arfcn >> 3] |= (1 << (cs->arfcn & 7));
+ freq[(cs->arfci) >> 3] |= (1 << (cs->arfci & 7));
for (i = 0; i <= 1023; i++) {
if ((s->freq[i].mask &
- (FREQ_TYPE_SERV | FREQ_TYPE_NCELL | FREQ_TYPE_REP)))
- freq[i >> 3] |= (1 << (i & 7));
+ (FREQ_TYPE_SERV | FREQ_TYPE_NCELL | FREQ_TYPE_REP))) {
+ if (refer_pcs && i >= 512 && i <= 810)
+ freq[(i-512+1024) >> 3] |= (1 << (i & 7));
+ else
+ freq[i >> 3] |= (1 << (i & 7));
+ }
}
if (!!memcmp(freq, ba->freq, sizeof(freq))) {
LOGP(DCS, LOGL_INFO, "New BA list (mcc=%s mnc=%s "
@@ -2111,18 +2154,18 @@ static int gsm322_c_camp_sysinfo_bcch(struct osmocom_ms *ms, struct msgb *msg)
if (gm->sysinfo == GSM48_MT_RR_SYSINFO_1) {
/* check if cell becomes barred */
if (!subscr->acc_barr && s->cell_barr
- && !(cs->list[cs->arfcn].sysinfo
- && cs->list[cs->arfcn].sysinfo->sp
- && cs->list[cs->arfcn].sysinfo->sp_cbq)) {
+ && !(cs->list[cs->arfci].sysinfo
+ && cs->list[cs->arfci].sysinfo->sp
+ && cs->list[cs->arfci].sysinfo->sp_cbq)) {
LOGP(DCS, LOGL_INFO, "Cell becomes barred.\n");
trigger_resel:
/* mark cell as unscanned */
- cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_SYSINFO;
- if (cs->list[cs->arfcn].sysinfo) {
- LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%d\n",
- cs->arfcn);
- talloc_free(cs->list[cs->arfcn].sysinfo);
- cs->list[cs->arfcn].sysinfo = NULL;
+ cs->list[cs->arfci].flags &= ~GSM322_CS_FLAG_SYSINFO;
+ if (cs->list[cs->arfci].sysinfo) {
+ LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%s\n",
+ gsm_print_arfcn(cs->arfcn));
+ talloc_free(cs->list[cs->arfci].sysinfo);
+ cs->list[cs->arfci].sysinfo = NULL;
gsm322_unselect_cell(cs);
}
/* trigger reselection without queueing,
@@ -2220,11 +2263,12 @@ static void gsm322_cs_timeout(void *arg)
LOGP(DCS, LOGL_INFO, "Cell selection failed, read timeout.\n");
/* remove system information */
- cs->list[cs->arfcn].flags &= ~GSM322_CS_FLAG_SYSINFO;
- if (cs->list[cs->arfcn].sysinfo) {
- LOGP(DCS, LOGL_DEBUG, "free sysinfo arfcn=%d\n", cs->arfcn);
- talloc_free(cs->list[cs->arfcn].sysinfo);
- cs->list[cs->arfcn].sysinfo = NULL;
+ cs->list[cs->arfci].flags &= ~GSM322_CS_FLAG_SYSINFO;
+ if (cs->list[cs->arfci].sysinfo) {
+ LOGP(DCS, LOGL_DEBUG, "free sysinfo arfcn=%s\n",
+ gsm_print_arfcn(cs->arfcn));
+ talloc_free(cs->list[cs->arfci].sysinfo);
+ cs->list[cs->arfci].sysinfo = NULL;
gsm322_unselect_cell(cs);
}
@@ -2254,7 +2298,7 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
/* in case of sticking to a cell, we only select it */
if (set->stick) {
LOGP(DCS, LOGL_DEBUG, "Scanning power for sticked cell.\n");
- i = set->stick_arfcn;
+ i = arfcn2index(set->stick_arfcn);
if ((cs->list[i].flags & mask) == flags)
s = e = i;
} else {
@@ -2268,7 +2312,7 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
} else
LOGP(DCS, LOGL_DEBUG, "Scanning power for all "
"frequencies.\n");
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if ((cs->list[i].flags & mask) == flags) {
s = e = i;
break;
@@ -2283,8 +2327,8 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
/* stop power level scanning */
cs->powerscan = 0;
- /* check if not signal is found */
- for (i = 0; i <= 1023; i++) {
+ /* check if no signal is found */
+ for (i = 0; i <= 1023+299; i++) {
if ((cs->list[i].flags & GSM322_CS_FLAG_SIGNAL))
found++;
}
@@ -2294,7 +2338,7 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
LOGP(DCS, LOGL_INFO, "Found no frequency.\n");
/* on normal cell selection, start over */
if (cs->state == GSM322_C1_NORMAL_CELL_SEL) {
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
/* clear flag that this was scanned */
cs->list[i].flags &=
~(GSM322_CS_FLAG_POWER
@@ -2302,8 +2346,9 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
| GSM322_CS_FLAG_SYSINFO);
if (cs->list[i].sysinfo) {
LOGP(DCS, LOGL_INFO, "free "
- "sysinfo arfcn=%d\n",
- i);
+ "sysinfo arfcn=%s\n",
+ gsm_print_arfcn(
+ index2arfcn(i)));
talloc_free(
cs->list[i].sysinfo);
cs->list[i].sysinfo = NULL;
@@ -2334,10 +2379,12 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
new_c_state(cs, GSM322_C3_CAMPED_NORMALLY);
cs->arfcn = cs->sel_arfcn;
+ cs->arfci = arfcn2index(cs->arfcn);
LOGP(DCS, LOGL_INFO, "Tuning back to frequency "
- "%d (rxlev %s).\n", cs->arfcn,
+ "%s (rxlev %s).\n",
+ gsm_print_arfcn(cs->arfcn),
gsm_print_rxlev(
- cs->list[cs->arfcn].rxlev));
+ cs->list[cs->arfci].rxlev));
hack = 1;
gsm322_sync_to_cell(cs);
@@ -2357,7 +2404,9 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
/* search last frequency to scan (en block) */
e = i;
if (!set->stick) {
- for (i = s + 1; i <= 1023; i++) {
+ for (i = s + 1; i <= 1023+299; i++) {
+ if (i == 1024)
+ break;
if ((cs->list[i].flags & mask) == flags)
e = i;
else
@@ -2365,7 +2414,9 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
}
}
- LOGP(DCS, LOGL_DEBUG, "Scanning frequencies. (%d..%d)\n", s, e);
+ LOGP(DCS, LOGL_DEBUG, "Scanning frequencies. (%s..%s)\n",
+ gsm_print_arfcn(index2arfcn(s)),
+ gsm_print_arfcn(index2arfcn(e)));
/* start scan on radio interface */
if (!cs->powerscan) {
@@ -2374,7 +2425,7 @@ static int gsm322_cs_powerscan(struct osmocom_ms *ms)
}
//#warning TESTING!!!!
//usleep(300000);
- return l1ctl_tx_pm_req_range(ms, s, e);
+ return l1ctl_tx_pm_req_range(ms, index2arfcn(s), index2arfcn(e));
}
int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
@@ -2397,12 +2448,12 @@ int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
cs = &ms->cellsel;
if (!cs->powerscan)
return -EINVAL;
- i = mr->band_arfcn & 1023;
+ i = arfcn2index(mr->band_arfcn);
rxlev = mr->rx_lev;
if ((cs->list[i].flags & GSM322_CS_FLAG_POWER)) {
- LOGP(DCS, LOGL_ERROR, "Getting PM for frequency %d "
+ LOGP(DCS, LOGL_ERROR, "Getting PM for ARFCN %s "
"twice. Overwriting the first! Please fix "
- "prim_pm.c\n", i);
+ "prim_pm.c\n", gsm_print_arfcn(index2arfcn(i)));
}
cs->list[i].rxlev = rxlev;
cs->list[i].flags |= GSM322_CS_FLAG_POWER;
@@ -2411,8 +2462,9 @@ int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
if (rxlev2dbm(rxlev) >= ms->settings.min_rxlev_db
|| ms->settings.stick) {
cs->list[i].flags |= GSM322_CS_FLAG_SIGNAL;
- LOGP(DCS, LOGL_INFO, "Found signal (frequency %d "
- "rxlev %s (%d))\n", i,
+ LOGP(DCS, LOGL_INFO, "Found signal (ARFCN %s "
+ "rxlev %s (%d))\n",
+ gsm_print_arfcn(index2arfcn(i)),
gsm_print_rxlev(rxlev), rxlev);
}
break;
@@ -2429,9 +2481,9 @@ int gsm322_l1_signal(unsigned int subsys, unsigned int signal,
ms = fr->ms;
cs = &ms->cellsel;
if (cs->ccch_state == GSM322_CCCH_ST_INIT) {
- LOGP(DCS, LOGL_INFO, "Channel synched. (ARFCN=%d, "
- "snr=%u, BSIC=%u)\n", cs->arfcn, fr->snr,
- fr->bsic);
+ LOGP(DCS, LOGL_INFO, "Channel synched. (ARFCN=%s, "
+ "snr=%u, BSIC=%u)\n",
+ gsm_print_arfcn(cs->arfcn), fr->snr, fr->bsic);
cs->ccch_state = GSM322_CCCH_ST_SYNC;
if (cs->si)
cs->si->bsic = fr->bsic;
@@ -2553,12 +2605,13 @@ static int gsm322_c_plmn_search(struct osmocom_ms *ms, struct msgb *msg)
new_c_state(cs, GSM322_PLMN_SEARCH);
/* mark all frequencies except our own BA to be scanned */
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
cs->list[i].flags &= ~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
if (cs->list[i].sysinfo) {
- LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%d\n", i);
+ LOGP(DCS, LOGL_INFO, "free sysinfo ARFCN=%s\n",
+ gsm_print_arfcn(index2arfcn(i)));
talloc_free(cs->list[i].sysinfo);
cs->list[i].sysinfo = NULL;
gsm322_unselect_cell(cs);
@@ -2576,21 +2629,21 @@ static int gsm322_c_plmn_search(struct osmocom_ms *ms, struct msgb *msg)
static int gsm322_c_hplmn_search(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm322_cellsel *cs = &ms->cellsel;
- int i;
+ int i, sel_i = arfcn2index(cs->sel_arfcn);
new_c_state(cs, GSM322_HPLMN_SEARCH);
/* mark all frequencies except our own BA to be scanned */
- for (i = 0; i <= 1023; i++) {
- if (i != cs->sel_arfcn
+ for (i = 0; i <= 1023+299; i++) {
+ if (i != sel_i
&& (cs->list[i].flags & GSM322_CS_FLAG_SYSINFO)
&& !(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) {
- LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%d\n",
- i);
+ LOGP(DCS, LOGL_INFO, "free sysinfo ARFCN=%s\n",
+ gsm_print_arfcn(index2arfcn(i)));
talloc_free(cs->list[i].sysinfo);
cs->list[i].sysinfo = NULL;
}
@@ -2613,7 +2666,7 @@ static int gsm322_c_stored_cell_sel(struct osmocom_ms *ms, struct gsm322_ba_list
new_c_state(cs, GSM322_C2_STORED_CELL_SEL);
/* flag all frequencies that are in current band allocation */
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if ((ba->freq[i >> 3] & (1 << (i & 7))))
cs->list[i].flags |= GSM322_CS_FLAG_BA;
else
@@ -2635,13 +2688,13 @@ static int gsm322_c_normal_cell_sel(struct osmocom_ms *ms, struct msgb *msg)
/* 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+299; i++) {
cs->list[i].flags &= ~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
if (cs->list[i].sysinfo) {
- LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%d\n",
- i);
+ LOGP(DCS, LOGL_INFO, "free sysinfo ARFCN=%s\n",
+ gsm_print_arfcn(index2arfcn(i)));
talloc_free(cs->list[i].sysinfo);
cs->list[i].sysinfo = NULL;
}
@@ -2668,13 +2721,13 @@ static int gsm322_c_any_cell_sel(struct osmocom_ms *ms, struct msgb *msg)
|| cs->state == GSM322_C8_ANY_CELL_RESEL) {
int i;
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
cs->list[i].flags &= ~(GSM322_CS_FLAG_POWER
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
if (cs->list[i].sysinfo) {
- LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%d\n",
- i);
+ LOGP(DCS, LOGL_INFO, "free sysinfo ARFCN=%s\n",
+ gsm_print_arfcn(index2arfcn(i)));
talloc_free(cs->list[i].sysinfo);
cs->list[i].sysinfo = NULL;
}
@@ -2738,8 +2791,9 @@ static int gsm322_c_camp_normally(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
struct msgb *nmsg;
- LOGP(DSUM, LOGL_INFO, "Camping normally on cell (arfcn=%d mcc=%s "
- "mnc=%s %s, %s)\n", cs->sel_arfcn, gsm_print_mcc(cs->sel_mcc),
+ LOGP(DSUM, LOGL_INFO, "Camping normally on cell (ARFCN=%s mcc=%s "
+ "mnc=%s %s, %s)\n", gsm_print_arfcn(cs->sel_arfcn),
+ gsm_print_mcc(cs->sel_mcc),
gsm_print_mnc(cs->sel_mnc), gsm_get_mcc(cs->sel_mcc),
gsm_get_mnc(cs->sel_mcc, cs->sel_mnc));
@@ -2760,8 +2814,9 @@ static int gsm322_c_camp_any_cell(struct osmocom_ms *ms, struct msgb *msg)
struct gsm322_cellsel *cs = &ms->cellsel;
struct msgb *nmsg;
- LOGP(DSUM, LOGL_INFO, "Camping on any cell (arfcn=%d mcc=%s "
- "mnc=%s %s, %s)\n", cs->sel_arfcn, gsm_print_mcc(cs->sel_mcc),
+ LOGP(DSUM, LOGL_INFO, "Camping on any cell (ARFCN=%s mcc=%s "
+ "mnc=%s %s, %s)\n", gsm_print_arfcn(cs->sel_arfcn),
+ gsm_print_mcc(cs->sel_mcc),
gsm_print_mnc(cs->sel_mnc), gsm_get_mcc(cs->sel_mcc),
gsm_get_mnc(cs->sel_mcc, cs->sel_mnc));
@@ -2779,24 +2834,39 @@ static int gsm322_c_camp_any_cell(struct osmocom_ms *ms, struct msgb *msg)
/* create temporary ba range with given frequency ranges */
struct gsm322_ba_list *gsm322_cs_ba_range(struct osmocom_ms *ms,
- uint32_t *range, uint8_t ranges)
+ uint32_t *range, uint8_t ranges, uint8_t refer_pcs)
{
static struct gsm322_ba_list ba;
- uint16_t lower, higher;
+ int lower, higher;
memset(&ba, 0, sizeof(ba));
while(ranges--) {
lower = *range & 1023;
higher = (*range >> 16) & 1023;
+ if (refer_pcs && lower >= 512 && lower <= 810) {
+ if (higher < 512 || higher > 810 || higher < lower) {
+ LOGP(DCS, LOGL_NOTICE, "Illegal PCS range: "
+ "%d..%d\n", lower, higher);
+ range++;
+ continue;
+ }
+ lower += 1024-512;
+ higher += 1024-512;
+ }
range++;
- LOGP(DCS, LOGL_INFO, "Use BA range: %d..%d\n", lower, higher);
+ LOGP(DCS, LOGL_INFO, "Use BA range: %s..%s\n",
+ gsm_print_arfcn(index2arfcn(lower)),
+ gsm_print_arfcn(index2arfcn(higher)));
/* GSM 05.08 6.3 */
while (1) {
ba.freq[lower >> 3] |= 1 << (lower & 7);
if (lower == higher)
break;
- lower = (lower + 1) & 1023;
+ lower++;
+ /* wrap arround, only if not PCS */
+ if (lower == 1024)
+ lower = 0;
}
}
@@ -2815,7 +2885,8 @@ static int gsm322_cs_choose(struct osmocom_ms *ms)
* we may access the BA range there.
*/
if (rr->ba_ranges)
- ba = gsm322_cs_ba_range(ms, rr->ba_range, rr->ba_ranges);
+ ba = gsm322_cs_ba_range(ms, rr->ba_range, rr->ba_ranges,
+ gsm_refer_pcs(cs->sel_arfcn, &cs->sel_si));
else {
LOGP(DCS, LOGL_INFO, "No BA range(s), try sysinfo.\n");
/* get and update BA of last received sysinfo 5* */
@@ -2844,7 +2915,7 @@ static int gsm322_cs_choose(struct osmocom_ms *ms)
}
/* flag all frequencies that are in current band allocation */
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if (cs->state == GSM322_C5_CHOOSE_CELL) {
if ((ba->freq[i >> 3] & (1 << (i & 7)))) {
cs->list[i].flags |= GSM322_CS_FLAG_BA;
@@ -2856,7 +2927,8 @@ static int gsm322_cs_choose(struct osmocom_ms *ms)
| GSM322_CS_FLAG_SIGNAL
| GSM322_CS_FLAG_SYSINFO);
if (cs->list[i].sysinfo) {
- LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%d\n", i);
+ LOGP(DCS, LOGL_INFO, "free sysinfo ARFCN=%s\n",
+ gsm_print_arfcn(index2arfcn(i)));
talloc_free(cs->list[i].sysinfo);
cs->list[i].sysinfo = NULL;
}
@@ -2884,13 +2956,14 @@ static int gsm322_c_choose_cell(struct osmocom_ms *ms, struct msgb *msg)
exit(0L);
}
cs->arfcn = cs->sel_arfcn;
+ cs->arfci = arfcn2index(cs->arfcn);
/* be sure to go to current camping frequency on return */
- LOGP(DCS, LOGL_INFO, "Selecting frequency %d. after LOC.UPD.\n",
- cs->arfcn);
+ LOGP(DCS, LOGL_INFO, "Selecting ARFCN %s. after LOC.UPD.\n",
+ gsm_print_arfcn(cs->arfcn));
hack = 1;
gsm322_sync_to_cell(cs);
- cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->si = cs->list[cs->arfci].sysinfo;
new_c_state(cs, GSM322_C3_CAMPED_NORMALLY);
@@ -2954,12 +3027,14 @@ static int gsm322_c_conn_mode_1(struct osmocom_ms *ms, struct msgb *msg)
if (!cs->selected)
return -EINVAL;
cs->arfcn = cs->sel_arfcn;
+ cs->arfci = arfcn2index(cs->arfcn);
/* be sure to go to current camping frequency on return */
- LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn);
+ LOGP(DCS, LOGL_INFO, "Going to camping (normal) ARFCN %s.\n",
+ gsm_print_arfcn(cs->arfcn));
hack = 1;
gsm322_sync_to_cell(cs);
- cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->si = cs->list[cs->arfci].sysinfo;
return 0;
}
@@ -2972,12 +3047,14 @@ static int gsm322_c_conn_mode_2(struct osmocom_ms *ms, struct msgb *msg)
if (!cs->selected)
return -EINVAL;
cs->arfcn = cs->sel_arfcn;
+ cs->arfci = arfcn2index(cs->arfcn);
/* be sure to go to current camping frequency on return */
- LOGP(DCS, LOGL_INFO, "Going to camping frequency %d.\n", cs->arfcn);
+ LOGP(DCS, LOGL_INFO, "Going to camping (any cell) ARFCN %s.\n",
+ gsm_print_arfcn(cs->arfcn));
hack = 1;
gsm322_sync_to_cell(cs);
- cs->si = cs->list[cs->arfcn].sysinfo;
+ cs->si = cs->list[cs->arfci].sysinfo;
return 0;
}
@@ -3377,15 +3454,20 @@ int gsm322_dump_cs_list(struct gsm322_cellsel *cs, uint8_t flags,
int i;
struct gsm48_sysinfo *s;
- print(priv, "arfcn |MCC |MNC |LAC |cell ID|forb.LA|prio |"
+ print(priv, "ARFCN |MCC |MNC |LAC |cell ID|forb.LA|prio |"
"min-db |max-pwr|rx-lev\n");
print(priv, "-------+-------+-------+-------+-------+-------+-------+"
"-------+-------+-------\n");
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
s = cs->list[i].sysinfo;
if (!s || !(cs->list[i].flags & flags))
continue;
- print(priv, "%4d |", i);
+ if (i >= 1024)
+ print(priv, "%4dPCS|", i-1024+512);
+ else if (i >= 512 && i <= 885)
+ print(priv, "%4dDCS|", i);
+ else
+ print(priv, "%4d |", i);
if ((cs->list[i].flags & GSM322_CS_FLAG_SYSINFO)) {
print(priv, "%s |%s%s |", gsm_print_mcc(s->mcc),
gsm_print_mnc(s->mnc),
@@ -3445,9 +3527,10 @@ int gsm322_dump_ba_list(struct gsm322_cellsel *cs, uint16_t mcc, uint16_t mnc,
"(%s, %s)\n", gsm_print_mcc(ba->mcc),
gsm_print_mnc(ba->mnc), gsm_get_mcc(ba->mcc),
gsm_get_mnc(ba->mcc, ba->mnc));
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if ((ba->freq[i >> 3] & (1 << (i & 7))))
- print(priv, " %d", i);
+ print(priv, " %s",
+ gsm_print_arfcn(index2arfcn(i)));
}
print(priv, "\n");
}
@@ -3468,6 +3551,7 @@ int gsm322_init(struct osmocom_ms *ms)
int i;
struct gsm322_ba_list *ba;
uint8_t buf[4];
+ char version[32];
LOGP(DPLMN, LOGL_INFO, "init PLMN process\n");
LOGP(DCS, LOGL_INFO, "init Cell Selection process\n");
@@ -3490,8 +3574,8 @@ int gsm322_init(struct osmocom_ms *ms)
INIT_LLIST_HEAD(&cs->ba_list);
/* set supported frequencies in cell selection list */
- for (i = 0; i <= 1023; i++)
- if ((ms->support.freq_map[i >> 3] & (1 << (i & 7))))
+ for (i = 0; i <= 1023+299; i++)
+ if ((ms->settings.freq_map[i >> 3] & (1 << (i & 7))))
cs->list[i].flags |= GSM322_CS_FLAG_SUPPORT;
/* read BA list */
@@ -3499,7 +3583,14 @@ int gsm322_init(struct osmocom_ms *ms)
fp = fopen(filename, "r");
if (fp) {
int rc;
+ char *s_rc;
+ s_rc = fgets(version, sizeof(version), fp);
+ version[sizeof(version) - 1] = '\0';
+ if (!s_rc || !!strcmp(ba_version, version)) {
+ LOGP(DCS, LOGL_NOTICE, "BA version missmatch, "
+ "stored BA list becomes obsolete.\n");
+ } else
while(!feof(fp)) {
ba = talloc_zero(l23_ctx, struct gsm322_ba_list);
if (!ba)
@@ -3552,9 +3643,10 @@ int gsm322_exit(struct osmocom_ms *ms)
stop_plmn_timer(plmn);
/* flush sysinfo */
- for (i = 0; i <= 1023; i++) {
+ for (i = 0; i <= 1023+299; i++) {
if (cs->list[i].sysinfo) {
- LOGP(DCS, LOGL_INFO, "free sysinfo arfcn=%d\n", i);
+ LOGP(DCS, LOGL_INFO, "free sysinfo ARFCN=%s\n",
+ gsm_print_arfcn(index2arfcn(i)));
talloc_free(cs->list[i].sysinfo);
cs->list[i].sysinfo = NULL;
}
@@ -3567,6 +3659,7 @@ int gsm322_exit(struct osmocom_ms *ms)
if (fp) {
int rc;
+ fputs(ba_version, fp);
llist_for_each_entry(ba, &cs->ba_list, entry) {
buf[0] = ba->mcc >> 8;
buf[1] = ba->mcc & 0xff;
diff --git a/src/host/layer23/src/mobile/gsm48_mm.c b/src/host/layer23/src/mobile/gsm48_mm.c
index 140750aa..a276a9e4 100644
--- a/src/host/layer23/src/mobile/gsm48_mm.c
+++ b/src/host/layer23/src/mobile/gsm48_mm.c
@@ -223,6 +223,25 @@ static int gsm48_mm_loc_upd(struct osmocom_ms *ms, struct msgb *msg);
* support functions
*/
+/* get supported power level of given arfcn */
+uint8_t gsm48_current_pwr_lev(struct gsm_settings *set, uint16_t arfcn)
+{
+ uint8_t pwr_lev;
+
+ if (arfcn >= (512 | ARFCN_PCS) && arfcn <= (810 | ARFCN_PCS))
+ pwr_lev = set->class_pcs - 1;
+ else if (arfcn >= 512 && arfcn <= 885)
+ pwr_lev = set->class_dcs - 1;
+ else if (arfcn >= 259 && arfcn <= 340)
+ pwr_lev = set->class_400 - 1;
+ else if (arfcn >= 128 && arfcn <= 251)
+ pwr_lev = set->class_850 - 1;
+ else
+ pwr_lev = set->class_900 - 1;
+
+ return pwr_lev;
+}
+
/* decode network name */
static int decode_network_name(char *name, int name_len,
const uint8_t *lv)
@@ -1703,10 +1722,7 @@ static int gsm48_mm_tx_imsi_detach(struct osmocom_ms *ms, int rr_prim)
ngh->msg_type = GSM48_MT_MM_IMSI_DETACH_IND;
/* classmark 1 */
- if (rr->cd_now.arfcn >= 512 && rr->cd_now.arfcn <= 885)
- pwr_lev = sup->class_dcs - 1;
- else
- pwr_lev = sup->class_900 - 1;
+ pwr_lev = gsm48_current_pwr_lev(set, rr->cd_now.arfcn);
gsm48_encode_classmark1(&cm, sup->rev_lev, sup->es_ind, set->a5_1,
pwr_lev);
msgb_v_put(nmsg, *((uint8_t *)&cm));
@@ -2210,10 +2226,7 @@ static int gsm48_mm_tx_loc_upd_req(struct osmocom_ms *ms)
gsm_print_mcc(subscr->mcc),
gsm_print_mnc(subscr->mnc), subscr->lac);
/* classmark 1 */
- if (rr->cd_now.arfcn >= 512 && rr->cd_now.arfcn <= 885)
- pwr_lev = sup->class_dcs - 1;
- else
- pwr_lev = sup->class_900 - 1;
+ pwr_lev = gsm48_current_pwr_lev(set, rr->cd_now.arfcn);
gsm48_encode_classmark1(&nlu->classmark1, sup->rev_lev, sup->es_ind,
set->a5_1, pwr_lev);
/* MI */
diff --git a/src/host/layer23/src/mobile/gsm48_rr.c b/src/host/layer23/src/mobile/gsm48_rr.c
index c1c27f42..79119434 100644
--- a/src/host/layer23/src/mobile/gsm48_rr.c
+++ b/src/host/layer23/src/mobile/gsm48_rr.c
@@ -1015,6 +1015,9 @@ static int gsm48_rr_enc_cm3(struct osmocom_ms *ms, uint8_t *buf, uint8_t *len)
else
bitvec_set_bit(&bv, ZERO);
/* radio capability */
+ if (!set->dcs && !set->p_gsm && !(set->e_gsm || set->r_gsm)) {
+ /* Fig. 10.5.7 / TS 24.0008: none of dcs, p, e, r */
+ } else
if (set->dcs && !set->p_gsm && !(set->e_gsm || set->r_gsm)) {
/* dcs only */
bitvec_set_uint(&bv, 0, 4);
@@ -1075,6 +1078,70 @@ static int gsm48_rr_enc_cm3(struct osmocom_ms *ms, uint8_t *buf, uint8_t *len)
} else {
bitvec_set_bit(&bv, ZERO);
}
+ /* The following bits are described in TS 24.008 */
+ /* EDGE multi slot support */
+ if (set->edge_ms_sup) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_uint(&bv, set->edge_ms_sup, 5);
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ /* EDGE support */
+ if (set->edge_psk_sup) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_bit(&bv, set->edge_psk_uplink == 1);
+ if (set->p_gsm || (set->e_gsm || set->r_gsm)) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_uint(&bv, set->class_900_edge, 2);
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ if (set->dcs || set->pcs) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_uint(&bv, set->class_dcs_pcs_edge, 2);
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ /* GSM 400 Bands */
+ if (set->gsm_480 || set->gsm_450) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_bit(&bv, set->gsm_480 == 1);
+ bitvec_set_bit(&bv, set->gsm_450 == 1);
+ bitvec_set_uint(&bv, set->class_400, 4);
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ /* GSM 850 Band */
+ if (set->gsm_850) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_uint(&bv, set->class_850, 4);
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ /* PCS Band */
+ if (set->pcs) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_uint(&bv, set->class_pcs, 4);
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ /* RAT Capability */
+ bitvec_set_bit(&bv, set->umts_fdd == 1);
+ bitvec_set_bit(&bv, set->umts_tdd == 1);
+ bitvec_set_bit(&bv, set->cdma_2000 == 1);
+ /* DTM */
+ if (set->dtm) {
+ bitvec_set_bit(&bv, ONE);
+ bitvec_set_uint(&bv, set->class_dtm, 2);
+ bitvec_set_bit(&bv, set->dtm_mac == 1);
+ bitvec_set_bit(&bv, set->dtm_egprs == 1);
+ } else {
+ bitvec_set_bit(&bv, ZERO);
+ }
+ /* info: The max number of bits are about 80. */
/* partitial bytes will be completed */
*len = (bv.cur_bit + 7) >> 3;
@@ -1090,10 +1157,7 @@ int gsm48_rr_enc_cm2(struct osmocom_ms *ms, struct gsm48_classmark2 *cm)
struct gsm_support *sup = &ms->support;
struct gsm_settings *set = &ms->settings;
- if (rr->cd_now.arfcn >= 512 && rr->cd_now.arfcn <= 885)
- cm->pwr_lev = set->class_dcs - 1;
- else
- cm->pwr_lev = set->class_900 - 1;
+ cm->pwr_lev = gsm48_current_pwr_lev(set, rr->cd_now.arfcn);
cm->a5_1 = !set->a5_1;
cm->es_ind = sup->es_ind;
cm->rev_lev = sup->rev_lev;
@@ -1138,7 +1202,7 @@ static int gsm48_rr_tx_cm_change(struct osmocom_ms *ms)
gsm48_rr_enc_cm2(ms, &cc->cm2);
/* classmark 3 */
- if (set->dcs || set->e_gsm || set->r_gsm
+ if (set->dcs || set->pcs || set->e_gsm || set->r_gsm || set->gsm_850
|| set->a5_7 || set->a5_6 || set->a5_5 || set->a5_4
|| sup->ms_sup
|| sup->ucs2_treat
@@ -1533,7 +1597,8 @@ fail:
} else {
tx_power = s->ms_txpwr_max_cch;
/* power offset in case of DCS1800 */
- if (s->po && cs->arfcn >= 512 && cs->arfcn <= 885) {
+ if (s->po && (cs->arfcn & 1023) >= 512
+ && (cs->arfcn & 1023) <= 885) {
LOGP(DRR, LOGL_INFO, "Use MS-TXPWR-MAX-CCH power value "
"%d (%d dBm) with offset %d dBm\n", tx_power,
ms_pwr_dbm(gsm_arfcn2band(cs->arfcn), tx_power),
@@ -1566,6 +1631,7 @@ fail:
static int gsm48_new_sysinfo(struct osmocom_ms *ms, uint8_t type)
{
struct gsm48_sysinfo *s = ms->cellsel.si;
+ struct gsm322_cellsel *cs = &ms->cellsel;
struct msgb *nmsg;
struct gsm322_msg *em;
@@ -1577,22 +1643,27 @@ static int gsm48_new_sysinfo(struct osmocom_ms *ms, uint8_t type)
&& s->si5
&& (!s->nb_ext_ind_si5 || s->si5bis)) {
struct gsm48_rr_meas *rrmeas = &ms->rrlayer.meas;
- int n = 0, i;
+ int n = 0, i, refer_pcs;
LOGP(DRR, LOGL_NOTICE, "Complete set of SI5* for BA(%d)\n",
s->nb_ba_ind_si5);
rrmeas->nc_num = 0;
+ refer_pcs = gsm_refer_pcs(cs->arfcn, s);
+
for (i = 1; i <= 1024; i++) {
- if ((s->freq[i & 1023].mask & FREQ_TYPE_REP)) {
+ if ((s->freq[i].mask & FREQ_TYPE_REP)) {
if (n == 32) {
LOGP(DRR, LOGL_NOTICE, "SI5* report "
"exceeds 32 BCCHs\n");
break;
}
- LOGP(DRR, LOGL_NOTICE, "SI5* report arfcn %d\n",
- i & 1023);
- rrmeas->nc_arfcn[n] = i & 1023;
+ if (refer_pcs && i >= 512 && i <= 810)
+ rrmeas->nc_arfcn[n] = i | ARFCN_PCS;
+ else
+ rrmeas->nc_arfcn[n] = i;
rrmeas->nc_rxlev[n] = -128;
+ LOGP(DRR, LOGL_NOTICE, "SI5* report arfcn %s\n",
+ gsm_print_arfcn(rrmeas->nc_arfcn[n]));
n++;
}
}
@@ -2227,6 +2298,8 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
struct gsm48_imm_ass *ia = msgb_l3(msg);
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_sysinfo *s = cs->si;
int ma_len = msgb_l3len(msg) - sizeof(*ia);
uint8_t ch_type, ch_subch, ch_ts;
struct gsm48_rr_cd cd;
@@ -2278,12 +2351,14 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
} else {
cd.h = 0;
gsm48_decode_chan_h0(&ia->chan_desc, &cd.tsc, &cd.arfcn);
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cd.arfcn |= ARFCN_PCS;
LOGP(DRR, LOGL_INFO, " (ta %d/%dm ra 0x%02x chan_nr 0x%02x "
- "ARFCN %u TS %u SS %u TSC %u)\n",
+ "ARFCN %s TS %u SS %u TSC %u)\n",
ia->timing_advance,
ia->timing_advance * GSM_TA_CM / 100,
- ia->req_ref.ra, ia->chan_desc.chan_nr, cd.arfcn,
- ch_ts, ch_subch, cd.tsc);
+ ia->req_ref.ra, ia->chan_desc.chan_nr,
+ gsm_print_arfcn(cd.arfcn), ch_ts, ch_subch, cd.tsc);
}
/* 3.3.1.1.2: ignore assignment while idle */
@@ -2322,6 +2397,8 @@ static int gsm48_rr_rx_imm_ass(struct osmocom_ms *ms, struct msgb *msg)
static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm48_imm_ass_ext *ia = msgb_l3(msg);
int ma_len = msgb_l3len(msg) - sizeof(*ia);
uint8_t ch_type, ch_subch, ch_ts;
@@ -2380,12 +2457,14 @@ static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
} else {
cd1.h = 0;
gsm48_decode_chan_h0(&ia->chan_desc1, &cd1.tsc, &cd1.arfcn);
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cd1.arfcn |= ARFCN_PCS;
LOGP(DRR, LOGL_INFO, " assignment 1 (ta %d/%dm ra 0x%02x "
- "chan_nr 0x%02x ARFCN %u TS %u SS %u TSC %u)\n",
+ "chan_nr 0x%02x ARFCN %s TS %u SS %u TSC %u)\n",
ia->timing_advance1,
ia->timing_advance1 * GSM_TA_CM / 100,
- ia->req_ref1.ra, ia->chan_desc1.chan_nr, cd1.arfcn,
- ch_ts, ch_subch, cd1.tsc);
+ ia->req_ref1.ra, ia->chan_desc1.chan_nr,
+ gsm_print_arfcn(cd1.arfcn), ch_ts, ch_subch, cd1.tsc);
}
cd2.chan_nr = ia->chan_desc2.chan_nr;
rsl_dec_chan_nr(cd2.chan_nr, &ch_type, &ch_subch, &ch_ts);
@@ -2402,12 +2481,14 @@ static int gsm48_rr_rx_imm_ass_ext(struct osmocom_ms *ms, struct msgb *msg)
} else {
cd2.h = 0;
gsm48_decode_chan_h0(&ia->chan_desc2, &cd2.tsc, &cd2.arfcn);
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cd2.arfcn |= ARFCN_PCS;
LOGP(DRR, LOGL_INFO, " assignment 2 (ta %d/%dm ra 0x%02x "
- "chan_nr 0x%02x ARFCN %u TS %u SS %u TSC %u)\n",
+ "chan_nr 0x%02x ARFCN %s TS %u SS %u TSC %u)\n",
ia->timing_advance2,
ia->timing_advance2 * GSM_TA_CM / 100,
- ia->req_ref2.ra, ia->chan_desc2.chan_nr, cd2.arfcn,
- ch_ts, ch_subch, cd2.tsc);
+ ia->req_ref2.ra, ia->chan_desc2.chan_nr,
+ gsm_print_arfcn(cd2.arfcn), ch_ts, ch_subch, cd2.tsc);
}
/* 3.3.1.1.2: ignore assignment while idle */
@@ -2847,14 +2928,17 @@ static int gsm48_rr_channel_after_time(struct osmocom_ms *ms,
static int gsm48_rr_render_ma(struct osmocom_ms *ms, struct gsm48_rr_cd *cd,
uint16_t *ma, uint8_t *ma_len)
{
- struct gsm48_sysinfo *s = ms->cellsel.si;
- struct gsm_support *sup = &ms->support;
- int i;
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_sysinfo *s = cs->si;
+ struct gsm_settings *set = &ms->settings;
+ int i, pcs, index;
uint16_t arfcn;
+ pcs = gsm_refer_pcs(cs->arfcn, s) ? ARFCN_PCS : 0;
+
/* no hopping (no MA), channel description is valid */
if (!cd->h) {
- ma_len = 0;
+ *ma_len = 0;
return 0;
}
@@ -2901,8 +2985,8 @@ static int gsm48_rr_render_ma(struct osmocom_ms *ms, struct gsm48_rr_cd *cd,
/* collect channels from bitmap (1..1023,0) */
for (i = 1; i <= 1024; i++) {
if ((f[i & 1023].mask & FREQ_TYPE_SERV)) {
- LOGP(DRR, LOGL_INFO, "Listed ARFCN #%d: %d\n",
- j, i);
+ LOGP(DRR, LOGL_INFO, "Listed ARFCN #%d: %s\n",
+ j, gsm_print_arfcn(i | pcs));
if (j == 64) {
LOGP(DRR, LOGL_NOTICE, "frequency list "
"exceeds 64 entries!\n");
@@ -2912,7 +2996,6 @@ static int gsm48_rr_render_ma(struct osmocom_ms *ms, struct gsm48_rr_cd *cd,
}
}
*ma_len = j;
- return 0;
} else
/* decode frequency channel sequence */
if (cd->freq_seq_lv[0]) {
@@ -2926,8 +3009,8 @@ static int gsm48_rr_render_ma(struct osmocom_ms *ms, struct gsm48_rr_cd *cd,
return GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
}
arfcn = cd->freq_seq_lv[1] & 0x7f;
- LOGP(DRR, LOGL_INFO, "Listed Sequence ARFCN #%d: %d\n", j,
- arfcn);
+ LOGP(DRR, LOGL_INFO, "Listed Sequence ARFCN #%d: %s\n", j,
+ gsm_print_arfcn(arfcn | pcs));
ma[j++] = arfcn;
for (i = 0; i <= 16; i++) {
if ((i & 1))
@@ -2937,25 +3020,27 @@ static int gsm48_rr_render_ma(struct osmocom_ms *ms, struct gsm48_rr_cd *cd,
if (inc) {
arfcn += inc;
LOGP(DRR, LOGL_INFO, "Listed Sequence ARFCN "
- "#%d: %d\n", j, arfcn);
+ "#%d: %s\n", j,
+ gsm_print_arfcn(i | pcs));
ma[j++] = arfcn;
} else
arfcn += 15;
}
*ma_len = j;
- return 0;
} else {
LOGP(DRR, LOGL_NOTICE, "hopping, but nothing that tells us "
"a sequence\n");
return GSM48_RR_CAUSE_ABNORMAL_UNSPEC;
}
- /* check for unsported frequency */
+ /* convert to band_arfcn and check for unsported frequency */
for (i = 0; i < *ma_len; i++) {
- arfcn = ma[i];
- if (!(sup->freq_map[arfcn >> 3] & (1 << (arfcn & 7)))) {
- LOGP(DRR, LOGL_NOTICE, "Hopping frequency %d not "
- "supported\n", arfcn);
+ arfcn = ma[i] | pcs;
+ ma[i] = arfcn;
+ index = arfcn2index(arfcn);
+ if (!(set->freq_map[index >> 3] & (1 << (index & 7)))) {
+ LOGP(DRR, LOGL_NOTICE, "Hopping ARFCN %s not "
+ "supported\n", gsm_print_arfcn(arfcn));
return GSM48_RR_CAUSE_FREQ_NOT_IMPL;
}
}
@@ -3233,6 +3318,8 @@ static int gsm48_rr_set_mode(struct osmocom_ms *ms, uint8_t chan_nr,
static int gsm48_rr_rx_frq_redef(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm48_frq_redef *fr = msgb_l3(msg);
int mob_al_len = msgb_l3len(msg) - sizeof(*fr);
uint8_t ch_type, ch_subch, ch_ts;
@@ -3269,8 +3356,10 @@ static int gsm48_rr_rx_frq_redef(struct osmocom_ms *ms, struct msgb *msg)
} else {
cd.h = 0;
gsm48_decode_chan_h0(&fr->chan_desc, &cd.tsc, &cd.arfcn);
- LOGP(DRR, LOGL_INFO, " (ARFCN %u TS %u SS %u TSC %u)\n",
- cd.arfcn, ch_ts, ch_subch, cd.tsc);
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cd.arfcn |= ARFCN_PCS;
+ LOGP(DRR, LOGL_INFO, " (ARFCN %s TS %u SS %u TSC %u)\n",
+ gsm_print_arfcn(cd.arfcn), ch_ts, ch_subch, cd.tsc);
}
/* mobile allocation */
@@ -3339,6 +3428,8 @@ static int gsm48_rr_tx_chan_modify_ack(struct osmocom_ms *ms,
static int gsm48_rr_rx_chan_modify(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_chan_mode_modify *cm =
(struct gsm48_chan_mode_modify *)gh->data;
@@ -3370,9 +3461,12 @@ static int gsm48_rr_rx_chan_modify(struct osmocom_ms *ms, struct msgb *msg)
} else {
cd->h = 0;
gsm48_decode_chan_h0(&cm->chan_desc, &cd->tsc, &cd->arfcn);
- LOGP(DRR, LOGL_INFO, " (chan_nr 0x%02x ARFCN %u TS %u SS %u "
- "TSC %u mode %u)\n", cm->chan_desc.chan_nr, cd->arfcn,
- ch_ts, ch_subch, cd->tsc, cm->mode);
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cd->arfcn |= ARFCN_PCS;
+ LOGP(DRR, LOGL_INFO, " (chan_nr 0x%02x ARFCN %s TS %u SS %u "
+ "TSC %u mode %u)\n", cm->chan_desc.chan_nr,
+ gsm_print_arfcn(cd->arfcn), ch_ts, ch_subch, cd->tsc,
+ cm->mode);
}
/* mode */
cause = gsm48_rr_check_mode(ms, cd->chan_nr, cm->mode);
@@ -3437,6 +3531,8 @@ static int gsm48_rr_tx_ass_fail(struct osmocom_ms *ms, uint8_t cause,
static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_ass_cmd *ac = (struct gsm48_ass_cmd *)gh->data;
int payload_len = msgb_l3len(msg) - sizeof(*gh) - sizeof(*ac);
@@ -3483,9 +3579,12 @@ static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
} else {
cdb->h = 0;
gsm48_decode_chan_h0(ccd, &cdb->tsc, &cdb->arfcn);
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cdb->arfcn |= ARFCN_PCS;
LOGP(DRR, LOGL_INFO, " before: (chan_nr 0x%02x "
- "ARFCN %u TS %u SS %u TSC %u)\n", ccd->chan_nr,
- cdb->arfcn, ch_ts, ch_subch, cdb->tsc);
+ "ARFCN %s TS %u SS %u TSC %u)\n", ccd->chan_nr,
+ gsm_print_arfcn(cdb->arfcn),
+ ch_ts, ch_subch, cdb->tsc);
}
before_time = 1;
}
@@ -3503,9 +3602,11 @@ static int gsm48_rr_rx_ass_cmd(struct osmocom_ms *ms, struct msgb *msg)
} else {
cda->h = 0;
gsm48_decode_chan_h0(&ac->chan_desc, &cda->tsc, &cda->arfcn);
- LOGP(DRR, LOGL_INFO, " after: (chan_nr 0x%02x ARFCN %u TS %u "
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cda->arfcn |= ARFCN_PCS;
+ LOGP(DRR, LOGL_INFO, " after: (chan_nr 0x%02x ARFCN %s TS %u "
"SS %u TSC %u)\n", ac->chan_desc.chan_nr,
- cda->arfcn, ch_ts, ch_subch, cda->tsc);
+ gsm_print_arfcn(cda->arfcn), ch_ts, ch_subch, cda->tsc);
}
/* starting time */
@@ -3793,6 +3894,8 @@ static int gsm48_rr_tx_hando_fail(struct osmocom_ms *ms, uint8_t cause,
static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
{
struct gsm48_rrlayer *rr = &ms->rrlayer;
+ struct gsm322_cellsel *cs = &ms->cellsel;
+ struct gsm48_sysinfo *s = cs->si;
struct gsm48_hdr *gh = msgb_l3(msg);
struct gsm48_ho_cmd *ho = (struct gsm48_ho_cmd *)gh->data;
int payload_len = msgb_l3len(msg) - sizeof(*gh) - sizeof(*ho);
@@ -3856,9 +3959,12 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
} else {
cdb->h = 0;
gsm48_decode_chan_h0(ccd, &cdb->tsc, &cdb->arfcn);
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cdb->arfcn |= ARFCN_PCS;
LOGP(DRR, LOGL_INFO, " before: (chan_nr 0x%02x "
- "ARFCN %u TS %u SS %u TSC %u)\n", ccd->chan_nr,
- cdb->arfcn, ch_ts, ch_subch, cdb->tsc);
+ "ARFCN %s TS %u SS %u TSC %u)\n", ccd->chan_nr,
+ gsm_print_arfcn(cdb->arfcn),
+ ch_ts, ch_subch, cdb->tsc);
}
before_time = 1;
}
@@ -3876,9 +3982,11 @@ static int gsm48_rr_rx_hando_cmd(struct osmocom_ms *ms, struct msgb *msg)
} else {
cda->h = 0;
gsm48_decode_chan_h0(&ho->chan_desc, &cda->tsc, &cda->arfcn);
- LOGP(DRR, LOGL_INFO, " after: (chan_nr 0x%02x ARFCN %u TS %u "
+ if (gsm_refer_pcs(cs->arfcn, s))
+ cda->arfcn |= ARFCN_PCS;
+ LOGP(DRR, LOGL_INFO, " after: (chan_nr 0x%02x ARFCN %s TS %u "
"SS %u TSC %u)\n", ho->chan_desc.chan_nr,
- cda->arfcn, ch_ts, ch_subch, cda->tsc);
+ gsm_print_arfcn(cda->arfcn), ch_ts, ch_subch, cda->tsc);
}
/* starting time */
diff --git a/src/host/layer23/src/mobile/settings.c b/src/host/layer23/src/mobile/settings.c
index db22fd9f..15397fa6 100644
--- a/src/host/layer23/src/mobile/settings.c
+++ b/src/host/layer23/src/mobile/settings.c
@@ -68,6 +68,9 @@ int gsm_settings_init(struct osmocom_ms *ms)
set->dcs = sup->dcs;
set->class_900 = sup->class_900;
set->class_dcs = sup->class_dcs;
+ set->class_850 = sup->class_850;
+ set->class_pcs = sup->class_pcs;
+ set->class_400 = sup->class_400;
set->full_v1 = sup->full_v1;
set->full_v2 = sup->full_v2;
set->full_v3 = sup->full_v3;
@@ -80,6 +83,7 @@ int gsm_settings_init(struct osmocom_ms *ms)
if (sup->half_v1 || sup->half_v3)
set->half = 1;
+
/* software features */
set->cc_dtmf = 1;
@@ -88,6 +92,43 @@ int gsm_settings_init(struct osmocom_ms *ms)
return 0;
}
+int gsm_settings_arfcn(struct osmocom_ms *ms)
+{
+ int i;
+ struct gsm_settings *set = &ms->settings;
+
+ /* set supported frequencies */
+ memset(set->freq_map, 0, sizeof(set->freq_map));
+ if (set->p_gsm)
+ for(i = 1; i <= 124; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+ if (set->gsm_850)
+ for(i = 128; i <= 251; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+ if (set->gsm_450)
+ for(i = 259; i <= 293; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+ if (set->gsm_480)
+ for(i = 306; i <= 340; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+ if (set->dcs)
+ for(i = 512; i <= 885; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+ if (set->pcs)
+ for(i = 1024; i <= 1024-512+810; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+ if (set->e_gsm) {
+ for(i = 975; i <= 1023; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+ set->freq_map[0] |= 1;
+ }
+ if (set->r_gsm)
+ for(i = 955; i <= 974; i++)
+ set->freq_map[i >> 3] |= (1 << (i & 7));
+
+ return 0;
+}
+
int gsm_settings_exit(struct osmocom_ms *ms)
{
struct gsm_settings *set = &ms->settings;
diff --git a/src/host/layer23/src/mobile/support.c b/src/host/layer23/src/mobile/support.c
index 97306f52..d2947dc6 100644
--- a/src/host/layer23/src/mobile/support.c
+++ b/src/host/layer23/src/mobile/support.c
@@ -28,14 +28,10 @@
void gsm_support_init(struct osmocom_ms *ms)
{
struct gsm_support *sup = &ms->support;
- int i;
memset(sup, 0, sizeof(*sup));
sup->ms = ms;
- /* rf power capability */
- sup->class_900 = 4; /* CLASS 4: Handheld 2W */
- sup->class_dcs = 1; /* CLASS 1: Handheld 1W */
/* controlled early classmark sending */
sup->es_ind = 0; /* no */
/* revision level */
@@ -70,21 +66,16 @@ void gsm_support_init(struct osmocom_ms *ms)
sup->e_gsm = 1; /* E-GSM */
sup->r_gsm = 1; /* R-GSM */
sup->dcs = 1;
- /* set supported frequencies */
- if (sup->p_gsm)
- for(i = 1; i <= 124; i++)
- sup->freq_map[i >> 3] |= (1 << (i & 7));
- if (sup->dcs)
- for(i = 512; i <= 885; i++)
- sup->freq_map[i >> 3] |= (1 << (i & 7));
- if (sup->e_gsm) {
- for(i = 975; i <= 1023; i++)
- sup->freq_map[i >> 3] |= (1 << (i & 7));
- sup->freq_map[0] |= 1;
- }
- if (sup->r_gsm)
- for(i = 955; i <= 974; i++)
- sup->freq_map[i >> 3] |= (1 << (i & 7));
+ sup->gsm_850 = 1;
+ sup->pcs = 1;
+ sup->gsm_480 = 0;
+ sup->gsm_450 = 0;
+ /* rf power capability */
+ sup->class_900 = 4; /* CLASS 4: Handheld 2W */
+ sup->class_850 = 4;
+ sup->class_400 = 4;
+ sup->class_dcs = 1; /* CLASS 1: Handheld 1W */
+ sup->class_pcs = 1;
/* multi slot support */
sup->ms_sup = 0; /* no */
/* ucs2 treatment */
@@ -116,7 +107,7 @@ struct gsm_support_scan_max gsm_sup_smax[] = {
{ 259, 293, 15, 0 }, /* GSM 450 */
{ 306, 340, 15, 0 }, /* GSM 480 */
{ 438, 511, 25, 0 },
- { 128, 251, 30, 0 },
+ { 128, 251, 30, 0 }, /* GSM 850 */
{ 955, 124, 30, 0 }, /* P,E,R GSM */
{ 512, 885, 40, 0 }, /* DCS 1800 */
{ 0, 0, 0, 0 }
@@ -133,46 +124,58 @@ void gsm_support_dump(struct osmocom_ms *ms,
print(priv, "Supported features of MS '%s':\n", sup->ms->name);
print(priv, " Phase %d mobile station\n", sup->rev_lev + 1);
- print(priv, " R-GSM : %s\n", SUP_SET(r_gsm));
- print(priv, " E-GSM : %s\n", SUP_SET(e_gsm));
- print(priv, " P-GSM : %s\n", SUP_SET(p_gsm));
- print(priv, " GSM900 Class: %d\n", set->class_900);
- print(priv, " DCS 1800 : %s\n", SUP_SET(dcs));
- print(priv, " DCS Class : %d\n", set->class_dcs);
- print(priv, " CECS : %s\n", (sup->es_ind) ? "yes" : "no");
- print(priv, " VGCS : %s\n", (sup->vgcs) ? "yes" : "no");
- print(priv, " VBS : %s\n", (sup->vbs) ? "yes" : "no");
- print(priv, " SMS : %s\n", SUP_SET(sms_ptp));
- print(priv, " SS_IND : %s\n", (sup->ss_ind) ? "yes" : "no");
- print(priv, " PS_CAP : %s\n", (sup->ps_cap) ? "yes" : "no");
- print(priv, " CMSP : %s\n", (sup->cmsp) ? "yes" : "no");
- print(priv, " SoLSA : %s\n", (sup->solsa) ? "yes" : "no");
- print(priv, " LCSVA : %s\n", (sup->lcsva) ? "yes" : "no");
- print(priv, " LOC_SERV : %s\n", (sup->loc_serv) ? "yes" : "no");
- print(priv, " A5/1 : %s\n", SUP_SET(a5_1));
- print(priv, " A5/2 : %s\n", SUP_SET(a5_2));
- print(priv, " A5/3 : %s\n", SUP_SET(a5_3));
- print(priv, " A5/4 : %s\n", SUP_SET(a5_4));
- print(priv, " A5/5 : %s\n", SUP_SET(a5_5));
- print(priv, " A5/6 : %s\n", SUP_SET(a5_6));
- print(priv, " A5/7 : %s\n", SUP_SET(a5_7));
- print(priv, " A5/1 : %s\n", SUP_SET(a5_1));
+ print(priv, " R-GSM : %s\n", SUP_SET(r_gsm));
+ print(priv, " E-GSM : %s\n", SUP_SET(e_gsm));
+ print(priv, " P-GSM : %s\n", SUP_SET(p_gsm));
+ if (set->r_gsm || set->e_gsm || set->p_gsm)
+ print(priv, " GSM900 Class : %d\n", set->class_900);
+ print(priv, " DCS 1800 : %s\n", SUP_SET(dcs));
+ if (set->dcs)
+ print(priv, " DCS Class : %d\n", set->class_dcs);
+ print(priv, " GSM 850 : %s\n", SUP_SET(gsm_850));
+ if (set->gsm_850)
+ print(priv, " GSM 850 Class: %d\n", set->class_850);
+ print(priv, " PCS 1900 : %s\n", SUP_SET(pcs));
+ if (set->pcs)
+ print(priv, " PCS Class : %d\n", set->class_pcs);
+ print(priv, " GSM 480 : %s\n", SUP_SET(gsm_480));
+ print(priv, " GSM 450 : %s\n", SUP_SET(gsm_450));
+ if (set->gsm_480 | set->gsm_450)
+ print(priv, " GSM 400 Class: %d\n", set->class_400);
+ print(priv, " CECS : %s\n", (sup->es_ind) ? "yes" : "no");
+ print(priv, " VGCS : %s\n", (sup->vgcs) ? "yes" : "no");
+ print(priv, " VBS : %s\n", (sup->vbs) ? "yes" : "no");
+ print(priv, " SMS : %s\n", SUP_SET(sms_ptp));
+ print(priv, " SS_IND : %s\n", (sup->ss_ind) ? "yes" : "no");
+ print(priv, " PS_CAP : %s\n", (sup->ps_cap) ? "yes" : "no");
+ print(priv, " CMSP : %s\n", (sup->cmsp) ? "yes" : "no");
+ print(priv, " SoLSA : %s\n", (sup->solsa) ? "yes" : "no");
+ print(priv, " LCSVA : %s\n", (sup->lcsva) ? "yes" : "no");
+ print(priv, " LOC_SERV : %s\n", (sup->loc_serv) ? "yes" : "no");
+ print(priv, " A5/1 : %s\n", SUP_SET(a5_1));
+ print(priv, " A5/2 : %s\n", SUP_SET(a5_2));
+ print(priv, " A5/3 : %s\n", SUP_SET(a5_3));
+ print(priv, " A5/4 : %s\n", SUP_SET(a5_4));
+ print(priv, " A5/5 : %s\n", SUP_SET(a5_5));
+ print(priv, " A5/6 : %s\n", SUP_SET(a5_6));
+ print(priv, " A5/7 : %s\n", SUP_SET(a5_7));
+ print(priv, " A5/1 : %s\n", SUP_SET(a5_1));
switch (set->ch_cap) {
case GSM_CAP_SDCCH:
- print(priv, " Channels : SDCCH only\n");
+ print(priv, " Channels : SDCCH only\n");
break;
case GSM_CAP_SDCCH_TCHF:
- print(priv, " Channels : SDCCH + TCH/F\n");
+ print(priv, " Channels : SDCCH + TCH/F\n");
break;
case GSM_CAP_SDCCH_TCHF_TCHH:
- print(priv, " Channels : SDCCH + TCH/F + TCH/H\n");
+ print(priv, " Channels : SDCCH + TCH/F + TCH/H\n");
break;
}
- print(priv, " Full-Rate V1: %s\n", SUP_SET(full_v1));
- print(priv, " Full-Rate V2: %s\n", SUP_SET(full_v2));
- print(priv, " Full-Rate V3: %s\n", SUP_SET(full_v3));
- print(priv, " Half-Rate V1: %s\n", SUP_SET(half_v1));
- print(priv, " Half-Rate V3: %s\n", SUP_SET(half_v3));
- print(priv, " Min RXLEV : %d\n", set->min_rxlev_db);
+ print(priv, " Full-Rate V1 : %s\n", SUP_SET(full_v1));
+ print(priv, " Full-Rate V2 : %s\n", SUP_SET(full_v2));
+ print(priv, " Full-Rate V3 : %s\n", SUP_SET(full_v3));
+ print(priv, " Half-Rate V1 : %s\n", SUP_SET(half_v1));
+ print(priv, " Half-Rate V3 : %s\n", SUP_SET(half_v3));
+ print(priv, " Min RXLEV : %d\n", set->min_rxlev_db);
}
diff --git a/src/host/layer23/src/mobile/vty_interface.c b/src/host/layer23/src/mobile/vty_interface.c
index 80a756c9..0614c6fb 100644
--- a/src/host/layer23/src/mobile/vty_interface.c
+++ b/src/host/layer23/src/mobile/vty_interface.c
@@ -203,7 +203,8 @@ static void gsm_ms_dump(struct osmocom_ms *ms, struct vty *vty)
vty_out(vty, " cell selection state: %s",
cs_state_names[ms->cellsel.state]);
if (ms->rrlayer.state == GSM48_RR_ST_IDLE && ms->cellsel.selected)
- vty_out(vty, " (ARFCN %d)", ms->cellsel.sel_arfcn);
+ vty_out(vty, " (ARFCN %s)",
+ gsm_print_arfcn(ms->cellsel.sel_arfcn));
vty_out(vty, "%s", VTY_NEWLINE);
vty_out(vty, " radio ressource layer state: %s%s",
gsm48_rr_state_names[ms->rrlayer.state], VTY_NEWLINE);
@@ -305,32 +306,36 @@ DEFUN(show_cell, show_cell_cmd, "show cell MS_NAME",
return CMD_SUCCESS;
}
-DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023>",
+DEFUN(show_cell_si, show_cell_si_cmd, "show cell MS_NAME <0-1023> [pcs]",
SHOW_STR "Display information about received cell\n"
- "Name of MS (see \"show ms\")\nRadio frequency number")
+ "Name of MS (see \"show ms\")\nRadio frequency number\n"
+ "Given frequency is PCS band (1900) rather than DCS band.")
{
struct osmocom_ms *ms;
- int i;
struct gsm48_sysinfo *s;
+ uint16_t arfcn = atoi(argv[1]);
ms = get_ms(argv[0], vty);
if (!ms)
return CMD_WARNING;
- i = atoi(argv[1]);
- if (i < 0 || i > 1023) {
- vty_out(vty, "Given ARFCN '%s' not in range (0..1023)%s",
- argv[1], VTY_NEWLINE);
- return CMD_WARNING;
+ if (argc > 2) {
+ if (arfcn < 512 || arfcn > 810) {
+ vty_out(vty, "Given ARFCN not in PCS band%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ arfcn |= ARFCN_PCS;
}
- s = ms->cellsel.list[i].sysinfo;
+
+ s = ms->cellsel.list[arfcn2index(arfcn)].sysinfo;
if (!s) {
vty_out(vty, "Given ARFCN '%s' has no sysinfo available%s",
argv[1], VTY_NEWLINE);
return CMD_SUCCESS;
}
- gsm48_sysinfo_dump(s, i, print_vty, vty);
+ gsm48_sysinfo_dump(s, arfcn, print_vty, vty, ms->settings.freq_map);
return CMD_SUCCESS;
}
@@ -1101,7 +1106,8 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
else
vty_out(vty, " no simulated-delay%s", VTY_NEWLINE);
if (set->stick)
- vty_out(vty, " stick %d%s", set->stick_arfcn,
+ vty_out(vty, " stick %d%s%s", set->stick_arfcn & 1023,
+ (set->stick_arfcn & ARFCN_PCS) ? " pcs" : "",
VTY_NEWLINE);
else
vty_out(vty, " no stick%s", VTY_NEWLINE);
@@ -1143,9 +1149,21 @@ static void config_write_ms(struct vty *vty, struct osmocom_ms *ms)
SUP_WRITE(p_gsm, "p-gsm");
SUP_WRITE(e_gsm, "e-gsm");
SUP_WRITE(r_gsm, "r-gsm");
+ SUP_WRITE(pcs, "gsm-850");
+ SUP_WRITE(gsm_480, "gsm-480");
+ SUP_WRITE(gsm_450, "gsm-450");
SUP_WRITE(dcs, "dcs");
- vty_out(vty, " class-900 %d%s", set->class_900, VTY_NEWLINE);
- vty_out(vty, " class-dcs %d%s", set->class_dcs, VTY_NEWLINE);
+ SUP_WRITE(pcs, "pcs");
+ if (sup->r_gsm || sup->e_gsm || sup->p_gsm)
+ vty_out(vty, " class-900 %d%s", set->class_900, VTY_NEWLINE);
+ if (sup->gsm_850)
+ vty_out(vty, " class-850 %d%s", set->class_850, VTY_NEWLINE);
+ if (sup->gsm_480 || sup->gsm_450)
+ vty_out(vty, " class-400 %d%s", set->class_400, VTY_NEWLINE);
+ if (sup->dcs)
+ vty_out(vty, " class-dcs %d%s", set->class_dcs, VTY_NEWLINE);
+ if (sup->pcs)
+ vty_out(vty, " class-pcs %d%s", set->class_pcs, VTY_NEWLINE);
switch (set->ch_cap) {
case GSM_CAP_SDCCH:
vty_out(vty, " channel-capability sdcch%s", VTY_NEWLINE);
@@ -1538,14 +1556,24 @@ DEFUN(cfg_ms_no_sim_delay, cfg_ms_no_sim_delay_cmd, "no simulated-delay",
return CMD_SUCCESS;
}
-DEFUN(cfg_ms_stick, cfg_ms_stick_cmd, "stick <0-1023>",
- "Stick to the given cell\nARFCN of the cell to stick to")
+DEFUN(cfg_ms_stick, cfg_ms_stick_cmd, "stick <0-1023> [pcs]",
+ "Stick to the given cell\nARFCN of the cell to stick to\n"
+ "Given frequency is PCS band (1900) rather than DCS band.")
{
struct osmocom_ms *ms = vty->index;
struct gsm_settings *set = &ms->settings;
+ uint16_t arfcn = atoi(argv[0]);
+ if (argc > 1) {
+ if (arfcn < 512 || arfcn > 810) {
+ vty_out(vty, "Given ARFCN not in PCS band%s",
+ VTY_NEWLINE);
+ return CMD_WARNING;
+ }
+ arfcn |= ARFCN_PCS;
+ }
set->stick = 1;
- set->stick_arfcn = atoi(argv[0]);
+ set->stick_arfcn = arfcn;
return CMD_SUCCESS;
}
@@ -1843,9 +1871,23 @@ SUP_DI(cfg_ms_sup_no_r_gsm, cfg_ms_sup_no_r_gsm_cmd, r_gsm, "r-gsm",
"R-GSM (850)", 1);
SUP_EN(cfg_ms_sup_dcs, cfg_ms_sup_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
SUP_DI(cfg_ms_sup_no_dcs, cfg_ms_sup_no_dcs_cmd, dcs, "dcs", "DCS (1800)", 0);
+SUP_EN(cfg_ms_sup_gsm_850, cfg_ms_sup_gsm_850_cmd, gsm_850, "gsm-850",
+ "GSM 850", 0);
+SUP_DI(cfg_ms_sup_no_gsm_850, cfg_ms_sup_no_gsm_850_cmd, gsm_850, "gsm-850",
+ "GSM 850", 0);
+SUP_EN(cfg_ms_sup_pcs, cfg_ms_sup_pcs_cmd, pcs, "pcs", "PCS (1900)", 0);
+SUP_DI(cfg_ms_sup_no_pcs, cfg_ms_sup_no_pcs_cmd, pcs, "pcs", "PCS (1900)", 0);
+SUP_EN(cfg_ms_sup_gsm_480, cfg_ms_sup_gsm_480_cmd, gsm_480, "gsm-480",
+ "GSM 480", 0);
+SUP_DI(cfg_ms_sup_no_gsm_480, cfg_ms_sup_no_gsm_480_cmd, gsm_480, "gsm-480",
+ "GSM 480", 0);
+SUP_EN(cfg_ms_sup_gsm_450, cfg_ms_sup_gsm_450_cmd, gsm_450, "gsm-450",
+ "GSM 450", 0);
+SUP_DI(cfg_ms_sup_no_gsm_450, cfg_ms_sup_no_gsm_450_cmd, gsm_450, "gsm-450",
+ "GSM 450", 0);
DEFUN(cfg_ms_sup_class_900, cfg_ms_sup_class_900_cmd, "class-900 (1|2|3|4|5)",
- "Select power class for GSM 850/900\n"
+ "Select power class for GSM 900\n"
"20 Watts\n"
"8 Watts\n"
"5 Watts\n"
@@ -1859,7 +1901,49 @@ DEFUN(cfg_ms_sup_class_900, cfg_ms_sup_class_900_cmd, "class-900 (1|2|3|4|5)",
set->class_900 = atoi(argv[0]);
if (set->class_900 < sup->class_900 && !vty_reading)
- vty_out(vty, "You selected an higher class than supported "
+ vty_out(vty, "Note: You selected a higher class than supported "
+ " by hardware!%s", VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_sup_class_850, cfg_ms_sup_class_850_cmd, "class-850 (1|2|3|4|5)",
+ "Select power class for GSM 850\n"
+ "20 Watts\n"
+ "8 Watts\n"
+ "5 Watts\n"
+ "2 Watts\n"
+ "0.8 Watts")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+ struct gsm_support *sup = &ms->support;
+
+ set->class_850 = atoi(argv[0]);
+
+ if (set->class_850 < sup->class_850 && !vty_reading)
+ vty_out(vty, "Note: You selected a higher class than supported "
+ " by hardware!%s", VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_sup_class_400, cfg_ms_sup_class_400_cmd, "class-400 (1|2|3|4|5)",
+ "Select power class for GSM 400 (480 and 450)\n"
+ "20 Watts\n"
+ "8 Watts\n"
+ "5 Watts\n"
+ "2 Watts\n"
+ "0.8 Watts")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+ struct gsm_support *sup = &ms->support;
+
+ set->class_400 = atoi(argv[0]);
+
+ if (set->class_400 < sup->class_400 && !vty_reading)
+ vty_out(vty, "Note: You selected a higher class than supported "
" by hardware!%s", VTY_NEWLINE);
return CMD_SUCCESS;
@@ -1879,7 +1963,27 @@ DEFUN(cfg_ms_sup_class_dcs, cfg_ms_sup_class_dcs_cmd, "class-dcs (1|2|3)",
if (((set->class_dcs + 1) & 3) < ((sup->class_dcs + 1) & 3)
&& !vty_reading)
- vty_out(vty, "You selected an higher class than supported "
+ vty_out(vty, "Note: You selected a higher class than supported "
+ " by hardware!%s", VTY_NEWLINE);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_ms_sup_class_pcs, cfg_ms_sup_class_pcs_cmd, "class-pcs (1|2|3)",
+ "Select power class for PCS 1900\n"
+ "1 Watt\n"
+ "0.25 Watts\n"
+ "4 Watts")
+{
+ struct osmocom_ms *ms = vty->index;
+ struct gsm_settings *set = &ms->settings;
+ struct gsm_support *sup = &ms->support;
+
+ set->class_pcs = atoi(argv[0]);
+
+ if (((set->class_pcs + 1) & 3) < ((sup->class_pcs + 1) & 3)
+ && !vty_reading)
+ vty_out(vty, "Note: You selected a higher class than supported "
" by hardware!%s", VTY_NEWLINE);
return CMD_SUCCESS;
@@ -2386,8 +2490,19 @@ int ms_vty_init(void)
install_element(SUPPORT_NODE, &cfg_ms_sup_no_r_gsm_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_dcs_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_no_dcs_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_850_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_850_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_pcs_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_no_pcs_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_480_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_480_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_gsm_450_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_no_gsm_450_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_class_900_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_class_dcs_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_class_850_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_class_pcs_cmd);
+ install_element(SUPPORT_NODE, &cfg_ms_sup_class_400_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_ch_cap_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_full_v1_cmd);
install_element(SUPPORT_NODE, &cfg_ms_sup_no_full_v1_cmd);