add support for more nanoBTS 12.21 tests

* perform a channel usage test
$ ./ipaccess-config -l 64 192.168.100.100
paccess-config.c:142 ==> ARFCN    3, RxLev 16
[...]
<0020> ipaccess-config.c:142 ==> ARFCN    4, RxLev 33
<0020> ipaccess-config.c:142 ==> ARFCN    8, RxLev  6
<0020> ipaccess-config.c:142 ==> ARFCN    5, RxLev 16
<0020> ipaccess-config.c:142 ==> ARFCN   11, RxLev  5
<0020> ipaccess-config.c:142 ==> ARFCN   12, RxLev  8
<0020> ipaccess-config.c:142 ==> ARFCN   10, RxLev  6
[...]

* perform a BCCH usage test
$ ./ipaccess-config -l 65 192.168.100.100
[...]
<0020> ipaccess-config.c:107 TEST REPORT: test_no=0x41 test_res=SUCCESS
<0020> ipaccess-config.c:142 ==> ARFCN    4, RxLev 32
<0020> ipaccess-config.c:142 ==> ARFCN    8, RxLev  6
<0020> ipaccess-config.c:142 ==> ARFCN   12, RxLev  6
<0020> ipaccess-config.c:142 ==> ARFCN   20, RxLev  9
<0020> ipaccess-config.c:142 ==> ARFCN   31, RxLev  6
<0020> ipaccess-config.c:142 ==> ARFCN   37, RxLev 23
<0020> ipaccess-config.c:142 ==> ARFCN   49, RxLev  7
<0020> ipaccess-config.c:142 ==> ARFCN   53, RxLev 14
<0020> ipaccess-config.c:142 ==> ARFCN   57, RxLev 19
<0020> ipaccess-config.c:142 ==> ARFCN   60, RxLev 63
<0020> ipaccess-config.c:142 ==> ARFCN   71, RxLev 15
<0020> ipaccess-config.c:142 ==> ARFCN   90, RxLev  4

* perform a frequency sync test
$ ./ipaccess-config -l 66 192.168.100.100
[...]
<0020> ipaccess-config.c:107 TEST REPORT: test_no=0x42 test_res=SUCCESS
<0020> ipaccess-config.c:130 ==> ARFCN    4, Frequency Error     -2
<0020> ipaccess-config.c:130 ==> ARFCN    8, Frequency Error    -40
<0020> ipaccess-config.c:130 ==> ARFCN   20, Frequency Error    -21
<0020> ipaccess-config.c:130 ==> ARFCN   31, Frequency Error      1
<0020> ipaccess-config.c:130 ==> ARFCN   37, Frequency Error     -4
<0020> ipaccess-config.c:130 ==> ARFCN   45, Frequency Error     -4
<0020> ipaccess-config.c:130 ==> ARFCN   53, Frequency Error     22
<0020> ipaccess-config.c:130 ==> ARFCN   57, Frequency Error      3
<0020> ipaccess-config.c:130 ==> ARFCN   60, Frequency Error      0
<0020> ipaccess-config.c:130 ==> ARFCN   69, Frequency Error      2
<0020> ipaccess-config.c:130 ==> ARFCN   73, Frequency Error     30
<0020> ipaccess-config.c:130 ==> ARFCN   89, Frequency Error     44
<0020> ipaccess-config.c:130 ==> ARFCN   90, Frequency Error      8
<0020> ipaccess-config.c:130 ==> ARFCN  123, Frequency Error     27
diff --git a/openbsc/src/ipaccess-config.c b/openbsc/src/ipaccess-config.c
index a7fb9c4..7358d64 100644
--- a/openbsc/src/ipaccess-config.c
+++ b/openbsc/src/ipaccess-config.c
@@ -42,7 +42,7 @@
 
 static struct gsm_network *gsmnet;
 
-static int net_listen;
+static int net_listen_testnr;
 static int restart;
 static char *prim_oml_ip;
 static char *unit_id;
@@ -74,6 +74,28 @@
 	u_int8_t arfcn;
 } __attribute__((packed));
 
+struct ipacc_cusage_elem {
+	u_int16_t arfcn:10,
+		  rxlev:6;
+} __attribute__ ((packed));
+
+static const char *ipacc_testres_names[] = {
+	[NM_IPACC_TESTRES_SUCCESS]	= "SUCCESS",
+	[NM_IPACC_TESTRES_TIMEOUT]	= "TIMEOUT",
+	[NM_IPACC_TESTRES_NO_CHANS]	= "NO CHANNELS",
+	[NM_IPACC_TESTRES_PARTIAL]	= "PARTIAL",
+	[NM_IPACC_TESTRES_STOPPED]	= "STOPPED",
+};
+
+const char *ipacc_testres_name(u_int8_t res)
+{
+	if (res < ARRAY_SIZE(ipacc_testres_names) &&
+	    ipacc_testres_names[res])
+		return ipacc_testres_names[res];
+
+	return "unknown";
+}
+
 static int test_rep(void *_msg)
 {
 	struct msgb *msg = _msg;
@@ -93,7 +115,7 @@
 	/* data[3..4]: test_rep_len */
 	test_rep_len = ntohs(*(u_int16_t *) &foh->data[3]);
 	/* data[5]: ip.access test result */
-	DEBUGPC(DNM, "test_res=%u\n", foh->data[5]);
+	DEBUGPC(DNM, "test_res=%s\n", ipacc_testres_name(foh->data[5]));
 
 	/* data[6]: ip.access nested IE. 3 == freq_err_list */
 	switch (foh->data[6]) {
@@ -108,6 +130,18 @@
 			ife->arfcn, ntohs(ife->freq_err));
 		}
 		break;
+	case 4:
+		/* data[7..8]: length of ferr_list */
+		ferr_list_len = ntohs(*(u_int16_t *) &foh->data[7]);
+
+		/* data[9...]: channel usage list elements */
+		for (i = 0; i < ferr_list_len; i+= 2) {
+			u_int16_t *cu_ptr = (u_int16_t *)(foh->data + 9 + i);
+			u_int16_t cu = ntohs(*cu_ptr);
+			DEBUGP(DNM, "==> ARFCN %4u, RxLev %2u\n",
+				cu & 0x3ff, cu >> 10);
+		}
+		break;
 	default:
 		break;
 	}
@@ -192,9 +226,6 @@
 		printf("restarting BTS\n");
 		abis_nm_ipaccess_restart(bts);
 	}
-
-	if (net_listen) {
-	}
 }
 
 void input_event(int event, enum e1inp_sign_type type, struct gsm_bts_trx *trx)
@@ -227,11 +258,11 @@
 	if (evt == EVT_STATECHG_OPER &&
 	    obj_class == NM_OC_RADIO_CARRIER &&
 	    new_state->availability == 3 &&
-	    net_listen) {
+	    net_listen_testnr) {
 		struct gsm_bts_trx *trx = obj;
 		u_int8_t phys_config[] = { 0x02, 0x0a, 0x00, 0x01, 0x02 };
 		abis_nm_perform_test(trx->bts, 2, 0, 0, 0xff,
-				     NM_IPACC_TESTNO_FREQ_SYNC, 1,
+				     net_listen_testnr, 1,
 				     phys_config, sizeof(phys_config));
 	}
 	return 0;
@@ -248,7 +279,7 @@
 	printf("  -o --oml-ip ip\n");
 	printf("  -r --restart\n");
 	printf("  -n flags/mask\tSet NVRAM attributes.\n");
-	printf("  -l --listen\tPerform Frequency Error test\n");
+	printf("  -l --listen testnr \tPerform speciified test number\n");
 	printf("  -h --help this text\n");
 }
 
@@ -270,10 +301,10 @@
 			{ "oml-ip", 1, 0, 'o' },
 			{ "restart", 0, 0, 'r' },
 			{ "help", 0, 0, 'h' },
-			{ "listen", 0, 0, 'l' },
+			{ "listen", 1, 0, 'l' },
 		};
 
-		c = getopt_long(argc, argv, "u:o:rn:lh", long_options,
+		c = getopt_long(argc, argv, "u:o:rn:l:h", long_options,
 				&option_index);
 
 		if (c == -1)
@@ -299,7 +330,7 @@
 			nv_mask = ul & 0xffff;
 			break;
 		case 'l':
-			net_listen = 1;
+			net_listen_testnr = atoi(optarg);
 			break;
 		case 'h':
 			print_usage();