diff options
author | Harald Welte <laforge@gnumonks.org> | 2011-03-04 13:41:31 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2011-03-04 13:44:07 +0100 |
commit | fd355a3c6feccca5b774c0b3291a6066d0459067 (patch) | |
tree | c6840a0623d7bb863b2ba3ef2356bdbfa3fe9aa8 /openbsc/src/libbsc | |
parent | 89579b4317a7f7ab6ee706399bee4b8f25a12c3a (diff) |
[HSL] initial support for the HSL 2.75G Femtocell
The HSL Femtocell seems to be a poor man implementation of the
ip.access Abis/IP protocol, but cutting corners wherever possible.
We try to workaround those corners wherever possible...
Diffstat (limited to 'openbsc/src/libbsc')
-rw-r--r-- | openbsc/src/libbsc/Makefile.am | 6 | ||||
-rw-r--r-- | openbsc/src/libbsc/abis_nm.c | 6 | ||||
-rw-r--r-- | openbsc/src/libbsc/abis_rsl.c | 12 | ||||
-rw-r--r-- | openbsc/src/libbsc/bsc_init.c | 36 | ||||
-rw-r--r-- | openbsc/src/libbsc/bsc_vty.c | 30 | ||||
-rw-r--r-- | openbsc/src/libbsc/bts_hsl_femtocell.c | 146 | ||||
-rw-r--r-- | openbsc/src/libbsc/system_information.c | 14 |
7 files changed, 239 insertions, 11 deletions
diff --git a/openbsc/src/libbsc/Makefile.am b/openbsc/src/libbsc/Makefile.am index 91be7fa62..de7692950 100644 --- a/openbsc/src/libbsc/Makefile.am +++ b/openbsc/src/libbsc/Makefile.am @@ -8,7 +8,11 @@ libbsc_a_SOURCES = abis_nm.c abis_nm_vty.c \ abis_om2000.c abis_om2000_vty.c \ abis_rsl.c bsc_rll.c \ paging.c \ - bts_ericsson_rbs2000.c bts_ipaccess_nanobts.c bts_siemens_bs11.c bts_unknown.c \ + bts_ericsson_rbs2000.c \ + bts_ipaccess_nanobts.c \ + bts_siemens_bs11.c \ + bts_hsl_femtocell.c \ + bts_unknown.c \ chan_alloc.c \ gsm_subscriber_base.c \ handover_decision.c handover_logic.c meas_rep.c \ diff --git a/openbsc/src/libbsc/abis_nm.c b/openbsc/src/libbsc/abis_nm.c index 45db8bac5..0e7fc8d8c 100644 --- a/openbsc/src/libbsc/abis_nm.c +++ b/openbsc/src/libbsc/abis_nm.c @@ -1080,6 +1080,12 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb) case NM_MT_IPACC_RESTART_NACK: dispatch_signal(SS_NM, S_NM_IPACC_RESTART_NACK, NULL); break; + case NM_MT_SET_BTS_ATTR_ACK: + /* The HSL wants an OPSTART _after_ the SI has been set */ + if (mb->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO) { + abis_nm_opstart(mb->trx->bts, NM_OC_BTS, 255, 255, 255); + } + break; } abis_nm_queue_send_next(mb->trx->bts); diff --git a/openbsc/src/libbsc/abis_rsl.c b/openbsc/src/libbsc/abis_rsl.c index 07a7dc68c..58e2a7cd7 100644 --- a/openbsc/src/libbsc/abis_rsl.c +++ b/openbsc/src/libbsc/abis_rsl.c @@ -636,11 +636,14 @@ static void error_timeout_cb(void *data) rsl_lchan_set_state(lchan, LCHAN_S_NONE); } +static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan); + /* Chapter 8.4.14 / 4.7: Tell BTS to release the radio channel */ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error) { struct abis_rsl_dchan_hdr *dh; struct msgb *msg; + int rc; if (lchan->state == LCHAN_S_REL_ERR) { LOGP(DRSL, LOGL_NOTICE, "%s is in error state not sending release.\n", @@ -671,8 +674,15 @@ static int rsl_rf_chan_release(struct gsm_lchan *lchan, int error) msg->trx->bts->network->T3111 + 2, 0); } + rc = abis_rsl_sendmsg(msg); + /* BTS will respond by RF CHAN REL ACK */ - return abis_rsl_sendmsg(msg); + + /* The HSL Femto seems to 'forget' sending a REL ACK for TS1...TS7 */ + if (lchan->ts->trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO && lchan->ts->nr != 0) + rc = rsl_rx_rf_chan_rel_ack(lchan); + + return rc; } static int rsl_rx_rf_chan_rel_ack(struct gsm_lchan *lchan) diff --git a/openbsc/src/libbsc/bsc_init.c b/openbsc/src/libbsc/bsc_init.c index 752056c37..0072bb6f8 100644 --- a/openbsc/src/libbsc/bsc_init.c +++ b/openbsc/src/libbsc/bsc_init.c @@ -92,13 +92,14 @@ int bsc_shutdown_net(struct gsm_network *net) static int generate_and_rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i) { struct gsm_bts *bts = trx->bts; - int rc; + int si_len, rc, j; /* Only generate SI if this SI is not in "static" (user-defined) mode */ if (!(bts->si_mode_static & (1 << i))) { rc = gsm_generate_si(bts, i); if (rc < 0) return rc; + si_len = rc; } DEBUGP(DRR, "SI%s: %s\n", gsm_sitype_name(i), @@ -109,8 +110,25 @@ static int generate_and_rsl_si(struct gsm_bts_trx *trx, enum osmo_sysinfo_type i case SYSINFO_TYPE_5bis: case SYSINFO_TYPE_5ter: case SYSINFO_TYPE_6: - rc = rsl_sacch_filling(trx, gsm_sitype2rsl(i), - GSM_BTS_SI(bts, i), rc); + if (trx->bts->type == GSM_BTS_TYPE_HSL_FEMTO) { + /* HSL has mistaken SACCH INFO MODIFY for SACCH FILLING, + * so we need a special workaround here */ + /* This assumes a combined BCCH and TCH on TS1...7 */ + for (j = 0; j < 4; j++) + rsl_sacch_info_modify(&trx->ts[0].lchan[j], + gsm_sitype2rsl(i), + GSM_BTS_SI(bts, i), si_len); + for (j = 1; j < 8; j++) { + rsl_sacch_info_modify(&trx->ts[j].lchan[0], + gsm_sitype2rsl(i), + GSM_BTS_SI(bts, i), si_len); + rsl_sacch_info_modify(&trx->ts[j].lchan[1], + gsm_sitype2rsl(i), + GSM_BTS_SI(bts, i), si_len); + } + } else + rc = rsl_sacch_filling(trx, gsm_sitype2rsl(i), + GSM_BTS_SI(bts, i), rc); break; default: rc = rsl_bcch_info(trx, gsm_sitype2rsl(i), @@ -423,9 +441,16 @@ int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *), register_signal_handler(SS_INPUT, inp_sig_cb, NULL); llist_for_each_entry(bts, &bsc_gsmnet->bts_list, list) { - bootstrap_bts(bts); - if (!is_ipaccess_bts(bts)) + rc = bootstrap_bts(bts); + + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: + case GSM_BTS_TYPE_HSL_FEMTO: + break; + default: rc = e1_reconfig_bts(bts); + break; + } if (rc < 0) { fprintf(stderr, "Error in E1 input driver setup\n"); @@ -435,6 +460,7 @@ int bsc_bootstrap_network(int (*mncc_recv)(struct gsm_network *, struct msgb *), /* initialize nanoBTS support omce */ rc = ipaccess_setup(bsc_gsmnet); + rc = hsl_setup(bsc_gsmnet); return 0; } diff --git a/openbsc/src/libbsc/bsc_vty.c b/openbsc/src/libbsc/bsc_vty.c index ed45afd4d..57a0c2005 100644 --- a/openbsc/src/libbsc/bsc_vty.c +++ b/openbsc/src/libbsc/bsc_vty.c @@ -253,6 +253,8 @@ static void bts_dump_vty(struct vty *vty, struct gsm_bts *bts) vty_out(vty, " Unit ID: %u/%u/0, OML Stream ID 0x%02x%s", bts->ip_access.site_id, bts->ip_access.bts_id, bts->oml_tei, VTY_NEWLINE); + else if (bts->type == GSM_BTS_TYPE_HSL_FEMTO) + vty_out(vty, " Serial Number: %lu%s", bts->hsl.serno, VTY_NEWLINE); vty_out(vty, " NM State: "); net_dump_nmstate(vty, &bts->nm_state); vty_out(vty, " Site Mgr NM State: "); @@ -497,13 +499,19 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) VTY_NEWLINE); } } - if (is_ipaccess_bts(bts)) { + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: vty_out(vty, " ip.access unit_id %u %u%s", bts->ip_access.site_id, bts->ip_access.bts_id, VTY_NEWLINE); vty_out(vty, " oml ip.access stream_id %u%s", bts->oml_tei, VTY_NEWLINE); - } else { + break; + case GSM_BTS_TYPE_HSL_FEMTO: + vty_out(vty, " hsl serial-number %lu%s", bts->hsl.serno, VTY_NEWLINE); + break; + default: config_write_e1_link(vty, &bts->oml_e1_link, " oml "); vty_out(vty, " oml e1 tei %u%s", bts->oml_tei, VTY_NEWLINE); + break; } /* if we have a limit, write it */ @@ -1584,6 +1592,23 @@ DEFUN(cfg_bts_unit_id, return CMD_SUCCESS; } +DEFUN(cfg_bts_serno, + cfg_bts_serno_cmd, + "hsl serial-number STRING", + "Set the HSL Serial Number of this BTS\n") +{ + struct gsm_bts *bts = vty->index; + + if (bts->type != GSM_BTS_TYPE_HSL_FEMTO) { + vty_out(vty, "%% BTS is not of HSL type%s", VTY_NEWLINE); + return CMD_WARNING; + } + + bts->hsl.serno = strtoul(argv[0], NULL, 10); + + return CMD_SUCCESS; +} + #define OML_STR "Organization & Maintenance Link\n" #define IPA_STR "ip.access Specific Options\n" @@ -2696,6 +2721,7 @@ int bsc_vty_init(void) install_element(BTS_NODE, &cfg_bts_tsc_cmd); install_element(BTS_NODE, &cfg_bts_bsic_cmd); install_element(BTS_NODE, &cfg_bts_unit_id_cmd); + install_element(BTS_NODE, &cfg_bts_serno_cmd); install_element(BTS_NODE, &cfg_bts_stream_id_cmd); install_element(BTS_NODE, &cfg_bts_oml_e1_cmd); install_element(BTS_NODE, &cfg_bts_oml_e1_tei_cmd); diff --git a/openbsc/src/libbsc/bts_hsl_femtocell.c b/openbsc/src/libbsc/bts_hsl_femtocell.c new file mode 100644 index 000000000..2813195b2 --- /dev/null +++ b/openbsc/src/libbsc/bts_hsl_femtocell.c @@ -0,0 +1,146 @@ +/* OpenBSC support code for HSL Femtocell */ + +/* (C) 2011 by Harald Welte <laforge@gnumonks.org> + * (C) 2011 by OnWaves + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU Affero General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + * + */ + +#include <sys/types.h> + +#include <arpa/inet.h> + +#include <osmocore/tlv.h> +#include <openbsc/gsm_data.h> +#include <openbsc/abis_nm.h> +#include <openbsc/abis_rsl.h> +#include <openbsc/signal.h> +#include <openbsc/e1_input.h> + +static struct gsm_bts_model model_hslfemto = { + .type = GSM_BTS_TYPE_HSL_FEMTO, + .nm_att_tlvdef = { + .def = { + /* no HSL specific OML attributes that we know of */ + }, + }, +}; + + +static const uint8_t l1_msg[] = { + 0x80, 0x8a, + 0xC4, 0x0b, +}; + +static const uint8_t conn_trau_msg[] = { + 0x80, 0x81, + 0xC1, 16, + 0x02, 0x00, 0x00, 0x00, 0xC0, 0xA8, 0xEA, 0x01, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 +}; + +static const uint8_t conn_trau_msg2[] = { + 0x80, 0x81, + 0xC1, 16, + 0x02, 0x00, 0xd4, 0x07, 0xC0, 0xA8, 0xEA, 0x01, + 0x38, 0xA4, 0x45, 0x00, 0x04, 0x59, 0x40, 0x00 +}; + +static uint8_t oml_arfcn_bsic[] = { + 0x81, 0x80, 0x00, 10, + NM_MT_SET_BTS_ATTR, NM_OC_BTS, 0xff, 0xff, 0xff, + NM_ATT_BCCH_ARFCN, 0x03, 0x67, + NM_ATT_BSIC, 0x00 +}; + +static inline struct msgb *hsl_alloc_msgb(void) +{ + return msgb_alloc_headroom(1024, 127, "HSL"); +} + +static int hslfemto_bootstrap_om(struct gsm_bts *bts) +{ + struct msgb *msg; + uint8_t *cur; + + msg = hsl_alloc_msgb(); + cur = msgb_put(msg, sizeof(l1_msg)); + memcpy(msg->data, l1_msg, sizeof(l1_msg)); + msg->trx = bts->c0; + abis_rsl_sendmsg(msg); + +#if 1 + msg = hsl_alloc_msgb(); + cur = msgb_put(msg, sizeof(conn_trau_msg)); + memcpy(msg->data, conn_trau_msg, sizeof(conn_trau_msg)); + msg->trx = bts->c0; + abis_rsl_sendmsg(msg); +#endif + msg = hsl_alloc_msgb(); + cur = msgb_put(msg, sizeof(conn_trau_msg2)); + memcpy(msg->data, conn_trau_msg2, sizeof(conn_trau_msg2)); + msg->trx = bts->c0; + abis_rsl_sendmsg(msg); + + *((uint16_t *)oml_arfcn_bsic+10) = htons(bts->c0->arfcn); + oml_arfcn_bsic[13] = bts->bsic; + + msg = hsl_alloc_msgb(); + cur = msgb_put(msg, sizeof(oml_arfcn_bsic)); + memcpy(msg->data, oml_arfcn_bsic, sizeof(oml_arfcn_bsic)); + msg->trx = bts->c0; + _abis_nm_sendmsg(msg, 0); + + /* Delay the OPSTART until after SI have been set via RSL */ + //abis_nm_opstart(bts, NM_OC_BTS, 255, 255, 255); + + return 0; +} + +/* Callback function to be called every time we receive a signal from INPUT */ +static int inp_sig_cb(unsigned int subsys, unsigned int signal, + void *handler_data, void *signal_data) +{ + struct input_signal_data *isd = signal_data; + + if (subsys != SS_INPUT) + return 0; + + switch (signal) { + case S_INP_TEI_UP: + switch (isd->link_type) { + case E1INP_SIGN_OML: + hslfemto_bootstrap_om(isd->trx->bts); + break; + } + } + + return 0; +} + +int bts_model_hslfemto_init(void) +{ + model_hslfemto.features.data = &model_hslfemto._features_data[0]; + model_hslfemto.features.data_len = sizeof(model_hslfemto._features_data); + + gsm_btsmodel_set_feature(&model_hslfemto, BTS_FEAT_GPRS); + gsm_btsmodel_set_feature(&model_hslfemto, BTS_FEAT_EGPRS); + + register_signal_handler(SS_INPUT, inp_sig_cb, NULL); + + return gsm_bts_model_register(&model_hslfemto); +} diff --git a/openbsc/src/libbsc/system_information.c b/openbsc/src/libbsc/system_information.c index 8a99c565e..dc719388b 100644 --- a/openbsc/src/libbsc/system_information.c +++ b/openbsc/src/libbsc/system_information.c @@ -370,9 +370,14 @@ static int generate_si5(u_int8_t *output, struct gsm_bts *bts) memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN); /* ip.access nanoBTS needs l2_plen!! */ - if (is_ipaccess_bts(bts)) { + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: + case GSM_BTS_TYPE_HSL_FEMTO: *output++ = (l2_plen << 2) | 1; l2_plen++; + break; + default: + break; } si5 = (struct gsm48_system_information_type_5 *) output; @@ -397,9 +402,14 @@ static int generate_si6(u_int8_t *output, struct gsm_bts *bts) memset(output, GSM_MACBLOCK_PADDING, GSM_MACBLOCK_LEN); /* ip.access nanoBTS needs l2_plen!! */ - if (is_ipaccess_bts(bts)) { + switch (bts->type) { + case GSM_BTS_TYPE_NANOBTS: + case GSM_BTS_TYPE_HSL_FEMTO: *output++ = (l2_plen << 2) | 1; l2_plen++; + break; + default: + break; } si6 = (struct gsm48_system_information_type_6 *) output; |