diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h index b8523b254..c9d12b001 100644 --- a/include/openbsc/abis_nm.h +++ b/include/openbsc/abis_nm.h @@ -461,7 +461,9 @@ int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *msg); int abis_nm_event_reports(struct gsm_bts *bts, int on); int abis_nm_reset_resource(struct gsm_bts *bts); int abis_nm_software_load(struct gsm_bts *bts, const char *fname, - u_int8_t win_size, gsm_cbfn *cbfn, void *cb_data); + u_int8_t win_size, int forced, + gsm_cbfn *cbfn, void *cb_data); +int abis_nm_software_load_status(struct gsm_bts *bts); int abis_nm_software_activate(struct gsm_bts *bts, const char *fname, gsm_cbfn *cbfn, void *cb_data); @@ -480,7 +482,8 @@ int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on); int abis_nm_bs11_set_trx1_pw(struct gsm_bts *bts, const char *password); int abis_nm_bs11_get_state(struct gsm_bts *bts); int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, - u_int8_t win_size, gsm_cbfn *cbfn); + u_int8_t win_size, int forced, gsm_cbfn *cbfn); int abis_nm_bs11_set_ext_time(struct gsm_bts *bts); +int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect); #endif /* _NM_H */ diff --git a/src/abis_nm.c b/src/abis_nm.c index c9bea25d9..8ebd96d50 100644 --- a/src/abis_nm.c +++ b/src/abis_nm.c @@ -296,6 +296,7 @@ struct abis_nm_sw { struct gsm_bts *bts; gsm_cbfn *cbfn; void *cb_data; + int forced; /* this will become part of the SW LOAD INITIATE */ u_int8_t obj_class; @@ -518,7 +519,7 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb) struct abis_nm_sw *sw = &g_sw; enum sw_state old_state = sw->state; - DEBUGP(DNM, "state %u, NM MT 0x%02x\n", sw->state, foh->msg_type); + //DEBUGP(DNM, "state %u, NM MT 0x%02x\n", sw->state, foh->msg_type); switch (sw->state) { case SW_STATE_WAIT_INITACK: @@ -533,18 +534,33 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb) sw->state = SW_STATE_WAIT_SEGACK; break; case NM_MT_LOAD_INIT_NACK: - DEBUGP(DNM, "Software Load Init NACK\n"); - if (sw->cbfn) - sw->cbfn(GSM_HOOK_NM_SWLOAD, - NM_MT_LOAD_INIT_NACK, mb, - sw->cb_data, NULL); - sw->state = SW_STATE_ERROR; + if (sw->forced) { + DEBUGP(DNM, "FORCED: Ignoring Software Load " + "Init NACK\n"); + if (sw->cbfn) + sw->cbfn(GSM_HOOK_NM_SWLOAD, + NM_MT_LOAD_INIT_ACK, mb, + sw->cb_data, NULL); + rc = sw_fill_window(sw); + sw->state = SW_STATE_WAIT_SEGACK; + } else { + DEBUGP(DNM, "Software Load Init NACK\n"); + if (sw->cbfn) + sw->cbfn(GSM_HOOK_NM_SWLOAD, + NM_MT_LOAD_INIT_NACK, mb, + sw->cb_data, NULL); + sw->state = SW_STATE_ERROR; + } break; } break; case SW_STATE_WAIT_SEGACK: switch (foh->msg_type) { case NM_MT_LOAD_SEG_ACK: + if (sw->cbfn) + sw->cbfn(GSM_HOOK_NM_SWLOAD, + NM_MT_LOAD_SEG_ACK, mb, + sw->cb_data, NULL); sw->seg_in_window = 0; if (!sw->last_seg) { /* fill window with more segments */ @@ -614,7 +630,8 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb) /* Load the specified software into the BTS */ int abis_nm_software_load(struct gsm_bts *bts, const char *fname, - u_int8_t win_size, gsm_cbfn *cbfn, void *cb_data) + u_int8_t win_size, int forced, + gsm_cbfn *cbfn, void *cb_data) { struct abis_nm_sw *sw = &g_sw; int rc; @@ -634,6 +651,7 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname, sw->state = SW_STATE_WAIT_INITACK; sw->cbfn = cbfn; sw->cb_data = cb_data; + sw->forced = forced; rc = sw_open_file(sw, fname); if (rc < 0) { @@ -835,8 +853,17 @@ int abis_nm_event_reports(struct gsm_bts *bts, int on) return __simple_cmd(bts, NM_MT_REST_EVENT_REP); } + /* Siemens (or BS-11) specific commands */ +int abis_nm_bs11_bsc_disconnect(struct gsm_bts *bts, int reconnect) +{ + if (reconnect == 0) + return __simple_cmd(bts, NM_MT_BS11_DISCONNECT); + else + return __simple_cmd(bts, NM_MT_BS11_RECONNECT); +} + struct bs11_date_time { u_int16_t year; u_int8_t month; @@ -1022,6 +1049,7 @@ struct abis_nm_bs11_sw { struct gsm_bts *bts; char swl_fname[PATH_MAX]; u_int8_t win_size; + int forced; struct llist_head file_list; gsm_cbfn *user_cb; /* specified by the user */ }; @@ -1070,7 +1098,7 @@ static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw) if (strlen(linebuf) < 4) continue; - printf("linebuf='%s'\n", linebuf); + rc = sscanf(linebuf+4, "%12s:%80s\r\n", file_id, file_version); if (rc < 0) { perror("ERR parsing SWL file"); @@ -1092,7 +1120,6 @@ static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw) strncat(fle->fname, dirname(dir), sizeof(fle->fname) - 1); strcat(fle->fname, "/"); strncat(fle->fname, file_id, sizeof(fle->fname) - 1 -strlen(fle->fname)); - printf("fname='%s'\n", fle->fname); llist_add_tail(&fle->list, &bs11_sw->file_list); } @@ -1110,8 +1137,6 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event, struct file_list_entry *fle; int rc = 0; - printf("bs11_swload_cbfn(%u, %u, %p, %p, %p)\n", hook, event, msg, data, param); - switch (event) { case NM_MT_LOAD_END_ACK: fle = fl_dequeue(&bs11_sw->file_list); @@ -1119,6 +1144,7 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event, /* start download the next file of our file list */ rc = abis_nm_software_load(bs11_sw->bts, fle->fname, bs11_sw->win_size, + bs11_sw->forced, &bs11_swload_cbfn, bs11_sw); free(fle); } else { @@ -1129,6 +1155,7 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event, bs11_sw); } break; + case NM_MT_LOAD_SEG_ACK: case NM_MT_LOAD_END_NACK: case NM_MT_LOAD_INIT_ACK: case NM_MT_LOAD_INIT_NACK: @@ -1147,7 +1174,7 @@ static int bs11_swload_cbfn(unsigned int hook, unsigned int event, * files that are part of a software release. We need to upload first * the list file, and then each file that is listed in the list file */ int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, - u_int8_t win_size, gsm_cbfn *cbfn) + u_int8_t win_size, int forced, gsm_cbfn *cbfn) { struct abis_nm_bs11_sw *bs11_sw = g_bs11_sw; struct file_list_entry *fle; @@ -1157,6 +1184,7 @@ int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, bs11_sw->bts = bts; bs11_sw->win_size = win_size; bs11_sw->user_cb = cbfn; + bs11_sw->forced = forced; strncpy(bs11_sw->swl_fname, fname, sizeof(bs11_sw->swl_fname)); rc = bs11_read_swl_file(bs11_sw); @@ -1169,7 +1197,7 @@ int abis_nm_bs11_load_swl(struct gsm_bts *bts, const char *fname, return -EINVAL; /* start download the next file of our file list */ - rc = abis_nm_software_load(bts, fle->fname, win_size, + rc = abis_nm_software_load(bts, fle->fname, win_size, forced, bs11_swload_cbfn, bs11_sw); free(fle); return rc; diff --git a/src/bs11_config.c b/src/bs11_config.c index e2916ab06..9acf3012b 100644 --- a/src/bs11_config.c +++ b/src/bs11_config.c @@ -92,9 +92,8 @@ static int create_trx1_objects(struct gsm_bts *bts) } /* create all objects for an initial configuration */ -static int create_objects(struct gsm_bts *bts, int trx1) +static int create_objects(struct gsm_bts *bts) { - //abis_nm_bs11_factory_logon(bts, 1); abis_nm_bs11_create_object(bts, BS11_OBJ_LI, 0, sizeof(obj_li_attr), obj_li_attr); abis_nm_bs11_create_object(bts, BS11_OBJ_GPSU, 0, 0, NULL); @@ -113,7 +112,6 @@ static int create_objects(struct gsm_bts *bts, int trx1) abis_nm_bs11_set_oml_tei(bts, TEI_OML); abis_nm_bs11_set_trx_power(&bts->trx[0], BS11_TRX_POWER_GSM_30mW); - //abis_nm_bs11_factory_logon(bts, 0); return 0; } @@ -124,6 +122,8 @@ static char *fname_software = "HS011106.SWL"; static int delay_ms = 0; static int have_trx1 = 0; static int win_size = 8; +static int param_disconnect = 0; +static int param_forced = 0; static struct gsm_bts *g_bts; static int file_is_readable(const char *fname) @@ -141,6 +141,9 @@ static int file_is_readable(const char *fname) return 0; } +static int percent; +static int percent_old; + /* callback function passed to the ABIS OML code */ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg, void *data, void *param) @@ -173,6 +176,12 @@ static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg, case NM_MT_ACTIVATE_SW_ACK: bs11cfg_state = STATE_NONE; + break; + case NM_MT_LOAD_SEG_ACK: + percent = abis_nm_software_load_status(g_bts); + if (percent > percent_old) + printf("Software Download Progress: %d%%\n", percent); + percent_old = percent; break; } return 0; @@ -278,8 +287,8 @@ static int handle_state_resp(enum abis_bs11_phase state) * a safety load from a regular software */ if (file_is_readable(fname_safety)) rc = abis_nm_software_load(g_bts, fname_safety, - win_size, swload_cbfn, - g_bts); + win_size, param_forced, + swload_cbfn, g_bts); else fprintf(stderr, "No valid Safety Load file \"%s\"\n", fname_safety); @@ -287,17 +296,20 @@ static int handle_state_resp(enum abis_bs11_phase state) case BS11_STATE_WAIT_MIN_CFG: case BS11_STATE_WAIT_MIN_CFG_2: bs11cfg_state = STATE_SWLOAD; - rc = create_objects(g_bts, have_trx1); + rc = create_objects(g_bts); break; case BS11_STATE_MAINTENANCE: - bs11cfg_state = STATE_SWLOAD; - /* send software (FIXME: over A-bis?) */ - if (file_is_readable(fname_software)) - rc = abis_nm_bs11_load_swl(g_bts, fname_software, - win_size, swload_cbfn); - else - fprintf(stderr, "No valid Software file \"%s\"\n", - fname_software); + if (bs11cfg_state != STATE_SWLOAD) { + bs11cfg_state = STATE_SWLOAD; + /* send software (FIXME: over A-bis?) */ + if (file_is_readable(fname_software)) + rc = abis_nm_bs11_load_swl(g_bts, fname_software, + win_size, param_forced, + swload_cbfn); + else + fprintf(stderr, "No valid Software file \"%s\"\n", + fname_software); + } break; case BS11_STATE_NORMAL: if (have_trx1) @@ -389,7 +401,9 @@ static void print_help(void) printf("\t-s --software \t\tSpecify Software file\n"); printf("\t-S --safety \t\tSpecify Safety Load file\n"); printf("\t-d --delay \t\tSpecify delay\n"); + printf("\t-D --disconnect\t\t\tDisconnect BTS from BSC\n"); printf("\t-w --win-size \t\tSpecify Window Size\n"); + printf("\t-f --forced\t\t\tForce Software Load\n"); } static void handle_options(int argc, char **argv) @@ -405,10 +419,12 @@ static void handle_options(int argc, char **argv) { "software", 1, 0, 's' }, { "safety", 1, 0, 'S' }, { "delay", 1, 0, 'd' }, + { "disconnect", 0, 0, 'D' }, { "win-size", 1, 0, 'w' }, + { "forced", 0, 0, 'f' }, }; - c = getopt_long(argc, argv, "hp:s:S:td:w:", + c = getopt_long(argc, argv, "hp:s:S:td:Dw:f", long_options, &option_index); if (c == -1) @@ -436,6 +452,12 @@ static void handle_options(int argc, char **argv) case 'w': win_size = atoi(optarg); break; + case 'D': + param_disconnect = 1; + break; + case 'f': + param_forced = 1; + break; default: break; } @@ -474,6 +496,9 @@ int main(int argc, char **argv) abis_nm_bs11_factory_logon(g_bts, 1); //abis_nm_bs11_get_serno(g_bts); + if (param_disconnect) + abis_nm_bs11_bsc_disconnect(g_bts, 0); + while (1) { bsc_select_main(); }