[ipaccess] Add firmware download option to ipaccess-config

This will mostly work like the downloading in bs11_config
and is based on the bs11_config state machine as well. Once
it is working we can see how to unite both implementations.
diff --git a/openbsc/src/ipaccess/ipaccess-config.c b/openbsc/src/ipaccess/ipaccess-config.c
index 7df4cef..c0fc2c4 100644
--- a/openbsc/src/ipaccess/ipaccess-config.c
+++ b/openbsc/src/ipaccess/ipaccess-config.c
@@ -1,6 +1,8 @@
 /* ip.access nanoBTS configuration tool */
 
 /* (C) 2009 by Harald Welte <laforge@gnumonks.org>
+ * (C) 2009 by Holger Hans Peter Freyther
+ * (C) 2009 by On Waves
  * All Rights Reserved
  *
  * This program is free software; you can redistribute it and/or modify
@@ -48,6 +50,7 @@
 static char *unit_id;
 static u_int16_t nv_flags;
 static u_int16_t nv_mask;
+static char *software = NULL;
 
 /*
 static u_int8_t prim_oml_attr[] = { 0x95, 0x00, 7, 0x88, 192, 168, 100, 11, 0x00, 0x00 };
@@ -164,6 +167,58 @@
 	return 0;
 }
 
+/* callback function passed to the ABIS OML code */
+static int percent;
+static int percent_old;
+static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
+		       void *data, void *param)
+{
+	struct gsm_bts *bts;
+
+	if (hook != GSM_HOOK_NM_SWLOAD)
+		return 0;
+
+	bts = (struct gsm_bts *) data;
+
+	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:
+		fprintf(stderr, "LOAD END ACK...");
+#if 0
+		if (data) {
+			/* we did a safety load and must activate it */
+			abis_nm_software_activate(g_bts, fname_safety,
+						  swload_cbfn, bts);
+			sleep(5);
+		}
+#endif
+		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:
+		break;
+	case NM_MT_LOAD_SEG_ACK:
+		percent = abis_nm_software_load_status(bts);
+		if (percent > percent_old)
+			printf("Software Download Progress: %d%%\n", percent);
+		percent_old = percent;
+		break;
+	}
+	return 0;
+}
+
 static void bootstrap_om(struct gsm_bts *bts)
 {
 	int len;
@@ -226,6 +281,16 @@
 		printf("restarting BTS\n");
 		abis_nm_ipaccess_restart(bts);
 	}
+
+	if (software) {
+		int rc;
+		printf("Attempting software upload with '%s'\n", software);
+		rc = abis_nm_software_load(bts, software, 19, 0, swload_cbfn, bts);
+		if (rc < 0) {
+			fprintf(stderr, "Failed to start software load\n");
+			exit(-3);
+		}
+	}
 }
 
 void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
@@ -310,9 +375,10 @@
 			{ "help", 0, 0, 'h' },
 			{ "listen", 1, 0, 'l' },
 			{ "stream-id", 1, 0, 's' },
+			{ "software", 1, 0, 'd' },
 		};
 
-		c = getopt_long(argc, argv, "u:o:rn:l:hs:", long_options,
+		c = getopt_long(argc, argv, "u:o:rn:l:hs:d:", long_options,
 				&option_index);
 
 		if (c == -1)
@@ -343,6 +409,9 @@
 		case 's':
 			stream_id = atoi(optarg);
 			break;
+		case 'd':
+			software = strdup(optarg);
+			break;
 		case 'h':
 			print_usage();
 			print_help();