diff options
-rw-r--r-- | src/host/gsmmap/gsmmap.c | 3 | ||||
-rw-r--r-- | src/host/layer23/include/osmocom/bb/common/sysinfo.h | 10 | ||||
-rw-r--r-- | src/host/layer23/include/osmocom/bb/mobile/gsm322.h | 10 | ||||
-rw-r--r-- | src/host/layer23/include/osmocom/bb/mobile/gsm48_mm.h | 1 | ||||
-rw-r--r-- | src/host/layer23/include/osmocom/bb/mobile/settings.h | 23 | ||||
-rw-r--r-- | src/host/layer23/include/osmocom/bb/mobile/support.h | 22 | ||||
-rw-r--r-- | src/host/layer23/src/common/sysinfo.c | 85 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/app_mobile.c | 1 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/gsm322.c | 395 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/gsm48_mm.c | 29 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/gsm48_rr.c | 206 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/settings.c | 41 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/support.c | 109 | ||||
-rw-r--r-- | src/host/layer23/src/mobile/vty_interface.c | 155 |
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); |