aboutsummaryrefslogtreecommitdiffstats
path: root/openbsc/src/abis_nm.c
diff options
context:
space:
mode:
Diffstat (limited to 'openbsc/src/abis_nm.c')
-rw-r--r--openbsc/src/abis_nm.c364
1 files changed, 234 insertions, 130 deletions
diff --git a/openbsc/src/abis_nm.c b/openbsc/src/abis_nm.c
index bb7248be7..99d8dd621 100644
--- a/openbsc/src/abis_nm.c
+++ b/openbsc/src/abis_nm.c
@@ -38,15 +38,16 @@
#include <openbsc/gsm_data.h>
#include <openbsc/debug.h>
-#include <openbsc/msgb.h>
-#include <openbsc/tlv.h>
+#include <osmocore/msgb.h>
+#include <osmocore/tlv.h>
+#include <osmocore/talloc.h>
#include <openbsc/abis_nm.h>
#include <openbsc/misdn.h>
#include <openbsc/signal.h>
-#include <openbsc/talloc.h>
#define OM_ALLOC_SIZE 1024
#define OM_HEADROOM_SIZE 128
+#define IPACC_SEGMENT_SIZE 245
/* unidirectional messages from BTS to BSC */
static const enum abis_nm_msgtype reports[] = {
@@ -263,7 +264,7 @@ static const enum abis_nm_attr nm_att_settable[] = {
NM_ATT_MEAS_TYPE,
};
-static const struct tlv_definition nm_att_tlvdef = {
+const struct tlv_definition nm_att_tlvdef = {
.def = {
[NM_ATT_ABIS_CHANNEL] = { TLV_TYPE_FIXED, 3 },
[NM_ATT_ADD_INFO] = { TLV_TYPE_TL16V },
@@ -329,77 +330,6 @@ static const struct tlv_definition nm_att_tlvdef = {
[NM_ATT_HW_CONF_CHG] = { TLV_TYPE_TL16V },
[NM_ATT_OUTST_ALARM] = { TLV_TYPE_TV },
[NM_ATT_MEAS_RES] = { TLV_TYPE_TL16V },
- /* BS11 specifics */
- [NM_ATT_BS11_ESN_FW_CODE_NO] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_ESN_HW_CODE_NO] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_ESN_PCB_SERIAL] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_BOOT_SW_VERS] = { TLV_TYPE_TLV },
- [0xd5] = { TLV_TYPE_TLV },
- [0xa8] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_PASSWORD] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_TXPWR] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_RSSI_OFFS] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_LINE_CFG] = { TLV_TYPE_TV },
- [NM_ATT_BS11_L1_PROT_TYPE] = { TLV_TYPE_TV },
- [NM_ATT_BS11_BIT_ERR_THESH] = { TLV_TYPE_FIXED, 2 },
- [NM_ATT_BS11_DIVERSITY] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_LMT_LOGON_SESSION]={ TLV_TYPE_TLV },
- [NM_ATT_BS11_LMT_LOGIN_TIME] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_LMT_USER_ACC_LEV] ={ TLV_TYPE_TLV },
- [NM_ATT_BS11_LMT_USER_NAME] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_BTS_STATE] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_E1_STATE] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_PLL_MODE] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_PLL] = { TLV_TYPE_TLV },
- [NM_ATT_BS11_CCLK_ACCURACY] = { TLV_TYPE_TV },
- [NM_ATT_BS11_CCLK_TYPE] = { TLV_TYPE_TV },
- /* ip.access specifics */
- [NM_ATT_IPACC_DST_IP] = { TLV_TYPE_FIXED, 4 },
- [NM_ATT_IPACC_DST_IP_PORT] = { TLV_TYPE_FIXED, 2 },
- [NM_ATT_IPACC_STREAM_ID] = { TLV_TYPE_TV, },
- [NM_ATT_IPACC_FREQ_CTRL] = { TLV_TYPE_TV, },
- [NM_ATT_IPACC_SEC_OML_CFG] = { TLV_TYPE_FIXED, 6 },
- [NM_ATT_IPACC_IP_IF_CFG] = { TLV_TYPE_FIXED, 8 },
- [NM_ATT_IPACC_IP_GW_CFG] = { TLV_TYPE_FIXED, 12 },
- [NM_ATT_IPACC_IN_SERV_TIME] = { TLV_TYPE_FIXED, 4 },
- [NM_ATT_IPACC_LOCATION] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_PAGING_CFG] = { TLV_TYPE_FIXED, 2 },
- [NM_ATT_IPACC_UNIT_ID] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_UNIT_NAME] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_SNMP_CFG] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_PRIM_OML_CFG_LIST] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_NV_FLAGS] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_FREQ_CTRL] = { TLV_TYPE_FIXED, 2 },
- [NM_ATT_IPACC_PRIM_OML_FB_TOUT] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_CUR_SW_CFG] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_TIMING_BUS] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_CGI] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_RAC] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_OBJ_VERSION] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_GPRS_PAGING_CFG]= { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_NSEI] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_BVCI] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_NSVCI] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_NS_CFG] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_BSSGP_CFG] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_NS_LINK_CFG] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_RLC_CFG] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_ALM_THRESH_LIST]= { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_MONIT_VAL_LIST] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_TIB_CONTROL] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_SUPP_FEATURES] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_CODING_SCHEMES] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_RLC_CFG_2] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_HEARTB_TOUT] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_UPTIME] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_RLC_CFG_3] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_SSL_CFG] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_SEC_POSSIBLE] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_IML_SSL_STATE] = { TLV_TYPE_TL16V },
- [NM_ATT_IPACC_REVOC_DATE] = { TLV_TYPE_TL16V },
- //[0x95] = { TLV_TYPE_FIXED, 2 },
- [0x85] = { TLV_TYPE_TV },
-
},
};
@@ -422,9 +352,11 @@ int abis_nm_chcomb4pchan(enum gsm_phys_chan_config pchan)
return -EINVAL;
}
-int abis_nm_tlv_parse(struct tlv_parsed *tp, const u_int8_t *buf, int len)
+int abis_nm_tlv_parse(struct tlv_parsed *tp, struct gsm_bts *bts, const u_int8_t *buf, int len)
{
- return tlv_parse(tp, &nm_att_tlvdef, buf, len, 0, 0);
+ if (!bts->model)
+ return -EIO;
+ return tlv_parse(tp, &bts->model->nm_att_tlvdef, buf, len, 0, 0);
}
static int is_in_arr(enum abis_nm_msgtype mt, const enum abis_nm_msgtype *arr, int size)
@@ -540,11 +472,11 @@ static const char *obj_class_name(u_int8_t oc)
const char *nm_opstate_name(u_int8_t os)
{
switch (os) {
- case 1:
+ case NM_OPSTATE_DISABLED:
return "Disabled";
- case 2:
+ case NM_OPSTATE_ENABLED:
return "Enabled";
- case 0xff:
+ case NM_OPSTATE_NULL:
return "NULL";
default:
return "RFU";
@@ -598,6 +530,13 @@ const char *nm_adm_name(u_int8_t adm)
}
}
+int nm_is_running(struct gsm_nm_state *s) {
+ return (s->operational == NM_OPSTATE_ENABLED) && (
+ (s->availability == NM_AVSTATE_OK) ||
+ (s->availability == 0xff)
+ );
+}
+
static void debugp_foh(struct abis_om_fom_hdr *foh)
{
DEBUGP(DNM, "OC=%s(%02x) INST=(%02x,%02x,%02x) ",
@@ -793,7 +732,7 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
new_state = *nm_state;
- abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
+ abis_nm_tlv_parse(&tp, bts, foh->data, oh->length-sizeof(*foh));
if (TLVP_PRESENT(&tp, NM_ATT_OPER_STATE)) {
new_state.operational = *TLVP_VAL(&tp, NM_ATT_OPER_STATE);
DEBUGPC(DNM, "OP_STATE=%s ", nm_opstate_name(new_state.operational));
@@ -805,19 +744,25 @@ static int abis_nm_rx_statechg_rep(struct msgb *mb)
new_state.availability = *TLVP_VAL(&tp, NM_ATT_AVAIL_STATUS);
DEBUGPC(DNM, "AVAIL=%s(%02x) ", nm_avail_name(new_state.availability),
new_state.availability);
- }
+ } else
+ new_state.availability = 0xff;
if (TLVP_PRESENT(&tp, NM_ATT_ADM_STATE)) {
new_state.administrative = *TLVP_VAL(&tp, NM_ATT_ADM_STATE);
DEBUGPC(DNM, "ADM=%2s ", nm_adm_name(new_state.administrative));
}
DEBUGPC(DNM, "\n");
- if (memcmp(&new_state, nm_state, sizeof(new_state))) {
+ if ((new_state.administrative != 0 && nm_state->administrative == 0) ||
+ new_state.operational != nm_state->operational ||
+ new_state.availability != nm_state->availability) {
/* Update the operational state of a given object in our in-memory data
* structures and send an event to the higher layer */
void *obj = objclass2obj(bts, foh->obj_class, &foh->obj_inst);
rc = nm_state_event(EVT_STATECHG_OPER, foh->obj_class, obj, nm_state, &new_state);
- *nm_state = new_state;
+ nm_state->operational = new_state.operational;
+ nm_state->availability = new_state.availability;
+ if (nm_state->administrative == 0)
+ nm_state->administrative = new_state.administrative;
}
#if 0
if (op_state == 1) {
@@ -839,7 +784,7 @@ static int rx_fail_evt_rep(struct msgb *mb)
DEBUGPC(DNM, "Failure Event Report ");
- abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
+ abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
if (TLVP_PRESENT(&tp, NM_ATT_EVENT_TYPE))
DEBUGPC(DNM, "Type=%s ", event_type_name(*TLVP_VAL(&tp, NM_ATT_EVENT_TYPE)));
@@ -933,7 +878,7 @@ static int abis_nm_rx_sw_act_req(struct msgb *mb)
if (nack)
return ret;
- abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
+ abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
sw_config = TLVP_VAL(&tp, NM_ATT_SW_CONFIG);
sw_config_len = TLVP_LEN(&tp, NM_ATT_SW_CONFIG);
if (!TLVP_PRESENT(&tp, NM_ATT_SW_CONFIG)) {
@@ -967,7 +912,7 @@ static int abis_nm_rx_chg_adm_state_ack(struct msgb *mb)
struct tlv_parsed tp;
u_int8_t adm_state;
- abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
+ abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
if (!TLVP_PRESENT(&tp, NM_ATT_ADM_STATE))
return -EINVAL;
@@ -983,7 +928,7 @@ static int abis_nm_rx_lmt_event(struct msgb *mb)
struct tlv_parsed tp;
DEBUGP(DNM, "LMT Event ");
- abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
+ abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
if (TLVP_PRESENT(&tp, NM_ATT_BS11_LMT_LOGON_SESSION) &&
TLVP_LEN(&tp, NM_ATT_BS11_LMT_LOGON_SESSION) >= 1) {
u_int8_t onoff = *TLVP_VAL(&tp, NM_ATT_BS11_LMT_LOGON_SESSION);
@@ -1029,7 +974,7 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
else
DEBUGPC(DNM, "NACK 0x%02x ", mt);
- abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
+ abis_nm_tlv_parse(&tp, mb->trx->bts, foh->data, oh->length-sizeof(*foh));
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
DEBUGPC(DNM, "CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
@@ -1043,13 +988,11 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
/* check if last message is to be acked */
if (is_ack_nack(nmh->last_msgtype)) {
if (mt == MT_ACK(nmh->last_msgtype)) {
- fprintf(stderr, "received ACK (0x%x)\n",
- foh->msg_type);
+ DEBUGP(DNM, "received ACK (0x%x)\n", foh->msg_type);
/* we got our ACK, continue sending the next msg */
} else if (mt == MT_NACK(nmh->last_msgtype)) {
/* we got a NACK, signal this to the caller */
- fprintf(stderr, "received NACK (0x%x)\n",
- foh->msg_type);
+ DEBUGP(DNM, "received NACK (0x%x)\n", foh->msg_type);
/* FIXME: somehow signal this to the caller */
} else {
/* really strange things happen */
@@ -1071,6 +1014,12 @@ static int abis_nm_rcvmsg_fom(struct msgb *mb)
case NM_MT_CONN_MDROP_LINK_ACK:
DEBUGP(DNM, "CONN MDROP LINK ACK\n");
break;
+ case NM_MT_IPACC_RESTART_ACK:
+ dispatch_signal(SS_NM, S_NM_IPACC_RESTART_ACK, NULL);
+ break;
+ case NM_MT_IPACC_RESTART_NACK:
+ dispatch_signal(SS_NM, S_NM_IPACC_RESTART_NACK, NULL);
+ break;
}
return 0;
@@ -1216,6 +1165,22 @@ struct abis_nm_sw {
static struct abis_nm_sw g_sw;
+static void sw_add_file_id_and_ver(struct abis_nm_sw *sw, struct msgb *msg)
+{
+ if (sw->bts->type == GSM_BTS_TYPE_NANOBTS) {
+ msgb_v_put(msg, NM_ATT_SW_DESCR);
+ msgb_tl16v_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tl16v_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else if (sw->bts->type == GSM_BTS_TYPE_BS11) {
+ msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
+ msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
+ sw->file_version);
+ } else {
+ LOGP(DNM, LOGL_ERROR, "Please implement this for the BTS.\n");
+ }
+}
+
/* 6.2.1 / 8.3.1: Load Data Initiate */
static int sw_load_init(struct abis_nm_sw *sw)
{
@@ -1227,11 +1192,8 @@ static int sw_load_init(struct abis_nm_sw *sw)
fill_om_fom_hdr(oh, len, NM_MT_LOAD_INIT, sw->obj_class,
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
-
- /* FIXME: this is BS11 specific format */
- msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
- msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
- sw->file_version);
+
+ sw_add_file_id_and_ver(sw, msg);
msgb_tv_put(msg, NM_ATT_WINDOW_SIZE, sw->window_size);
return abis_nm_sendmsg(sw->bts, msg);
@@ -1289,7 +1251,24 @@ static int sw_load_segment(struct abis_nm_sw *sw)
/* we only now know the exact length for the OM hdr */
len = strlen(line_buf)+2;
break;
+ case GSM_BTS_TYPE_NANOBTS: {
+ static_assert(sizeof(seg_buf) >= IPACC_SEGMENT_SIZE, buffer_big_enough);
+ len = read(sw->fd, &seg_buf, IPACC_SEGMENT_SIZE);
+ if (len < 0) {
+ perror("read failed");
+ return -EINVAL;
+ }
+
+ if (len != IPACC_SEGMENT_SIZE)
+ sw->last_seg = 1;
+
+ ++sw->seg_in_window;
+ msgb_tl16v_put(msg, NM_ATT_IPACC_FILE_DATA, len, (const u_int8_t *) seg_buf);
+ len += 3;
+ break;
+ }
default:
+ LOGP(DNM, LOGL_ERROR, "sw_load_segment needs implementation for the BTS.\n");
/* FIXME: Other BTS types */
return -1;
}
@@ -1313,11 +1292,7 @@ static int sw_load_end(struct abis_nm_sw *sw)
sw->obj_instance[0], sw->obj_instance[1],
sw->obj_instance[2]);
- /* FIXME: this is BS11 specific format */
- msgb_tlv_put(msg, NM_ATT_FILE_ID, sw->file_id_len, sw->file_id);
- msgb_tlv_put(msg, NM_ATT_FILE_VERSION, sw->file_version_len,
- sw->file_version);
-
+ sw_add_file_id_and_ver(sw, msg);
return abis_nm_sendmsg(sw->bts, msg);
}
@@ -1341,6 +1316,59 @@ static int sw_activate(struct abis_nm_sw *sw)
return abis_nm_sendmsg(sw->bts, msg);
}
+struct sdp_firmware {
+ char magic[4];
+ char more_magic[4];
+ unsigned int header_length;
+ unsigned int file_length;
+} __attribute__ ((packed));
+
+static int parse_sdp_header(struct abis_nm_sw *sw)
+{
+ struct sdp_firmware firmware_header;
+ int rc;
+ struct stat stat;
+
+ rc = read(sw->fd, &firmware_header, sizeof(firmware_header));
+ if (rc != sizeof(firmware_header)) {
+ LOGP(DNM, LOGL_ERROR, "Could not read SDP file header.\n");
+ return -1;
+ }
+
+ if (strncmp(firmware_header.magic, " SDP", 4) != 0) {
+ LOGP(DNM, LOGL_ERROR, "The magic number1 is wrong.\n");
+ return -1;
+ }
+
+ if (firmware_header.more_magic[0] != 0x10 ||
+ firmware_header.more_magic[1] != 0x02 ||
+ firmware_header.more_magic[2] != 0x00 ||
+ firmware_header.more_magic[3] != 0x00) {
+ LOGP(DNM, LOGL_ERROR, "The more magic number is wrong.\n");
+ return -1;
+ }
+
+
+ if (fstat(sw->fd, &stat) == -1) {
+ LOGP(DNM, LOGL_ERROR, "Could not stat the file.\n");
+ return -1;
+ }
+
+ if (ntohl(firmware_header.file_length) != stat.st_size) {
+ LOGP(DNM, LOGL_ERROR, "The filesizes do not match.\n");
+ return -1;
+ }
+
+ /* go back to the start as we checked the whole filesize.. */
+ lseek(sw->fd, 0l, SEEK_SET);
+ LOGP(DNM, LOGL_NOTICE, "The ipaccess SDP header is not fully understood.\n"
+ "There might be checksums in the file that are not\n"
+ "verified and incomplete firmware might be flashed.\n"
+ "There is absolutely no WARRANTY that flashing will\n"
+ "work.\n");
+ return 0;
+}
+
static int sw_open_file(struct abis_nm_sw *sw, const char *fname)
{
char file_id[12+1];
@@ -1372,6 +1400,19 @@ static int sw_open_file(struct abis_nm_sw *sw, const char *fname)
/* rewind to start of file */
rewind(sw->stream);
break;
+ case GSM_BTS_TYPE_NANOBTS:
+ /* TODO: extract that from the filename or content */
+ rc = parse_sdp_header(sw);
+ if (rc < 0) {
+ fprintf(stderr, "Could not parse the ipaccess SDP header\n");
+ return -1;
+ }
+
+ strcpy((char *)sw->file_id, "id");
+ sw->file_id_len = 3;
+ strcpy((char *)sw->file_version, "version");
+ sw->file_version_len = 8;
+ break;
default:
/* We don't know how to treat them yet */
close(sw->fd);
@@ -1470,6 +1511,12 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
rc = sw_load_end(sw);
}
break;
+ case NM_MT_LOAD_ABORT:
+ if (sw->cbfn)
+ sw->cbfn(GSM_HOOK_NM_SWLOAD,
+ NM_MT_LOAD_ABORT, mb,
+ sw->cb_data, NULL);
+ break;
}
break;
case SW_STATE_WAIT_ENDACK:
@@ -1483,6 +1530,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb)
sw->cbfn(GSM_HOOK_NM_SWLOAD,
NM_MT_LOAD_END_ACK, mb,
sw->cb_data, NULL);
+ rc = 0;
break;
case NM_MT_LOAD_END_NACK:
if (sw->forced) {
@@ -1559,10 +1607,26 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname,
return -EBUSY;
sw->bts = bts;
- sw->obj_class = NM_OC_SITE_MANAGER;
- sw->obj_instance[0] = 0xff;
- sw->obj_instance[1] = 0xff;
- sw->obj_instance[2] = 0xff;
+
+ switch (bts->type) {
+ case GSM_BTS_TYPE_BS11:
+ sw->obj_class = NM_OC_SITE_MANAGER;
+ sw->obj_instance[0] = 0xff;
+ sw->obj_instance[1] = 0xff;
+ sw->obj_instance[2] = 0xff;
+ break;
+ case GSM_BTS_TYPE_NANOBTS:
+ sw->obj_class = NM_OC_BASEB_TRANSC;
+ sw->obj_instance[0] = 0x00;
+ sw->obj_instance[1] = 0x00;
+ sw->obj_instance[2] = 0xff;
+ break;
+ case GSM_BTS_TYPE_UNKNOWN:
+ default:
+ LOGPC(DNM, LOGL_ERROR, "Software Load not properly implemented.\n");
+ return -1;
+ break;
+ }
sw->window_size = win_size;
sw->state = SW_STATE_WAIT_INITACK;
sw->cbfn = cbfn;
@@ -1590,7 +1654,10 @@ int abis_nm_software_load_status(struct gsm_bts *bts)
return rc;
}
- percent = (ftell(sw->stream) * 100) / st.st_size;
+ if (sw->stream)
+ percent = (ftell(sw->stream) * 100) / st.st_size;
+ else
+ percent = (lseek(sw->fd, 0, SEEK_CUR) * 100) / st.st_size;
return percent;
}
@@ -2281,11 +2348,19 @@ int abis_nm_bs11_get_cclk(struct gsm_bts *bts)
}
//static const u_int8_t bs11_logon_c7[] = { 0x07, 0xd9, 0x01, 0x11, 0x0d, 0x10, 0x20 };
-static const u_int8_t bs11_logon_c8[] = { 0x02 };
-static const u_int8_t bs11_logon_c9[] = "FACTORY";
int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on)
{
+ return abis_nm_bs11_logon(bts, 0x02, "FACTORY", on);
+}
+
+int abis_nm_bs11_infield_logon(struct gsm_bts *bts, int on)
+{
+ return abis_nm_bs11_logon(bts, 0x03, "FIELD ", on);
+}
+
+int abis_nm_bs11_logon(struct gsm_bts *bts, u_int8_t level, const char *name, int on)
+{
struct abis_om_hdr *oh;
struct msgb *msg = nm_msgb_alloc();
struct bs11_date_time bdt;
@@ -2295,15 +2370,15 @@ int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on)
oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
if (on) {
u_int8_t len = 3*2 + sizeof(bdt)
- + sizeof(bs11_logon_c8) + sizeof(bs11_logon_c9);
+ + 1 + strlen(name);
fill_om_fom_hdr(oh, len, NM_MT_BS11_LMT_LOGON,
NM_OC_BS11_BTSE, 0xff, 0xff, 0xff);
msgb_tlv_put(msg, NM_ATT_BS11_LMT_LOGIN_TIME,
sizeof(bdt), (u_int8_t *) &bdt);
msgb_tlv_put(msg, NM_ATT_BS11_LMT_USER_ACC_LEV,
- sizeof(bs11_logon_c8), bs11_logon_c8);
+ 1, &level);
msgb_tlv_put(msg, NM_ATT_BS11_LMT_USER_NAME,
- sizeof(bs11_logon_c9), bs11_logon_c9);
+ strlen(name), (u_int8_t *)name);
} else {
fill_om_fom_hdr(oh, 0, NM_MT_BS11_LMT_LOGOFF,
NM_OC_BS11_BTSE, 0xff, 0xff, 0xff);
@@ -2351,6 +2426,27 @@ int abis_nm_bs11_set_pll_locked(struct gsm_bts *bts, int locked)
return abis_nm_sendmsg(bts, msg);
}
+/* Set the calibration value of the PLL (work value/set value)
+ * It depends on the login which one is changed */
+int abis_nm_bs11_set_pll(struct gsm_bts *bts, int value)
+{
+ struct abis_om_hdr *oh;
+ struct msgb *msg;
+ u_int8_t tlv_value[2];
+
+ msg = nm_msgb_alloc();
+ oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
+ fill_om_fom_hdr(oh, 3, NM_MT_BS11_SET_ATTR, NM_OC_BS11,
+ BS11_OBJ_TRX1, 0x00, 0x00);
+
+ tlv_value[0] = value>>8;
+ tlv_value[1] = value&0xff;
+
+ msgb_tlv_put(msg, NM_ATT_BS11_PLL, 2, tlv_value);
+
+ return abis_nm_sendmsg(bts, msg);
+}
+
int abis_nm_bs11_get_state(struct gsm_bts *bts)
{
return __simple_cmd(bts, NM_MT_BS11_GET_STATE);
@@ -2597,14 +2693,15 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
struct abis_om_fom_hdr *foh;
u_int8_t idstrlen = oh->data[0];
struct tlv_parsed tp;
+ struct ipacc_ack_signal_data signal;
if (strncmp((char *)&oh->data[1], ipaccess_magic, idstrlen)) {
- DEBUGP(DNM, "id string is not com.ipaccess !?!\n");
+ LOGP(DNM, LOGL_ERROR, "id string is not com.ipaccess !?!\n");
return -EINVAL;
}
foh = (struct abis_om_fom_hdr *) (oh->data + 1 + idstrlen);
- abis_nm_tlv_parse(&tp, foh->data, oh->length-sizeof(*foh));
+ abis_nm_tlv_parse(&tp, msg->trx->bts, foh->data, oh->length-sizeof(*foh));
debugp_foh(foh);
@@ -2627,7 +2724,7 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
DEBUGPC(DNM, "\n");
break;
case NM_MT_IPACC_RSL_CONNECT_NACK:
- DEBUGPC(DNM, "RSL CONNECT NACK ");
+ LOGP(DNM, LOGL_ERROR, "RSL CONNECT NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
DEBUGPC(DNM, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
@@ -2639,35 +2736,35 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
/* FIXME: decode and show the actual attributes */
break;
case NM_MT_IPACC_SET_NVATTR_NACK:
- DEBUGPC(DNM, "SET NVATTR NACK ");
+ LOGP(DNM, LOGL_ERROR, "SET NVATTR NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
- DEBUGPC(DNM, " CAUSE=%s\n",
+ LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
else
- DEBUGPC(DNM, "\n");
+ LOGPC(DNM, LOGL_ERROR, "\n");
break;
case NM_MT_IPACC_GET_NVATTR_ACK:
DEBUGPC(DNM, "GET NVATTR ACK\n");
/* FIXME: decode and show the actual attributes */
break;
case NM_MT_IPACC_GET_NVATTR_NACK:
- DEBUGPC(DNM, "GET NVATTR NACK ");
+ LOGPC(DNM, LOGL_ERROR, "GET NVATTR NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
- DEBUGPC(DNM, " CAUSE=%s\n",
+ LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
else
- DEBUGPC(DNM, "\n");
+ LOGPC(DNM, LOGL_ERROR, "\n");
break;
case NM_MT_IPACC_SET_ATTR_ACK:
DEBUGPC(DNM, "SET ATTR ACK\n");
break;
case NM_MT_IPACC_SET_ATTR_NACK:
- DEBUGPC(DNM, "SET ATTR NACK ");
+ LOGPC(DNM, LOGL_ERROR, "SET ATTR NACK ");
if (TLVP_PRESENT(&tp, NM_ATT_NACK_CAUSES))
- DEBUGPC(DNM, " CAUSE=%s\n",
+ LOGPC(DNM, LOGL_ERROR, " CAUSE=%s\n",
nack_cause_name(*TLVP_VAL(&tp, NM_ATT_NACK_CAUSES)));
else
- DEBUGPC(DNM, "\n");
+ LOGPC(DNM, LOGL_ERROR, "\n");
break;
default:
DEBUGPC(DNM, "unknown\n");
@@ -2679,7 +2776,14 @@ static int abis_nm_rx_ipacc(struct msgb *msg)
case NM_MT_IPACC_RSL_CONNECT_NACK:
case NM_MT_IPACC_SET_NVATTR_NACK:
case NM_MT_IPACC_GET_NVATTR_NACK:
- dispatch_signal(SS_NM, S_NM_IPACC_NACK, &foh->msg_type);
+ signal.bts = msg->trx->bts;
+ signal.msg_type = foh->msg_type;
+ dispatch_signal(SS_NM, S_NM_IPACC_NACK, &signal);
+ break;
+ case NM_MT_IPACC_SET_NVATTR_ACK:
+ signal.bts = msg->trx->bts;
+ signal.msg_type = foh->msg_type;
+ dispatch_signal(SS_NM, S_NM_IPACC_ACK, &signal);
break;
default:
break;
@@ -2726,11 +2830,11 @@ int abis_nm_ipaccess_msg(struct gsm_bts *bts, u_int8_t msg_type,
}
/* set some attributes in NVRAM */
-int abis_nm_ipaccess_set_nvattr(struct gsm_bts *bts, u_int8_t *attr,
+int abis_nm_ipaccess_set_nvattr(struct gsm_bts_trx *trx, u_int8_t *attr,
int attr_len)
{
- return abis_nm_ipaccess_msg(bts, NM_MT_IPACC_SET_NVATTR,
- NM_OC_BASEB_TRANSC, 0, 0, 0xff, attr,
+ return abis_nm_ipaccess_msg(trx->bts, NM_MT_IPACC_SET_NVATTR,
+ NM_OC_BASEB_TRANSC, 0, trx->nr, 0xff, attr,
attr_len);
}
@@ -2781,7 +2885,7 @@ void gsm_trx_lock_rf(struct gsm_bts_trx *trx, int locked)
{
int new_state = locked ? NM_STATE_LOCKED : NM_STATE_UNLOCKED;
- trx->rf_locked = locked;
+ trx->nm_state.administrative = new_state;
if (!trx->bts || !trx->bts->oml_link)
return;