From 5e4d1b366366e60ca63c9a72a1e015ae0d4ddbd5 Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Sun, 1 Feb 2009 13:36:56 +0000 Subject: [PATCH] * rename NM_MT_BS11_LOGOFF to NM_MT_BS11_LMT_LOGOFF * add more BS11 specific attributes * define all valid BS11 PA power classes * add callback function to software load * introduce SWL load function for BS-11 style SWL file lists * separate activation of software from loading of software * add function to obtain BS-11 serial number --- include/openbsc/abis_nm.h | 29 +++- src/abis_nm.c | 275 +++++++++++++++++++++++++++++++++++++- src/bs11_config.c | 96 +++++++++---- 3 files changed, 364 insertions(+), 36 deletions(-) diff --git a/include/openbsc/abis_nm.h b/include/openbsc/abis_nm.h index 1e59a4446..db02ae604 100644 --- a/include/openbsc/abis_nm.h +++ b/include/openbsc/abis_nm.h @@ -196,8 +196,8 @@ enum abis_nm_msgtype { NM_MT_BS11_RESTART_ACK, NM_MT_BS11_DISCONNECT = 0xe9, NM_MT_BS11_DISCONNECT_ACK, - NM_MT_BS11_LOGOFF = 0xec, - NM_MT_BS11_LOGOFF_ACK, + NM_MT_BS11_LMT_LOGOFF = 0xec, + NM_MT_BS11_LMT_LOGOFF_ACK, NM_MT_BS11_RECONNECT = 0xf1, NM_MT_BS11_RECONNECT_ACK, }; @@ -296,6 +296,11 @@ enum abis_nm_attr { NM_ATT_MEAS_RES, NM_ATT_MEAS_TYPE, + NM_ATT_BS11_ESN_FW_CODE_NO = 0x4c, + NM_ATT_BS11_ESN_HW_CODE_NO = 0x4f, + + NM_ATT_BS11_ESN_PCB_SERIAL = 0x55, + NM_ATT_BS11_ALL_TEST_CATG = 0x60, NM_ATT_BS11_BTSLS_HOPPING, NM_ATT_BS11_CELL_ALLOC_NR, @@ -330,7 +335,7 @@ enum abis_nm_attr { NM_ATT_BS11_L1_REM_ALM_TYPE = 0xb0, NM_ATT_BS11_SW_LOAD_INTENDED = 0xbb, NM_ATT_BS11_SW_LOAD_SAFETY = 0xbc, - NM_ATT_BS11_SW_LOAD_SSTORED = 0xbd, + NM_ATT_BS11_SW_LOAD_STORED = 0xbd, NM_ATT_BS11_VENDOR_NAME = 0xc1, NM_ATT_BS11_LMT_LOGON_SESSION = 0xc6, @@ -388,17 +393,24 @@ enum abis_bs11_objtype { }; enum abis_bs11_trx_power { - BS11_TRX_POWER_30mW = 0x09, + BS11_TRX_POWER_GSM_2W = 0x06, + BS11_TRX_POWER_GSM_250mW= 0x07, + BS11_TRX_POWER_GSM_80mW = 0x08, + BS11_TRX_POWER_GSM_30mW = 0x09, + BS11_TRX_POWER_DCS_3W = 0x0a, + BS11_TRX_POWER_DCS_1W6 = 0x0b, + BS11_TRX_POWER_DCS_500mW= 0x0c, + BS11_TRX_POWER_DCS_160mW= 0x0d, }; enum abis_bs11_state { BS11_STATE_SOFTWARE_RQD = 0x01, - BS11_STATE_NORMAL = 0x03, BS11_STATE_LOAD_SMU_SAFETY = 0x21, BS11_STATE_WARM_UP = 0x51, BS11_STATE_WAIT_MIN_CFG = 0x62, BS11_STATE_MAINTENANCE = 0x72, BS11_STATE_WAIT_MIN_CFG_2 = 0xA2, + BS11_STATE_NORMAL = 0x03, }; /* PUBLIC */ @@ -430,7 +442,10 @@ int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb); 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); +int abis_nm_software_load(struct gsm_bts *bts, const char *fname, + u_int8_t win_size, gsm_cbfn *cbfn, void *cb_data); +int abis_nm_software_activate(struct gsm_bts *bts, const char *fname, + gsm_cbfn *cbfn, void *cb_data); /* Siemens / BS-11 specific */ int abis_nm_bs11_reset_resource(struct gsm_bts *bts); @@ -446,5 +461,7 @@ int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, u_int8_t level); 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); #endif /* _NM_H */ diff --git a/src/abis_nm.c b/src/abis_nm.c index 2cff36ffc..259132029 100644 --- a/src/abis_nm.c +++ b/src/abis_nm.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -291,6 +293,9 @@ enum sw_state { struct abis_nm_sw { struct gsm_bts *bts; + gsm_cbfn *cbfn; + void *cb_data; + /* this will become part of the SW LOAD INITIATE */ u_int8_t obj_class; u_int8_t obj_instance[3]; @@ -416,6 +421,7 @@ static int sw_load_end(struct abis_nm_sw *sw) return abis_nm_sendmsg(sw->bts, msg); } + /* Activate the specified software into the BTS */ static int sw_activate(struct abis_nm_sw *sw) { @@ -518,11 +524,19 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb) switch (foh->msg_type) { case NM_MT_LOAD_INIT_ACK: /* fill window with segments */ + 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; 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; break; } @@ -547,26 +561,42 @@ static int abis_nm_rcvmsg_sw(struct msgb *mb) switch (foh->msg_type) { case NM_MT_LOAD_END_ACK: sw_close_file(sw); - /* send activate request */ - sw->state = SW_STATE_WAIT_ACTACK; - rc = sw_activate(sw); + DEBUGP(DNM, "Software Load End (BTS %u)\n", + sw->bts->nr); + sw->state = SW_STATE_NONE; + if (sw->cbfn) + sw->cbfn(GSM_HOOK_NM_SWLOAD, + NM_MT_LOAD_END_ACK, mb, + sw->cb_data, NULL); break; case NM_MT_LOAD_END_NACK: DEBUGP(DNM, "Software Load End NACK\n"); sw->state = SW_STATE_ERROR; + if (sw->cbfn) + sw->cbfn(GSM_HOOK_NM_SWLOAD, + NM_MT_LOAD_END_NACK, mb, + sw->cb_data, NULL); break; } case SW_STATE_WAIT_ACTACK: switch (foh->msg_type) { case NM_MT_ACTIVATE_SW_ACK: /* we're done */ + DEBUGP(DNM, "Activate Software DONE!\n"); sw->state = SW_STATE_NONE; rc = 0; - DEBUGP(DMM, "DONE!\n"); + if (sw->cbfn) + sw->cbfn(GSM_HOOK_NM_SWLOAD, + NM_MT_ACTIVATE_SW_ACK, mb, + sw->cb_data, NULL); break; case NM_MT_ACTIVATE_SW_NACK: DEBUGP(DNM, "Activate Software NACK\n"); sw->state = SW_STATE_ERROR; + if (sw->cbfn) + sw->cbfn(GSM_HOOK_NM_SWLOAD, + NM_MT_ACTIVATE_SW_NACK, mb, + sw->cb_data, NULL); break; } case SW_STATE_NONE: @@ -583,11 +613,14 @@ 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) + u_int8_t win_size, gsm_cbfn *cbfn, void *cb_data) { struct abis_nm_sw *sw = &g_sw; int rc; + DEBUGP(DNM, "Software Load (BTS %u, File \"%s\")\n", + bts->nr, fname); + if (sw->state != SW_STATE_NONE) return -EBUSY; @@ -598,6 +631,8 @@ int abis_nm_software_load(struct gsm_bts *bts, const char *fname, sw->obj_instance[2] = 0xff; sw->window_size = win_size; sw->state = SW_STATE_WAIT_INITACK; + sw->cbfn = cbfn; + sw->cb_data = cb_data; rc = sw_open_file(sw, fname); if (rc < 0) { @@ -624,6 +659,39 @@ int abis_nm_software_load_status(struct gsm_bts *bts) return percent; } +/* Activate the specified software into the BTS */ +int abis_nm_software_activate(struct gsm_bts *bts, const char *fname, + gsm_cbfn *cbfn, void *cb_data) +{ + struct abis_nm_sw *sw = &g_sw; + int rc; + + DEBUGP(DNM, "Activating Software (BTS %u, File \"%s\")\n", + bts->nr, fname); + + if (sw->state != SW_STATE_NONE) + 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; + sw->state = SW_STATE_WAIT_ACTACK; + sw->cbfn = cbfn; + sw->cb_data = cb_data; + + /* Open the file in order to fill some sw struct members */ + rc = sw_open_file(sw, fname); + if (rc < 0) { + sw->state = SW_STATE_NONE; + return rc; + } + sw_close_file(sw); + + return sw_activate(sw); +} + static void fill_nm_channel(struct abis_nm_channel *ch, u_int8_t bts_port, u_int8_t ts_nr, u_int8_t subslot_nr) { @@ -891,7 +959,7 @@ int abis_nm_bs11_factory_logon(struct gsm_bts *bts, int on) msgb_tlv_put(msg, NM_ATT_BS11_LMT_USER_NAME, sizeof(bs11_logon_c9), bs11_logon_c9); } else { - fill_om_fom_hdr(oh, 0, NM_MT_BS11_LOGOFF, + fill_om_fom_hdr(oh, 0, NM_MT_BS11_LMT_LOGOFF, NM_OC_BS11_A3, 0xff, 0xff, 0xff); } @@ -919,3 +987,198 @@ int abis_nm_bs11_get_state(struct gsm_bts *bts) { return __simple_cmd(bts, NM_MT_BS11_GET_STATE); } + +/* BS11 SWL */ + +struct abis_nm_bs11_sw { + struct gsm_bts *bts; + char swl_fname[PATH_MAX]; + u_int8_t win_size; + struct llist_head file_list; + gsm_cbfn *user_cb; /* specified by the user */ +}; +static struct abis_nm_bs11_sw _g_bs11_sw, *g_bs11_sw = &_g_bs11_sw; + +struct file_list_entry { + struct llist_head list; + char fname[PATH_MAX]; +}; + +struct file_list_entry *fl_dequeue(struct llist_head *queue) +{ + struct llist_head *lh; + + if (llist_empty(queue)) + return NULL; + + lh = queue->next; + llist_del(lh); + + return llist_entry(lh, struct file_list_entry, list); +} + +static int bs11_read_swl_file(struct abis_nm_bs11_sw *bs11_sw) +{ + char linebuf[255]; + struct llist_head *lh, *lh2; + FILE *swl; + int rc = 0; + + swl = fopen(bs11_sw->swl_fname, "r"); + if (!swl) + return -ENODEV; + + /* zero the stale file list, if any */ + llist_for_each_safe(lh, lh2, &bs11_sw->file_list) { + llist_del(lh); + free(lh); + } + + while (fgets(linebuf, sizeof(linebuf), swl)) { + char file_id[12+1]; + char file_version[80+1]; + struct file_list_entry *fle; + static char dir[PATH_MAX]; + + 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"); + rc = -EINVAL; + goto out; + } + if (rc < 2) + continue; + + fle = malloc(sizeof(*fle)); + if (!fle) { + rc = -ENOMEM; + goto out; + } + memset(fle, 0, sizeof(*fle)); + + /* construct new filename */ + strncpy(dir, bs11_sw->swl_fname, sizeof(dir)); + 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); + } + +out: + fclose(swl); + return rc; +} + +/* bs11 swload specific callback, passed to abis_nm core swload */ +static int bs11_swload_cbfn(unsigned int hook, unsigned int event, + struct msgb *msg, void *data, void *param) +{ + struct abis_nm_bs11_sw *bs11_sw = data; + 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); + if (fle) { + /* start download the next file of our file list */ + rc = abis_nm_software_load(bs11_sw->bts, fle->fname, + bs11_sw->win_size, + &bs11_swload_cbfn, bs11_sw); + free(fle); + } else { + /* activate the SWL */ + rc = abis_nm_software_activate(bs11_sw->bts, + bs11_sw->swl_fname, + bs11_swload_cbfn, + bs11_sw); + } + break; + case NM_MT_LOAD_END_NACK: + case NM_MT_LOAD_INIT_ACK: + case NM_MT_LOAD_INIT_NACK: + case NM_MT_ACTIVATE_SW_NACK: + case NM_MT_ACTIVATE_SW_ACK: + default: + /* fallthrough to the user callback */ + rc = bs11_sw->user_cb(hook, event, msg, NULL, NULL); + break; + } + + return rc; +} + +/* Siemens provides a SWL file that is a mere listing of all the other + * 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) +{ + struct abis_nm_bs11_sw *bs11_sw = g_bs11_sw; + struct file_list_entry *fle; + int rc = 0; + + INIT_LLIST_HEAD(&bs11_sw->file_list); + bs11_sw->bts = bts; + bs11_sw->win_size = win_size; + bs11_sw->user_cb = cbfn; + + strncpy(bs11_sw->swl_fname, fname, sizeof(bs11_sw->swl_fname)); + rc = bs11_read_swl_file(bs11_sw); + if (rc < 0) + return rc; + + /* dequeue next item in file list */ + fle = fl_dequeue(&bs11_sw->file_list); + if (!fle) + return -EINVAL; + + /* start download the next file of our file list */ + rc = abis_nm_software_load(bts, fle->fname, win_size, + bs11_swload_cbfn, bs11_sw); + free(fle); + return rc; +} + +static u_int8_t req_attr_btse[] = { + NM_ATT_ADM_STATE, NM_ATT_BS11_LMT_LOGON_SESSION, + NM_ATT_BS11_LMT_LOGIN_TIME, NM_ATT_BS11_LMT_USER_ACC_LEV, + NM_ATT_BS11_LMT_USER_NAME, + + 0xaf, NM_ATT_BS11_RX_OFFSET, NM_ATT_BS11_VENDOR_NAME, + + NM_ATT_BS11_SW_LOAD_INTENDED, NM_ATT_BS11_SW_LOAD_SAFETY, + + NM_ATT_BS11_SW_LOAD_STORED }; + +static u_int8_t req_attr_btsm[] = { + NM_ATT_ABIS_CHANNEL, NM_ATT_TEI, NM_ATT_BS11_ABIS_EXT_TIME, + NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xce, NM_ATT_FILE_ID, + NM_ATT_FILE_VERSION, NM_ATT_OPER_STATE, 0xe8, NM_ATT_BS11_ALL_TEST_CATG, + NM_ATT_SW_DESCR, NM_ATT_GET_ARI }; + +static u_int8_t req_attr[] = { + NM_ATT_ADM_STATE, NM_ATT_AVAIL_STATUS, 0xa8, NM_ATT_OPER_STATE, + 0xd5, 0xa1, NM_ATT_BS11_ESN_FW_CODE_NO, NM_ATT_BS11_ESN_HW_CODE_NO, + 0x42, NM_ATT_BS11_ESN_PCB_SERIAL }; + +int abis_nm_bs11_get_serno(struct gsm_bts *bts) +{ + struct abis_om_hdr *oh; + struct msgb *msg = nm_msgb_alloc(); + + oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE); + /* SiemensHW CCTRL object */ + fill_om_fom_hdr(oh, 2+sizeof(req_attr), NM_MT_GET_ATTR, NM_OC_BS11, + 0x03, 0x00, 0x00); + msgb_tlv_put(msg, NM_ATT_LIST_REQ_ATTR, sizeof(req_attr), req_attr); + + return abis_nm_sendmsg(bts, msg); +} diff --git a/src/bs11_config.c b/src/bs11_config.c index 457e90f08..6166c8414 100644 --- a/src/bs11_config.c +++ b/src/bs11_config.c @@ -52,16 +52,16 @@ enum bs11cfg_state { static enum bs11cfg_state bs11cfg_state = STATE_NONE; static const u_int8_t obj_li_attr[] = { - 0xa0, 0x09, 0x00, - 0xab, 0x00, - 0xac, 0x00, + NM_ATT_BS11_BIT_ERR_THESH, 0x09, 0x00, + NM_ATT_BS11_L1_PROT_TYPE, 0x00, + NM_ATT_BS11_LINE_CFG, 0x00, }; static const u_int8_t obj_bbsig0_attr[] = { - 0x3d, 0x02, 0x00, 0x00, - 0x3f, 0x01, 0x00, + NM_ATT_BS11_RSSI_OFFS, 0x02, 0x00, 0x00, + NM_ATT_BS11_DIVERSITY, 0x01, 0x00, }; static const u_int8_t obj_pa0_attr[] = { - NM_ATT_BS11_TXPWR, 0x01, BS11_TRX_POWER_30mW, + NM_ATT_BS11_TXPWR, 0x01, BS11_TRX_POWER_GSM_30mW, }; static const char *trx1_password = "1111111111"; #define TEI_OML 25 @@ -84,7 +84,7 @@ static int handle_serial_msg(struct msgb *rx_msg); /* create all objects for an initial configuration */ static int create_objects(struct gsm_bts *bts, int trx1) { - abis_nm_bs11_factory_logon(bts, 1); + //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); @@ -118,12 +118,12 @@ static int create_objects(struct gsm_bts *bts, int trx1) abis_nm_bs11_conn_oml(bts, 0, 1, 0xff); abis_nm_bs11_set_oml_tei(bts, TEI_OML); - abis_nm_bs11_set_trx_power(&bts->trx[0], BS11_TRX_POWER_30mW); + abis_nm_bs11_set_trx_power(&bts->trx[0], BS11_TRX_POWER_GSM_30mW); if (trx1) - abis_nm_bs11_set_trx_power(&bts->trx[1], BS11_TRX_POWER_30mW); + abis_nm_bs11_set_trx_power(&bts->trx[1], BS11_TRX_POWER_GSM_30mW); - abis_nm_bs11_factory_logon(bts, 0); + //abis_nm_bs11_factory_logon(bts, 0); return 0; } @@ -172,6 +172,7 @@ int _abis_nm_sendmsg(struct msgb *msg) return 0; } +/* select.c callback in case we can write to the RS232 */ static int handle_ser_write(struct bsc_fd *bfd) { struct serial_handle *sh = bfd->data; @@ -203,6 +204,7 @@ static int handle_ser_write(struct bsc_fd *bfd) #define SERIAL_ALLOC_SIZE 300 +/* select.c callback in case we can read from the RS232 */ static int handle_ser_read(struct bsc_fd *bfd) { struct serial_handle *sh = bfd->data; @@ -265,6 +267,7 @@ static int handle_ser_read(struct bsc_fd *bfd) return rc; } +/* select.c callback */ static int serial_fd_cb(struct bsc_fd *bfd, unsigned int what) { int rc = 0; @@ -296,7 +299,44 @@ static int file_is_readable(const char *fname) return 0; } +/* 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) +{ + if (hook != GSM_HOOK_NM_SWLOAD) + return 0; + switch (event) { + case NM_MT_LOAD_INIT_ACK: + fprintf(stdout, "Software Load Initiate ACK\n"); + break; + case NM_MT_LOAD_INIT_NACK: + fprintf(stderr, "ERROR: Software Load Initiate NACK\n"); + exit(5); + break; + case NM_MT_LOAD_END_ACK: + /* FIXME: activate in case we want to */ + if (data) + abis_nm_software_activate(g_bts, fname_safety, + swload_cbfn, g_bts); + break; + case NM_MT_LOAD_END_NACK: + fprintf(stderr, "ERROR: Software Load End NACK\n"); + exit(3); + break; + case NM_MT_ACTIVATE_SW_NACK: + fprintf(stderr, "ERROR: Activate Software NACK\n"); + exit(4); + break; + case NM_MT_ACTIVATE_SW_ACK: + bs11cfg_state = STATE_NONE; + + break; + } + return 0; +} + +/* handle a response from the BTS to a GET STATE command */ static int handle_state_resp(u_int8_t state) { int rc = 0; @@ -315,10 +355,13 @@ static int handle_state_resp(u_int8_t state) case BS11_STATE_SOFTWARE_RQD: printf("Software required...\n"); bs11cfg_state = STATE_SWLOAD; - /* send safety load */ + /* send safety load. Use g_bts as private 'param' + * argument, so our swload_cbfn can distinguish + * a safety load from a regular software */ if (file_is_readable(fname_safety)) rc = abis_nm_software_load(g_bts, fname_safety, - win_size); + win_size, swload_cbfn, + g_bts); else fprintf(stderr, "No valid Safety Load file \"%s\"\n", fname_safety); @@ -334,8 +377,8 @@ static int handle_state_resp(u_int8_t state) bs11cfg_state = STATE_SWLOAD; /* send software (FIXME: over A-bis?) */ if (file_is_readable(fname_software)) - rc = abis_nm_software_load(g_bts, fname_software, - win_size); + 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); @@ -351,6 +394,7 @@ static int handle_state_resp(u_int8_t state) return rc; } +/* handle a fully-received message/packet from the RS232 port */ static int handle_serial_msg(struct msgb *rx_msg) { struct abis_om_hdr *oh; @@ -379,6 +423,9 @@ static int handle_serial_msg(struct msgb *rx_msg) bs11cfg_state = STATE_LOGON_ACK; rc = 0; break; + case NM_MT_BS11_LMT_LOGOFF_ACK: + exit(0); + break; case NM_MT_BS11_GET_STATE_ACK: rc = handle_state_resp(foh->data[2]); break; @@ -409,19 +456,19 @@ static int handle_serial_msg(struct msgb *rx_msg) static void print_banner(void) { printf("bs11_config (C) 2009 by Harald Welte and Dieter Spaar\n"); - printf("THIS SOFTWARE IS FREE SOFTWARE WIH NO WARRANTY\n\n"); + printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n"); } static void print_help(void) { printf("Supported arguments:\n"); - printf("\t--help\t\t\t-h\tPrint this help text\n"); - printf("\t--port /dev/ttyXXX\t-p\tSpecify serial port\n"); - printf("\t--with-trx1\t\t-t\tAssume the BS-11 has 2 TRX\n"); - printf("\t--software file\t\t-s\tSpecify Software file\n"); - printf("\t--safety file\t\t-S\tSpecify Safety Load file\n"); - printf("\t--delay file\t\t-d\tSpecify delay\n"); - printf("\t--win-size num\t\t-w\tSpecify Window Size\n"); + printf("\t-h --help\t\t\tPrint this help text\n"); + printf("\t-p --port \t\tSpecify serial port\n"); + printf("\t-t --with-trx1\t\t\tAssume the BS-11 has 2 TRX\n"); + 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-w --win-size \t\tSpecify Window Size\n"); } static void handle_options(int argc, char **argv) @@ -479,7 +526,7 @@ static void signal_handler(int signal) fprintf(stdout, "signal %u received\n", signal); switch (signal) { - case SIGABRT: + case SIGINT: abis_nm_bs11_factory_logon(g_bts, 0); break; } @@ -538,9 +585,10 @@ int main(int argc, char **argv) exit(1); } - signal(SIGABRT, &signal_handler); + signal(SIGINT, &signal_handler); abis_nm_bs11_factory_logon(g_bts, 1); + //abis_nm_bs11_get_serno(g_bts); while (1) { bsc_select_main();