summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndreas.Eversberg <jolly@eversberg.eu>2011-03-16 08:52:01 +0000
committerSylvain Munaut <tnt@246tNt.com>2011-05-29 19:51:54 +0200
commit58ac7e0e98c448dcece8e7dfa53f484c982e96cf (patch)
tree9e81e18348a4b3cf76dc3b204a5493f1f9e6cca1
parent16ec2358a014f290be47e87e3489f98769681979 (diff)
[layer23] Adding Quadband support and GSM 4x0 support
This makes it possible to use GSM 850 and PCS 1900 bands, as used in the US. The support relies on the phone hardware. Each band (900, DCS, 850, PCS, 480 and 450) can be enabled and disabled individually for each setting.
-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);