blob: 281e8cee755cd0bbd934162dde04f4bf91ff4f98 [file] [log] [blame]
Dieter Spaar16646022011-07-28 00:01:50 +02001/* Nokia XXXsite family specific code */
2
3/* (C) 2011 by Dieter Spaar <spaar@mirider.augusta.de>
4 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU Affero General Public License as published by
9 * the Free Software Foundation; either version 3 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU Affero General Public License for more details.
16 *
17 * You should have received a copy of the GNU Affero General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22/*
23 TODO: Attention: There are some static variables used for states during
24 configuration. Those variables have to be moved to a BTS specific context,
25 otherwise there will most certainly be problems if more than one Nokia BTS
26 is used.
27*/
28
29#include <time.h>
30
31#include <osmocom/gsm/tlv.h>
32
33#include <openbsc/debug.h>
34#include <openbsc/gsm_data.h>
35#include <openbsc/abis_nm.h>
36#include <openbsc/e1_input.h>
37#include <openbsc/signal.h>
38
39#include <osmocom/core/timer.h>
40
41#include "../libabis/input/lapd.h"
42
43/* TODO: put in a separate file ? */
44
Harald Weltebda367c2011-07-28 00:03:49 +020045#define RESET_INTERVAL 0, 3000000 /* 3 seconds */
Dieter Spaar16646022011-07-28 00:01:50 +020046
47extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg);
48/* was static in system_information.c */
Harald Weltebda367c2011-07-28 00:03:49 +020049extern int generate_cell_chan_list(uint8_t * chan_list, struct gsm_bts *bts);
Dieter Spaar16646022011-07-28 00:01:50 +020050
51static void abis_nm_queue_send_next(struct gsm_bts *bts);
52static void reset_timer_cb(void *_bts);
53static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref);
Harald Weltebda367c2011-07-28 00:03:49 +020054static int dump_elements(uint8_t * data, int len);
Dieter Spaar16646022011-07-28 00:01:50 +020055
56static void bootstrap_om_bts(struct gsm_bts *bts)
57{
Harald Weltebda367c2011-07-28 00:03:49 +020058 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
59
Harald Weltec8755af2011-07-28 00:22:17 +020060 if (bts->nokia.do_reset)
Harald Weltebda367c2011-07-28 00:03:49 +020061 abis_nm_reset(bts, 1);
Dieter Spaar16646022011-07-28 00:01:50 +020062}
63
64static void bootstrap_om_trx(struct gsm_bts_trx *trx)
65{
Harald Weltebda367c2011-07-28 00:03:49 +020066 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
67 trx->bts->nr, trx->nr);
Dieter Spaar16646022011-07-28 00:01:50 +020068}
69
70static int shutdown_om(struct gsm_bts *bts)
71{
Harald Weltebda367c2011-07-28 00:03:49 +020072 /* TODO !? */
73 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +020074}
75
76#define SAPI_OML 62
77#define SAPI_RSL 0
78
Harald Weltecde57942011-07-28 00:13:46 +020079/*
Dieter Spaar16646022011-07-28 00:01:50 +020080
81 Tell LAPD to start start the SAP (send SABM requests) for all signalling
Harald Weltecde57942011-07-28 00:13:46 +020082 timeslots in this line
83
84 Attention: this has to be adapted for mISDN
Dieter Spaar16646022011-07-28 00:01:50 +020085*/
Harald Weltebda367c2011-07-28 00:03:49 +020086
Dieter Spaar16646022011-07-28 00:01:50 +020087static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi)
88{
Harald Weltebda367c2011-07-28 00:03:49 +020089 struct e1inp_sign_link *link;
90 int i;
Dieter Spaar16646022011-07-28 00:01:50 +020091
Harald Weltebda367c2011-07-28 00:03:49 +020092 for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
93 struct e1inp_ts *ts = &line->ts[i];
Dieter Spaar16646022011-07-28 00:01:50 +020094
Harald Weltebda367c2011-07-28 00:03:49 +020095 if (ts->type != E1INP_TS_TYPE_SIGN)
96 continue;
Dieter Spaar16646022011-07-28 00:01:50 +020097
Harald Weltebda367c2011-07-28 00:03:49 +020098 llist_for_each_entry(link, &ts->sign.sign_links, list) {
99 if (sapi != -1 && link->sapi != sapi)
100 continue;
101
102#if 0 /* debugging */
103 printf("sap start/stop (%d): %d tei=%d sapi=%d\n",
104 start, i + 1, link->tei, link->sapi);
Dieter Spaar16646022011-07-28 00:01:50 +0200105#endif
Harald Weltebda367c2011-07-28 00:03:49 +0200106
107 if (start)
108 lapd_sap_start(ts->driver.dahdi.lapd, link->tei,
109 link->sapi);
110 else
111 lapd_sap_stop(ts->driver.dahdi.lapd, link->tei,
112 link->sapi);
113 }
114 }
Dieter Spaar16646022011-07-28 00:01:50 +0200115}
116
117/* Callback function to be called every time we receive a signal from INPUT */
118static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200119 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200120{
Harald Weltebda367c2011-07-28 00:03:49 +0200121 struct gsm_bts *bts;
Dieter Spaar16646022011-07-28 00:01:50 +0200122
Harald Weltebda367c2011-07-28 00:03:49 +0200123 if (subsys != SS_GLOBAL)
124 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200125
Harald Weltebda367c2011-07-28 00:03:49 +0200126 switch (signal) {
127 case S_GLOBAL_BTS_CLOSE_OM:
128 bts = signal_data;
129 if (bts->type == GSM_BTS_TYPE_NOKIA_SITE)
130 shutdown_om(signal_data);
131 break;
132 }
Dieter Spaar16646022011-07-28 00:01:50 +0200133
Harald Weltebda367c2011-07-28 00:03:49 +0200134 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200135}
136
137/* Callback function to be called every time we receive a signal from INPUT */
138static int inp_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200139 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200140{
Harald Weltebda367c2011-07-28 00:03:49 +0200141 struct input_signal_data *isd = signal_data;
Dieter Spaar16646022011-07-28 00:01:50 +0200142
Harald Weltebda367c2011-07-28 00:03:49 +0200143 if (subsys != SS_INPUT)
144 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200145
Harald Weltebda367c2011-07-28 00:03:49 +0200146 switch (signal) {
147 case S_INP_LINE_INIT:
148 start_sabm_in_line(isd->line, 1, SAPI_OML); /* start only OML */
149 break;
150 case S_INP_TEI_DN:
151 break;
152 case S_INP_TEI_UP:
153 switch (isd->link_type) {
154 case E1INP_SIGN_OML:
155 if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
156 break;
Dieter Spaar16646022011-07-28 00:01:50 +0200157
Harald Weltebda367c2011-07-28 00:03:49 +0200158 if (isd->tei == isd->trx->bts->oml_tei)
159 bootstrap_om_bts(isd->trx->bts);
160 else
161 bootstrap_om_trx(isd->trx);
162 break;
163 }
164 break;
165 }
166
167 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200168}
169
170static void nm_statechg_evt(unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200171 struct nm_statechg_signal_data *nsd)
Dieter Spaar16646022011-07-28 00:01:50 +0200172{
Harald Weltebda367c2011-07-28 00:03:49 +0200173 if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
174 return;
Dieter Spaar16646022011-07-28 00:01:50 +0200175}
176
177static int nm_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200178 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200179{
Harald Weltebda367c2011-07-28 00:03:49 +0200180 if (subsys != SS_NM)
181 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200182
Harald Weltebda367c2011-07-28 00:03:49 +0200183 switch (signal) {
184 case S_NM_STATECHG_OPER:
185 case S_NM_STATECHG_ADM:
186 nm_statechg_evt(signal, signal_data);
187 break;
188 default:
189 break;
190 }
Dieter Spaar16646022011-07-28 00:01:50 +0200191
Harald Weltebda367c2011-07-28 00:03:49 +0200192 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200193}
194
195/* TODO: put in a separate file ? */
196
197static char *get_msg_type_name_string(uint8_t msg_type)
198{
Harald Weltebda367c2011-07-28 00:03:49 +0200199 switch (msg_type) {
200 case 0x80:
201 return "NOKIA_BTS_CONF_DATA";
202 case 0x81:
203 return "NOKIA_BTS_ACK";
204 case 0x82:
205 return "NOKIA_BTS_OMU_STARTED";
206 case 0x83:
207 return "NOKIA_BTS_START_DOWNLOAD_REQ";
208 case 0x84:
209 return "NOKIA_BTS_MF_REQ";
210 case 0x85:
211 return "NOKIA_BTS_AF_REQ";
212 case 0x86:
213 return "NOKIA_BTS_RESET_REQ";
214 case 0x87:
215 return "NOKIA_reserved";
216 case 0x88:
217 return "NOKIA_BTS_CONF_REQ";
218 case 0x89:
219 return "NOKIA_BTS_TEST_REQ";
220 case 0x8A:
221 return "NOKIA_BTS_TEST_REPORT";
222 case 0x8B:
223 return "NOKIA_reserved";
224 case 0x8C:
225 return "NOKIA_reserved";
226 case 0x8D:
227 return "NOKIA_reserved";
228 case 0x8E:
229 return "NOKIA_BTS_CONF_COMPL";
230 case 0x8F:
231 return "NOKIA_reserved";
232 case 0x90:
233 return "NOKIA_BTS_STM_TEST_REQ";
234 case 0x91:
235 return "NOKIA_BTS_STM_TEST_REPORT";
236 case 0x92:
237 return "NOKIA_BTS_TRANSMISSION_COMMAND";
238 case 0x93:
239 return "NOKIA_BTS_TRANSMISSION_ANSWER";
240 case 0x94:
241 return "NOKIA_BTS_HW_DB_UPLOAD_REQ";
242 case 0x95:
243 return "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ";
244 case 0x96:
245 return "NOKIA_BTS_HW_DB_SAVE_REQ";
246 case 0x97:
247 return "NOKIA_BTS_FLASH_ERASURE_REQ";
248 case 0x98:
249 return "NOKIA_BTS_HW_DB_DOWNLOAD_REQ";
250 case 0x99:
251 return "NOKIA_BTS_PWR_SUPPLY_CONTROL";
252 case 0x9A:
253 return "NOKIA_BTS_ATTRIBUTE_REQ";
254 case 0x9B:
255 return "NOKIA_BTS_ATTRIBUTE_REPORT";
256 case 0x9C:
257 return "NOKIA_BTS_HW_REQ";
258 case 0x9D:
259 return "NOKIA_BTS_HW_REPORT";
260 case 0x9E:
261 return "NOKIA_BTS_RTE_TEST_REQ";
262 case 0x9F:
263 return "NOKIA_BTS_RTE_TEST_REPORT";
264 case 0xA0:
265 return "NOKIA_BTS_HW_DB_VERIFICATION_REQ";
266 case 0xA1:
267 return "NOKIA_BTS_CLOCK_REQ";
268 case 0xA2:
269 return "NOKIA_AC_CIRCUIT_REQ_NACK";
270 case 0xA3:
271 return "NOKIA_AC_INTERRUPTED";
272 case 0xA4:
273 return "NOKIA_BTS_NEW_TRE_INFO";
274 case 0xA5:
275 return "NOKIA_AC_BSC_CIRCUITS_ALLOCATED";
276 case 0xA6:
277 return "NOKIA_BTS_TRE_POLL_LIST";
278 case 0xA7:
279 return "NOKIA_AC_CIRCUIT_REQ";
280 case 0xA8:
281 return "NOKIA_BTS_BLOCK_CTRL_REQ";
282 case 0xA9:
283 return "NOKIA_BTS_GSM_TIME_REQ";
284 case 0xAA:
285 return "NOKIA_BTS_GSM_TIME";
286 case 0xAB:
287 return "NOKIA_BTS_OUTPUT_CONTROL";
288 case 0xAC:
289 return "NOKIA_BTS_STATE_CHANGED";
290 case 0xAD:
291 return "NOKIA_BTS_SW_SAVE_REQ";
292 case 0xAE:
293 return "NOKIA_BTS_ALARM";
294 case 0xAF:
295 return "NOKIA_BTS_CHA_ADM_STATE";
296 case 0xB0:
297 return "NOKIA_AC_POOL_SIZE_REPORT";
298 case 0xB1:
299 return "NOKIA_AC_POOL_SIZE_INQUIRY";
300 case 0xB2:
301 return "NOKIA_BTS_COMMISS_TEST_COMPLETED";
302 case 0xB3:
303 return "NOKIA_BTS_COMMISS_TEST_REQ";
304 case 0xB4:
305 return "NOKIA_BTS_TRANSP_BTS_TO_BSC";
306 case 0xB5:
307 return "NOKIA_BTS_TRANSP_BSC_TO_BTS";
308 case 0xB6:
309 return "NOKIA_BTS_LCS_COMMAND";
310 case 0xB7:
311 return "NOKIA_BTS_LCS_ANSWER";
312 case 0xB8:
313 return "NOKIA_BTS_LMU_FN_OFFSET_COMMAND";
314 case 0xB9:
315 return "NOKIA_BTS_LMU_FN_OFFSET_ANSWER";
316 default:
317 return "unknown";
318 }
Dieter Spaar16646022011-07-28 00:01:50 +0200319}
320
321static char *get_element_name_string(uint16_t element)
322{
Harald Weltebda367c2011-07-28 00:03:49 +0200323 switch (element) {
324 case 0x01:
325 return "Ny1";
326 case 0x02:
327 return "T3105_F";
328 case 0x03:
329 return "Interference band limits";
330 case 0x04:
331 return "Interference report timer in secs";
332 case 0x05:
333 return "Channel configuration per TS";
334 case 0x06:
335 return "BSIC";
336 case 0x07:
337 return "RACH report timer in secs";
338 case 0x08:
339 return "Hardware database status";
340 case 0x09:
341 return "BTS RX level";
342 case 0x0A:
343 return "ARFN";
344 case 0x0B:
345 return "STM antenna attenuation";
346 case 0x0C:
347 return "Cell allocation bitmap";
348 case 0x0D:
349 return "Radio definition per TS";
350 case 0x0E:
351 return "Frame number";
352 case 0x0F:
353 return "Antenna diversity";
354 case 0x10:
355 return "T3105_D";
356 case 0x11:
357 return "File format";
358 case 0x12:
359 return "Last File";
360 case 0x13:
361 return "BTS type";
362 case 0x14:
363 return "Erasure mode";
364 case 0x15:
365 return "Hopping mode";
366 case 0x16:
367 return "Floating TRX";
368 case 0x17:
369 return "Power supplies";
370 case 0x18:
371 return "Reset type";
372 case 0x19:
373 return "Averaging period";
374 case 0x1A:
375 return "RBER2";
376 case 0x1B:
377 return "LAC";
378 case 0x1C:
379 return "CI";
380 case 0x1D:
381 return "Failure parameters";
382 case 0x1E:
383 return "(RF max power reduction)";
384 case 0x1F:
385 return "Measured RX_SENS";
386 case 0x20:
387 return "Extended cell radius";
388 case 0x21:
389 return "reserved";
390 case 0x22:
391 return "Success-Failure";
392 case 0x23:
393 return "Ack-Nack";
394 case 0x24:
395 return "OMU test results";
396 case 0x25:
397 return "File identity";
398 case 0x26:
399 return "Generation and version code";
400 case 0x27:
401 return "SW description";
402 case 0x28:
403 return "BCCH LEV";
404 case 0x29:
405 return "Test type";
406 case 0x2A:
407 return "Subscriber number";
408 case 0x2B:
409 return "reserved";
410 case 0x2C:
411 return "HSN";
412 case 0x2D:
413 return "reserved";
414 case 0x2E:
415 return "MS RXLEV";
416 case 0x2F:
417 return "MS TXLEV";
418 case 0x30:
419 return "RXQUAL";
420 case 0x31:
421 return "RX SENS";
422 case 0x32:
423 return "Alarm block";
424 case 0x33:
425 return "Neighbouring BCCH levels";
426 case 0x34:
427 return "STM report type";
428 case 0x35:
429 return "MA";
430 case 0x36:
431 return "MAIO";
432 case 0x37:
433 return "H_FLAG";
434 case 0x38:
435 return "TCH_ARFN";
436 case 0x39:
437 return "Clock output";
438 case 0x3A:
439 return "Transmitted power";
440 case 0x3B:
441 return "Clock sync";
442 case 0x3C:
443 return "TMS protocol discriminator";
444 case 0x3D:
445 return "TMS protocol data";
446 case 0x3E:
447 return "FER";
448 case 0x3F:
449 return "SWR result";
450 case 0x40:
451 return "Object identity";
452 case 0x41:
453 return "STM RX Antenna Test";
454 case 0x42:
455 return "reserved";
456 case 0x43:
457 return "reserved";
458 case 0x44:
459 return "Object current state";
460 case 0x45:
461 return "reserved";
462 case 0x46:
463 return "FU channel configuration";
464 case 0x47:
465 return "reserved";
466 case 0x48:
467 return "ARFN of a CU";
468 case 0x49:
469 return "FU radio definition";
470 case 0x4A:
471 return "reserved";
472 case 0x4B:
473 return "Severity";
474 case 0x4C:
475 return "Diversity selection";
476 case 0x4D:
477 return "RX antenna test";
478 case 0x4E:
479 return "RX antenna supervision period";
480 case 0x4F:
481 return "RX antenna state";
482 case 0x50:
483 return "Sector configuration";
484 case 0x51:
485 return "Additional info";
486 case 0x52:
487 return "SWR parameters";
488 case 0x53:
489 return "HW inquiry mode";
490 case 0x54:
491 return "reserved";
492 case 0x55:
493 return "Availability status";
494 case 0x56:
495 return "reserved";
496 case 0x57:
497 return "EAC inputs";
498 case 0x58:
499 return "EAC outputs";
500 case 0x59:
501 return "reserved";
502 case 0x5A:
503 return "Position";
504 case 0x5B:
505 return "HW unit identity";
506 case 0x5C:
507 return "RF test signal attenuation";
508 case 0x5D:
509 return "Operational state";
510 case 0x5E:
511 return "Logical object identity";
512 case 0x5F:
513 return "reserved";
514 case 0x60:
515 return "BS_TXPWR_OM";
516 case 0x61:
517 return "Loop_Duration";
518 case 0x62:
519 return "LNA_Path_Selection";
520 case 0x63:
521 return "Serial number";
522 case 0x64:
523 return "HW version";
524 case 0x65:
525 return "Obj. identity and obj. state";
526 case 0x66:
527 return "reserved";
528 case 0x67:
529 return "EAC input definition";
530 case 0x68:
531 return "EAC id and text";
532 case 0x69:
533 return "HW unit status";
534 case 0x6A:
535 return "SW release version";
536 case 0x6B:
537 return "FW version";
538 case 0x6C:
539 return "Bit_Error_Ratio";
540 case 0x6D:
541 return "RXLEV_with_Attenuation";
542 case 0x6E:
543 return "RXLEV_without_Attenuation";
544 case 0x6F:
545 return "reserved";
546 case 0x70:
547 return "CU_Results";
548 case 0x71:
549 return "reserved";
550 case 0x72:
551 return "LNA_Path_Results";
552 case 0x73:
553 return "RTE Results";
554 case 0x74:
555 return "Real Time";
556 case 0x75:
557 return "RX diversity selection";
558 case 0x76:
559 return "EAC input config";
560 case 0x77:
561 return "Feature support";
562 case 0x78:
563 return "File version";
564 case 0x79:
565 return "Outputs";
566 case 0x7A:
567 return "FU parameters";
568 case 0x7B:
569 return "Diagnostic info";
570 case 0x7C:
571 return "FU BSIC";
572 case 0x7D:
573 return "TRX Configuration";
574 case 0x7E:
575 return "Download status";
576 case 0x7F:
577 return "RX difference limit";
578 case 0x80:
579 return "TRX HW capability";
580 case 0x81:
581 return "Common HW config";
582 case 0x82:
583 return "Autoconfiguration pool size";
584 case 0x83:
585 return "TRE diagnostic info";
586 case 0x84:
587 return "TRE object identity";
588 case 0x85:
589 return "New TRE Info";
590 case 0x86:
591 return "Acknowledgement period";
592 case 0x87:
593 return "Synchronization mode";
594 case 0x88:
595 return "reserved";
596 case 0x89:
597 return "Block Control Data";
598 case 0x8A:
599 return "SW load mode";
600 case 0x8B:
601 return "Recommended recovery action";
602 case 0x8C:
603 return "BSC BCF id";
604 case 0x8D:
605 return "Q1 baud rate";
606 case 0x8E:
607 return "Allocation status";
608 case 0x8F:
609 return "Functional entity number";
610 case 0x90:
611 return "Transmission delay";
612 case 0x91:
613 return "Loop Duration ms";
614 case 0x92:
615 return "Logical channel";
616 case 0x93:
617 return "Q1 address";
618 case 0x94:
619 return "Alarm detail";
620 case 0x95:
621 return "Cabinet type";
622 case 0x96:
623 return "HW unit existence";
624 case 0x97:
625 return "RF power parameters";
626 case 0x98:
627 return "Message scenario";
628 case 0x99:
629 return "HW unit max amount";
630 case 0x9A:
631 return "Master TRX";
632 case 0x9B:
633 return "Transparent data";
634 case 0x9C:
635 return "BSC topology info";
636 case 0x9D:
637 return "Air i/f modulation";
638 case 0x9E:
639 return "LCS Q1 command data";
640 case 0x9F:
641 return "Frame number offset";
642 case 0xA0:
643 return "Abis TSL";
644 case 0xA1:
645 return "Dynamic pool info";
646 case 0xA2:
647 return "LCS LLP data";
648 case 0xA3:
649 return "LCS Q1 answer data";
650 case 0xA4:
651 return "DFCA FU Radio Definition";
652 case 0xA5:
653 return "Antenna hopping";
654 case 0xA6:
655 return "Field record sequence number";
656 case 0xA7:
657 return "Timeslot offslot";
658 case 0xA8:
659 return "EPCR capability";
660 case 0xA9:
661 return "Connectsite optional element";
662 case 0xAA:
663 return "TSC";
664 case 0xAB:
665 return "Special TX Power Setting";
666 case 0xAC:
667 return "Optional sync settings";
668 case 0xFA:
669 return "Abis If parameters";
670 default:
671 return "unknown";
672 }
Dieter Spaar16646022011-07-28 00:01:50 +0200673}
674
Harald Welte3c3003f2011-07-28 00:28:20 +0200675static const struct value_string nokia_bts_types[] = {
676 { 0x0a, "MetroSite GSM 900" },
677 { 0x0b, "MetroSite GSM 1800" },
678 { 0x0c, "MetroSite GSM 1900 (PCS)" },
679 { 0x0d, "MetroSite GSM 900 & 1800" },
680 { 0x0e, "InSite GSM 900" },
681 { 0x0f, "InSite GSM 1800" },
682 { 0x10, "InSite GSM 1900" },
683 { 0x11, "UltraSite GSM 900" },
684 { 0x12, "UltraSite GSM 1800" },
685 { 0x13, "UltraSite GSM/US-TDMA 1900" },
686 { 0x14, "UltraSite GSM 900 & 1800" },
687 { 0x16, "UltraSite GSM/US-TDMA 850" },
688 { 0x18, "MetroSite GSM/US-TDMA 850" },
689 { 0x19, "UltraSite GSM 800/1900" },
690 { 0, NULL }
691};
692
693static const char *get_bts_type_string(uint8_t type)
Dieter Spaar16646022011-07-28 00:01:50 +0200694{
Harald Welte3c3003f2011-07-28 00:28:20 +0200695 return get_value_string(nokia_bts_types, type);
Dieter Spaar16646022011-07-28 00:01:50 +0200696}
697
Harald Welte3c3003f2011-07-28 00:28:20 +0200698static const struct value_string nokia_severity[] = {
699 { 0, "indeterminate" },
700 { 1, "critical" },
701 { 2, "major" },
702 { 3, "minor" },
703 { 4, "warning" },
704 { 0, NULL }
705};
706
707static const char *get_severity_string(uint8_t severity)
Dieter Spaar16646022011-07-28 00:01:50 +0200708{
Harald Welte3c3003f2011-07-28 00:28:20 +0200709 return get_value_string(nokia_severity, severity);
Dieter Spaar16646022011-07-28 00:01:50 +0200710}
711
712/* TODO: put in a separate file ? */
713
714/* some message IDs */
715
716#define NOKIA_MSG_CONF_DATA 128
717#define NOKIA_MSG_ACK 129
718#define NOKIA_MSG_OMU_STARTED 130
719#define NOKIA_MSG_START_DOWNLOAD_REQ 131
720#define NOKIA_MSG_MF_REQ 132
721#define NOKIA_MSG_RESET_REQ 134
722#define NOKIA_MSG_CONF_REQ 136
723#define NOKIA_MSG_CONF_COMPLETE 142
724#define NOKIA_MSG_BLOCK_CTRL_REQ 168
725#define NOKIA_MSG_STATE_CHANGED 172
726#define NOKIA_MSG_ALARM 174
727
728/* some element IDs */
729
730#define NOKIA_EI_BTS_TYPE 0x13
731#define NOKIA_EI_ACK 0x23
732#define NOKIA_EI_ADD_INFO 0x51
733#define NOKIA_EI_SEVERITY 0x4B
734#define NOKIA_EI_ALARM_DETAIL 0x94
735
736#define OM_ALLOC_SIZE 1024
737#define OM_HEADROOM_SIZE 128
738
Harald Weltebda367c2011-07-28 00:03:49 +0200739static uint8_t fu_config_template[] = {
740 0x7F, 0x7A, 0x39,
741 /* ID = 0x7A (FU parameters) ## constructed ## */
742 /* length = 57 */
743 /* [3] */
Dieter Spaar16646022011-07-28 00:01:50 +0200744
Harald Weltebda367c2011-07-28 00:03:49 +0200745 0x5F, 0x40, 0x04,
746 /* ID = 0x40 (Object identity) */
747 /* length = 4 */
748 /* [6] */
749 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200750
Harald Weltebda367c2011-07-28 00:03:49 +0200751 0x41, 0x02,
752 /* ID = 0x01 (Ny1) */
753 /* length = 2 */
754 /* [12] */
755 0x00, 0x05,
Dieter Spaar16646022011-07-28 00:01:50 +0200756
Harald Weltebda367c2011-07-28 00:03:49 +0200757 0x42, 0x02,
758 /* ID = 0x02 (T3105_F) */
759 /* length = 2 */
760 /* [16] */
761 0x00, 0x28,
Dieter Spaar16646022011-07-28 00:01:50 +0200762
Harald Weltebda367c2011-07-28 00:03:49 +0200763 0x50, 0x02,
764 /* ID = 0x10 (T3105_D) */
765 /* length = 2 */
766 /* [20] */
767 0x00, 0x28,
Dieter Spaar16646022011-07-28 00:01:50 +0200768
Harald Weltebda367c2011-07-28 00:03:49 +0200769 0x43, 0x05,
770 /* ID = 0x03 (Interference band limits) */
771 /* length = 5 */
772 /* [24] */
773 0x0F, 0x1B, 0x27, 0x33, 0x3F,
Dieter Spaar16646022011-07-28 00:01:50 +0200774
Harald Weltebda367c2011-07-28 00:03:49 +0200775 0x44, 0x02,
776 /* ID = 0x04 (Interference report timer in secs) */
777 /* length = 2 */
778 /* [31] */
779 0x00, 0x10,
Dieter Spaar16646022011-07-28 00:01:50 +0200780
Harald Weltebda367c2011-07-28 00:03:49 +0200781 0x47, 0x01,
782 /* ID = 0x07 (RACH report timer in secs) */
783 /* length = 1 */
784 /* [35] */
785 0x1E,
Dieter Spaar16646022011-07-28 00:01:50 +0200786
Harald Weltebda367c2011-07-28 00:03:49 +0200787 0x4C, 0x10,
788 /* ID = 0x0C (Cell allocation bitmap) ####### */
789 /* length = 16 */
790 /* [38] */
791 0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
792 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200793
Harald Weltebda367c2011-07-28 00:03:49 +0200794 0x59, 0x01,
795 /* ID = 0x19 (Averaging period) */
796 /* length = 1 */
797 /* [56] */
798 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +0200799
Harald Weltebda367c2011-07-28 00:03:49 +0200800 0x5E, 0x01,
801 /* ID = 0x1E ((RF max power reduction)) */
802 /* length = 1 */
803 /* [59] */
804 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200805
Harald Weltebda367c2011-07-28 00:03:49 +0200806 0x7F, 0x46, 0x11,
807 /* ID = 0x46 (FU channel configuration) ## constructed ## */
808 /* length = 17 */
809 /* [63] */
Dieter Spaar16646022011-07-28 00:01:50 +0200810
Harald Weltebda367c2011-07-28 00:03:49 +0200811 0x5F, 0x40, 0x04,
812 /* ID = 0x40 (Object identity) */
813 /* length = 4 */
814 /* [66] */
815 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200816
Harald Weltebda367c2011-07-28 00:03:49 +0200817 0x45, 0x08,
818 /* ID = 0x05 (Channel configuration per TS) */
819 /* length = 8 */
820 /* [72] */
821 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
Dieter Spaar16646022011-07-28 00:01:50 +0200822
Harald Weltebda367c2011-07-28 00:03:49 +0200823 0x7F, 0x65, 0x0B,
824 /* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */
825 /* length = 11 */
826 /* [83] */
Dieter Spaar16646022011-07-28 00:01:50 +0200827
Harald Weltebda367c2011-07-28 00:03:49 +0200828 0x5F, 0x40, 0x04,
829 /* ID = 0x40 (Object identity) */
830 /* length = 4 */
831 /* [86] */
832 0x00, 0x04, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200833
Harald Weltebda367c2011-07-28 00:03:49 +0200834 0x5F, 0x44, 0x01,
835 /* ID = 0x44 (Object current state) */
836 /* length = 1 */
837 /* [93] */
838 0x03,
Dieter Spaar16646022011-07-28 00:01:50 +0200839
Harald Weltebda367c2011-07-28 00:03:49 +0200840 0x7F, 0x7C, 0x0A,
841 /* ID = 0x7C (FU BSIC) ## constructed ## */
842 /* length = 10 */
843 /* [97] */
Dieter Spaar16646022011-07-28 00:01:50 +0200844
Harald Weltebda367c2011-07-28 00:03:49 +0200845 0x5F, 0x40, 0x04,
846 /* ID = 0x40 (Object identity) */
847 /* length = 4 */
848 /* [100] */
849 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200850
Harald Weltebda367c2011-07-28 00:03:49 +0200851 0x46, 0x01,
852 /* ID = 0x06 (BSIC) */
853 /* length = 1 */
854 /* [106] */
855 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200856
Harald Weltebda367c2011-07-28 00:03:49 +0200857 0x7F, 0x48, 0x0B,
858 /* ID = 0x48 (ARFN of a CU) ## constructed ## */
859 /* length = 11 */
860 /* [110] */
Dieter Spaar16646022011-07-28 00:01:50 +0200861
Harald Weltebda367c2011-07-28 00:03:49 +0200862 0x5F, 0x40, 0x04,
863 /* ID = 0x40 (Object identity) */
864 /* length = 4 */
865 /* [113] */
866 0x00, 0x08, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200867
Harald Weltebda367c2011-07-28 00:03:49 +0200868 0x4A, 0x02,
869 /* ID = 0x0A (ARFN) ####### */
870 /* length = 2 */
871 /* [119] */
872 0x03, 0x62,
Dieter Spaar16646022011-07-28 00:01:50 +0200873
Harald Weltebda367c2011-07-28 00:03:49 +0200874 0x7F, 0x49, 0x59,
875 /* ID = 0x49 (FU radio definition) ## constructed ## */
876 /* length = 89 */
877 /* [124] */
Dieter Spaar16646022011-07-28 00:01:50 +0200878
Harald Weltebda367c2011-07-28 00:03:49 +0200879 0x5F, 0x40, 0x04,
880 /* ID = 0x40 (Object identity) */
881 /* length = 4 */
882 /* [127] */
883 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200884
Harald Weltebda367c2011-07-28 00:03:49 +0200885 0x4D, 0x50,
886 /* ID = 0x0D (Radio definition per TS) ####### */
887 /* length = 80 */
888 /* [133] */
889 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MA */
890 0x03, 0x62, /* HSN, MAIO or ARFCN if no hopping */
891 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
892 0x03, 0x62,
893 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
894 0x03, 0x62,
895 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
896 0x03, 0x62,
897 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
898 0x03, 0x62,
899 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
900 0x03, 0x62,
901 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
902 0x03, 0x62,
903 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
904 0x03, 0x62,
Dieter Spaar16646022011-07-28 00:01:50 +0200905};
906
907/* TODO: put in a separate file ? */
908
909/*
Harald Weltecde57942011-07-28 00:13:46 +0200910 build the configuration for each TRX
Dieter Spaar16646022011-07-28 00:01:50 +0200911*/
912
Harald Weltebda367c2011-07-28 00:03:49 +0200913static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id,
914 uint8_t * fu_config, int *hopping)
Dieter Spaar16646022011-07-28 00:01:50 +0200915{
Harald Weltebda367c2011-07-28 00:03:49 +0200916 int i;
Dieter Spaar16646022011-07-28 00:01:50 +0200917
Harald Weltebda367c2011-07-28 00:03:49 +0200918 *hopping = 0;
919
920 memcpy(fu_config, fu_config_template, sizeof(fu_config_template));
921
922 /* set ID */
923
924 fu_config[6 + 2] = id;
925 fu_config[66 + 2] = id;
926 fu_config[86 + 2] = id;
927 fu_config[100 + 2] = id;
928 fu_config[113 + 2] = id;
929 fu_config[127 + 2] = id;
930
931 /* set ARFCN */
932
933 uint16_t arfcn = trx->arfcn;
934
935 fu_config[119] = arfcn >> 8;
936 fu_config[119 + 1] = arfcn & 0xFF;
937
938 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
939 struct gsm_bts_trx_ts *ts = &trx->ts[i];
940
941 if (ts->hopping.enabled) {
942 /* reverse order */
943 int j;
944 for (j = 0; j < ts->hopping.ma_len; j++)
945 fu_config[133 + (i * 10) + (7 - j)] =
946 ts->hopping.ma_data[j];
947 fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn;
948 fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio;
949 *hopping = 1;
950 } else {
951 fu_config[133 + 8 + (i * 10)] = arfcn >> 8;
952 fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF;
953 }
954 }
955
956 /* set BSIC */
957
Harald Weltecde57942011-07-28 00:13:46 +0200958 /*
Harald Weltebda367c2011-07-28 00:03:49 +0200959 Attention: all TRX except the first one seem to get the TSC
960 from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION,
Harald Weltecde57942011-07-28 00:13:46 +0200961 GSM 04.08 CHANNEL DESCRIPTION).
962 There was a bug in rsl_chan_activate_lchan() setting this parameter.
Harald Weltebda367c2011-07-28 00:03:49 +0200963 */
964
965 uint8_t bsic = trx->bts->bsic;
966
967 fu_config[106] = bsic;
968
969 /* set CA */
970
971 if (generate_cell_chan_list(&fu_config[38], trx->bts) != 0) {
972 fprintf(stderr, "generate_cell_chan_list failed\n");
973 return 0;
974 }
975
976 /* set channel configuration */
977
978 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
979 struct gsm_bts_trx_ts *ts = &trx->ts[i];
980 uint8_t chan_config;
981
982 /*
983 0 = FCCH + SCH + BCCH + CCCH
984 1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4
985 2 = BCCH + CCCH (This combination is not used in any BTS)
986 3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH
987 4 = SDCCH/8 + SACCH/8
988 5 = SDCCH/8 with SDCCH2 used as CBCH
989 6 = TCH/F + FACCH/F + SACCH/F
990 7 = E-RACH (Talk family)
991 9 = Dual rate (capability for TCH/F and TCH/H)
992 10 = reserved for BTS internal use
Harald Weltecde57942011-07-28 00:13:46 +0200993 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (can be used in GPRS release 2).
994 0xFF = spare TS
Harald Weltebda367c2011-07-28 00:03:49 +0200995 */
996
997 if (ts->pchan == GSM_PCHAN_NONE)
998 chan_config = 0xFF;
999 else if (ts->pchan == GSM_PCHAN_CCCH)
1000 chan_config = 0;
1001 else if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4)
1002 chan_config = 1;
1003 else if (ts->pchan == GSM_PCHAN_TCH_F)
1004 chan_config = 6; /* 9 should work too */
1005 else if (ts->pchan == GSM_PCHAN_TCH_H)
1006 chan_config = 9;
1007 else if (ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C)
1008 chan_config = 4;
1009 else if (ts->pchan == GSM_PCHAN_PDCH)
1010 chan_config = 11;
1011 else {
1012 fprintf(stderr,
1013 "unsupported channel config %d for timeslot %d\n",
1014 ts->pchan, i);
1015 return 0;
1016 }
1017
1018 fu_config[72 + i] = chan_config;
1019 }
1020 return sizeof(fu_config_template);
Dieter Spaar16646022011-07-28 00:01:50 +02001021}
1022
1023/* TODO: put in a separate file ? */
1024
Harald Weltebda367c2011-07-28 00:03:49 +02001025static uint8_t bts_config_1[] = {
1026 0x4E, 0x02,
1027 /* ID = 0x0E (Frame number) */
1028 /* length = 2 */
1029 /* [2] */
1030 0xFF, 0xFF,
1031
1032 0x5F, 0x4E, 0x02,
1033 /* ID = 0x4E (RX antenna supervision period) */
1034 /* length = 2 */
1035 /* [7] */
1036 0xFF, 0xFF,
1037
1038 0x5F, 0x50, 0x02,
1039 /* ID = 0x50 (Sector configuration) */
1040 /* length = 2 */
1041 /* [12] */
1042 0x01, 0x01,
1043};
1044
1045static uint8_t bts_config_2[] = {
1046 0x55, 0x02,
1047 /* ID = 0x15 (Hopping mode) */
1048 /* length = 2 */
1049 /* [2] */
1050 0x01, 0x00,
1051
1052 0x5F, 0x75, 0x02,
1053 /* ID = 0x75 (RX diversity selection) */
1054 /* length = 2 */
1055 /* [7] */
1056 0x01, 0x01,
1057};
1058
1059static uint8_t bts_config_3[] = {
1060 0x5F, 0x20, 0x02,
1061 /* ID = 0x20 (Extended cell radius) */
1062 /* length = 2 */
1063 /* [3] */
1064 0x01, 0x00,
1065};
1066
1067static uint8_t bts_config_4[] = {
1068 0x5F, 0x74, 0x09,
1069 /* ID = 0x74 (Real Time) */
1070 /* length = 9 */
1071 /* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
1072 0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00,
1073 0x00,
1074
1075 0x5F, 0x76, 0x03,
1076 /* ID = 0x76 (EAC input config) */
1077 /* length = 3 */
1078 /* [15] */
1079 0x01, 0x01, 0x00,
1080
1081 0x5F, 0x76, 0x03,
1082 /* ID = 0x76 (EAC input config) */
1083 /* length = 3 */
1084 /* [21] */
1085 0x02, 0x01, 0x00,
1086
1087 0x5F, 0x76, 0x03,
1088 /* ID = 0x76 (EAC input config) */
1089 /* length = 3 */
1090 /* [27] */
1091 0x03, 0x01, 0x00,
1092
1093 0x5F, 0x76, 0x03,
1094 /* ID = 0x76 (EAC input config) */
1095 /* length = 3 */
1096 /* [33] */
1097 0x04, 0x01, 0x00,
1098
1099 0x5F, 0x76, 0x03,
1100 /* ID = 0x76 (EAC input config) */
1101 /* length = 3 */
1102 /* [39] */
1103 0x05, 0x01, 0x00,
1104
1105 0x5F, 0x76, 0x03,
1106 /* ID = 0x76 (EAC input config) */
1107 /* length = 3 */
1108 /* [45] */
1109 0x06, 0x01, 0x00,
1110
1111 0x5F, 0x76, 0x03,
1112 /* ID = 0x76 (EAC input config) */
1113 /* length = 3 */
1114 /* [51] */
1115 0x07, 0x01, 0x00,
1116
1117 0x5F, 0x76, 0x03,
1118 /* ID = 0x76 (EAC input config) */
1119 /* length = 3 */
1120 /* [57] */
1121 0x08, 0x01, 0x00,
1122
1123 0x5F, 0x76, 0x03,
1124 /* ID = 0x76 (EAC input config) */
1125 /* length = 3 */
1126 /* [63] */
1127 0x09, 0x01, 0x00,
1128
1129 0x5F, 0x76, 0x03,
1130 /* ID = 0x76 (EAC input config) */
1131 /* length = 3 */
1132 /* [69] */
1133 0x0A, 0x01, 0x00,
1134};
1135
1136static uint8_t bts_config_insite[] = {
1137 0x4E, 0x02,
1138 /* ID = 0x0E (Frame number) */
1139 /* length = 2 */
1140 /* [2] */
1141 0xFF, 0xFF,
1142
1143 0x5F, 0x4E, 0x02,
1144 /* ID = 0x4E (RX antenna supervision period) */
1145 /* length = 2 */
1146 /* [7] */
1147 0xFF, 0xFF,
1148
1149 0x5F, 0x50, 0x02,
1150 /* ID = 0x50 (Sector configuration) */
1151 /* length = 2 */
1152 /* [12] */
1153 0x01, 0x01,
1154
1155 0x55, 0x02,
1156 /* ID = 0x15 (Hopping mode) */
1157 /* length = 2 */
1158 /* [16] */
1159 0x01, 0x00,
1160
1161 0x5F, 0x20, 0x02,
1162 /* ID = 0x20 (Extended cell radius) */
1163 /* length = 2 */
1164 /* [21] */
1165 0x01, 0x00,
1166
1167 0x5F, 0x74, 0x09,
1168 /* ID = 0x74 (Real Time) */
1169 /* length = 9 */
1170 /* [26] */
1171 0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00,
1172 0x00,
1173};
1174
1175void set_real_time(uint8_t * real_time)
Dieter Spaar16646022011-07-28 00:01:50 +02001176{
Harald Weltebda367c2011-07-28 00:03:49 +02001177 time_t t;
1178 struct tm *tm;
Dieter Spaar16646022011-07-28 00:01:50 +02001179
Harald Weltebda367c2011-07-28 00:03:49 +02001180 t = time(NULL);
1181 tm = localtime(&t);
Dieter Spaar16646022011-07-28 00:01:50 +02001182
Harald Weltebda367c2011-07-28 00:03:49 +02001183 /* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
Dieter Spaar16646022011-07-28 00:01:50 +02001184
Harald Weltebda367c2011-07-28 00:03:49 +02001185 real_time[0] = (1900 + tm->tm_year) >> 8;
1186 real_time[1] = (1900 + tm->tm_year) & 0xFF;
1187 real_time[2] = tm->tm_mon + 1;
1188 real_time[3] = tm->tm_mday;
1189 real_time[4] = tm->tm_hour;
1190 real_time[5] = tm->tm_min;
1191 real_time[6] = tm->tm_sec;
1192 real_time[7] = 0;
1193 real_time[8] = 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001194}
1195
1196/* TODO: put in a separate file ? */
1197
1198/*
Dieter Spaar16646022011-07-28 00:01:50 +02001199 build the configuration data
Dieter Spaar16646022011-07-28 00:01:50 +02001200*/
1201
Harald Weltebda367c2011-07-28 00:03:49 +02001202static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config,
1203 int need_hopping)
Dieter Spaar16646022011-07-28 00:01:50 +02001204{
Harald Weltebda367c2011-07-28 00:03:49 +02001205 /* is it an InSite BTS ? */
1206 if (bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */
1207 if (n_trx != 1) {
1208 fprintf(stderr, "InSite has only one TRX\n");
1209 return 0;
1210 }
1211 if (need_hopping != 0) {
1212 fprintf(stderr, "InSite does not support hopping\n");
1213 return 0;
1214 }
1215 memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite));
1216 set_real_time(&fu_config[26]);
1217 return sizeof(bts_config_insite);
1218 }
Dieter Spaar16646022011-07-28 00:01:50 +02001219
Harald Weltebda367c2011-07-28 00:03:49 +02001220 int len = 0;
1221 int i;
1222
1223 memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1));
1224
1225 /* set sector configuration */
1226 fu_config[len + 12 - 1] = 1 + n_trx; /* len */
1227 for (i = 0; i < n_trx; i++)
1228 fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF);
1229
1230 len += (sizeof(bts_config_1) + (n_trx - 1));
1231
1232 memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2));
1233 /* set hopping mode (Baseband and RF hopping work for the MetroSite) */
1234 if (need_hopping)
1235 fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */
1236 len += sizeof(bts_config_2);
1237
1238 /* set extended cell radius for each TRX */
1239 for (i = 0; i < n_trx; i++) {
1240 memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3));
1241 fu_config[len + 3] = ((i + 1) & 0xFF);
1242 len += sizeof(bts_config_3);
1243 }
1244
1245 memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4));
1246 set_real_time(&fu_config[len + 3]);
1247 len += sizeof(bts_config_4);
1248
1249 return len;
Dieter Spaar16646022011-07-28 00:01:50 +02001250}
1251
1252/* TODO: put in a separate file ? */
1253
1254static struct msgb *nm_msgb_alloc(void)
1255{
Harald Weltebda367c2011-07-28 00:03:49 +02001256 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
Dieter Spaar16646022011-07-28 00:01:50 +02001257}
1258
1259/* TODO: put in a separate file ? */
1260
1261struct abis_om_nokia_hdr {
Harald Weltebda367c2011-07-28 00:03:49 +02001262 uint8_t msg_type;
1263 uint8_t spare;
1264 uint16_t reference;
1265 uint8_t data[0];
Dieter Spaar16646022011-07-28 00:01:50 +02001266} __attribute__ ((packed));
1267
1268#define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr))
1269
Harald Weltebda367c2011-07-28 00:03:49 +02001270static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref,
1271 uint8_t * data, int len_data)
Dieter Spaar16646022011-07-28 00:01:50 +02001272{
Harald Weltebda367c2011-07-28 00:03:49 +02001273 struct abis_om_hdr *oh;
1274 struct abis_om_nokia_hdr *noh;
1275 struct msgb *msg = nm_msgb_alloc();
Dieter Spaar16646022011-07-28 00:01:50 +02001276
Harald Weltebda367c2011-07-28 00:03:49 +02001277 oh = (struct abis_om_hdr *)msgb_put(msg,
1278 ABIS_OM_NOKIA_HDR_SIZE + len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001279
Harald Weltebda367c2011-07-28 00:03:49 +02001280 oh->mdisc = ABIS_OM_MDISC_FOM;
1281 oh->placement = ABIS_OM_PLACEMENT_ONLY;
1282 oh->sequence = 0;
1283 oh->length = sizeof(struct abis_om_nokia_hdr) + len_data;
1284
1285 noh = (struct abis_om_nokia_hdr *)oh->data;
1286
1287 noh->msg_type = msg_type;
1288 noh->spare = 0;
1289 noh->reference = htons(ref);
1290 memcpy(noh->data, data, len_data);
1291
1292 DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type));
1293
1294 return abis_nm_sendmsg(bts, msg);
Dieter Spaar16646022011-07-28 00:01:50 +02001295}
1296
1297/* TODO: put in a separate file ? */
1298
1299static uint8_t download_req[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001300 0x5F, 0x25, 0x0B,
1301 /* ID = 0x25 (File identity) */
1302 /* length = 11 */
1303 /* [3] */
1304 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
1305 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001306
Harald Weltebda367c2011-07-28 00:03:49 +02001307 0x5F, 0x78, 0x03,
1308 /* ID = 0x78 (File version) */
1309 /* length = 3 */
1310 /* [17] */
1311 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001312
Harald Weltebda367c2011-07-28 00:03:49 +02001313 0x5F, 0x81, 0x0A, 0x01,
1314 /* ID = 0x8A (SW load mode) */
1315 /* length = 1 */
1316 /* [24] */
1317 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001318
Harald Weltebda367c2011-07-28 00:03:49 +02001319 0x5F, 0x81, 0x06, 0x01,
1320 /* ID = 0x86 (Acknowledgement period) */
1321 /* length = 1 */
1322 /* [29] */
1323 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001324};
1325
1326static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref)
1327{
Harald Weltebda367c2011-07-28 00:03:49 +02001328 uint8_t *data = download_req;
1329 int len_data = sizeof(download_req);
1330
1331 return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data,
1332 len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001333}
1334
1335/* TODO: put in a separate file ? */
1336
1337static uint8_t ack[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001338 0x5F, 0x23, 0x01,
1339 /* ID = 0x23 (Ack-Nack) */
1340 /* length = 1 */
1341 /* [3] */
1342 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001343};
1344
1345static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref)
1346{
Harald Weltebda367c2011-07-28 00:03:49 +02001347 uint8_t *data = ack;
1348 int len_data = sizeof(ack);
1349
1350 return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001351}
1352
1353/* TODO: put in a separate file ? */
1354
1355static uint8_t reset[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001356 0x5F, 0x40, 0x04,
1357 /* ID = 0x40 (Object identity) */
1358 /* length = 4 */
1359 /* [3] */
1360 0x00, 0x01, 0xFF, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +02001361};
1362
1363static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref)
1364{
Harald Weltebda367c2011-07-28 00:03:49 +02001365 uint8_t *data = reset;
1366 int len_data = sizeof(reset);
1367
1368 return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001369}
1370
1371/* TODO: put in a separate file ? */
1372
Harald Weltebda367c2011-07-28 00:03:49 +02001373static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type,
1374 uint16_t ref, uint8_t * data, int len)
Dieter Spaar16646022011-07-28 00:01:50 +02001375{
Harald Weltebda367c2011-07-28 00:03:49 +02001376 int len_remain, len_to_send, max_send;
1377 int seq = 0;
1378 int ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001379
Harald Weltebda367c2011-07-28 00:03:49 +02001380 len_remain = len;
1381
1382 while (len_remain) {
1383 struct abis_om_hdr *oh;
1384 struct abis_om_nokia_hdr *noh;
1385 struct msgb *msg = nm_msgb_alloc();
1386
1387 if (seq == 0)
1388 max_send = 256 - sizeof(struct abis_om_nokia_hdr);
1389 else
1390 max_send = 256;
1391
1392 if (len_remain > max_send) {
1393 len_to_send = max_send;
1394
1395 if (seq == 0) {
1396 /* first segment */
1397 oh = (struct abis_om_hdr *)msgb_put(msg,
1398 ABIS_OM_NOKIA_HDR_SIZE
1399 +
1400 len_to_send);
1401
1402 oh->mdisc = ABIS_OM_MDISC_FOM;
1403 oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */
1404 oh->sequence = seq;
1405 oh->length = 0; /* 256 bytes */
1406
1407 noh = (struct abis_om_nokia_hdr *)oh->data;
1408
1409 noh->msg_type = msg_type;
1410 noh->spare = 0;
1411 noh->reference = htons(ref);
1412 memcpy(noh->data, data, len_to_send);
1413 } else {
1414 /* segment in between */
1415 oh = (struct abis_om_hdr *)msgb_put(msg,
1416 sizeof
1417 (struct
1418 abis_om_hdr)
1419 +
1420 len_to_send);
1421
1422 oh->mdisc = ABIS_OM_MDISC_FOM;
1423 oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */
1424 oh->sequence = seq;
1425 oh->length = 0; /* 256 bytes */
1426
1427 memcpy(oh->data, data, len_to_send);
1428 }
1429 } else {
1430
1431 len_to_send = len_remain;
1432
1433 /* check if message fits in a single segment */
1434
1435 if (seq == 0)
1436 return abis_nm_send(bts, msg_type, ref, data,
1437 len_to_send);
1438
1439 /* last segment */
1440
1441 oh = (struct abis_om_hdr *)msgb_put(msg,
1442 sizeof(struct
1443 abis_om_hdr)
1444 + len_to_send);
1445
1446 oh->mdisc = ABIS_OM_MDISC_FOM;
1447 oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */
1448 oh->sequence = seq;
1449 oh->length = len_to_send;
1450
1451 memcpy(oh->data, data, len_to_send);
1452 }
1453
1454 DEBUGPC(DNM, "Sending multi-segment %d\n", seq);
1455
1456 ret = abis_nm_sendmsg(bts, msg);
1457 if (ret < 0)
1458 return ret;
1459
1460 abis_nm_queue_send_next(bts);
1461
1462 /* next segment */
1463 len_remain -= len_to_send;
1464 data += len_to_send;
1465 seq++;
1466 }
1467 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001468}
1469
1470/* TODO: put in a separate file ? */
1471
1472static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type)
1473{
Harald Weltebda367c2011-07-28 00:03:49 +02001474 struct gsm_bts_trx *trx;
1475 uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */
1476 int len = 0;
1477 int idx = 0;
1478 int ret;
1479 int hopping = 0;
1480 int need_hopping = 0;
1481
1482 memset(config, 0, sizeof(config));
1483
1484 llist_for_each_entry(trx, &bts->trx_list, list) {
1485#if 0 /* debugging */
1486 printf("TRX\n");
1487 printf(" arfcn: %d\n", trx->arfcn);
1488 printf(" bsic: %d\n", trx->bts->bsic);
1489 uint8_t ca[20];
1490 memset(ca, 0xFF, sizeof(ca));
1491 ret = generate_cell_chan_list(ca, trx->bts);
1492 printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca)));
1493 int i;
1494 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
1495 struct gsm_bts_trx_ts *ts = &trx->ts[i];
1496
1497 printf(" pchan %d: %d\n", i, ts->pchan);
1498 }
Dieter Spaar16646022011-07-28 00:01:50 +02001499#endif
Harald Weltebda367c2011-07-28 00:03:49 +02001500 ret = make_fu_config(trx, idx + 1, config + len, &hopping);
1501 need_hopping |= hopping;
1502 len += ret;
1503
1504 idx++;
1505 }
1506
1507 ret = make_bts_config(bts_type, idx, config + len, need_hopping);
1508 len += ret;
1509
1510#if 0 /* debugging */
1511 dump_elements(config, len);
1512#endif
1513
1514 return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config,
1515 len);
Dieter Spaar16646022011-07-28 00:01:50 +02001516}
1517
1518#define GET_NEXT_BYTE if(idx >= len) return 0; \
Harald Weltebda367c2011-07-28 00:03:49 +02001519 ub = data[idx++];
Dieter Spaar16646022011-07-28 00:01:50 +02001520
Harald Weltebda367c2011-07-28 00:03:49 +02001521static int find_element(uint8_t * data, int len, uint16_t id, uint8_t * value,
1522 int max_value)
1523{
1524 uint8_t ub;
1525 int idx = 0;
1526 int found = 0;
1527 int constructed;
1528 uint16_t id_value;
1529
1530 for (;;) {
1531
1532 GET_NEXT_BYTE;
1533
1534 /* encoding bit, construced means that other elements are contained */
1535 constructed = ((ub & 0x20) ? 1 : 0);
1536
1537 if ((ub & 0x1F) == 0x1F) {
1538 /* fixed pattern, ID follows */
1539 GET_NEXT_BYTE; /* ID */
1540 id_value = ub & 0x7F;
1541 if (ub & 0x80) {
1542 /* extension bit */
1543 GET_NEXT_BYTE; /* ID low part */
1544 id_value = (id_value << 7) | (ub & 0x7F);
1545 }
1546 if (id_value == id)
1547 found = 1;
1548 } else {
1549 id_value = (ub & 0x3F);
1550 if (id_value == id)
1551 found = 1;
1552 }
1553
1554 GET_NEXT_BYTE; /* length */
1555
1556 if (found) {
1557 /* get data */
1558 uint8_t n = ub;
1559 uint8_t i;
1560 for (i = 0; i < n; i++) {
1561 GET_NEXT_BYTE;
1562 if (max_value <= 0)
1563 return -1; /* buffer too small */
1564 *value = ub;
1565 value++;
1566 max_value--;
1567 }
1568 return n; /* length */
1569 } else {
1570 /* skip data */
1571 uint8_t n = ub;
1572 uint8_t i;
1573 for (i = 0; i < n; i++) {
1574 GET_NEXT_BYTE;
1575 }
1576 }
1577 }
1578 return 0; /* not found */
Dieter Spaar16646022011-07-28 00:01:50 +02001579}
1580
Harald Weltebda367c2011-07-28 00:03:49 +02001581static int dump_elements(uint8_t * data, int len)
1582{
1583 uint8_t ub;
1584 int idx = 0;
1585 int constructed;
1586 uint16_t id_value;
1587 static char indent[100] = ""; /* TODO: move static to BTS context */
Dieter Spaar16646022011-07-28 00:01:50 +02001588
Harald Weltebda367c2011-07-28 00:03:49 +02001589 for (;;) {
1590
1591 GET_NEXT_BYTE;
1592
1593 /* encoding bit, construced means that other elements are contained */
1594 constructed = ((ub & 0x20) ? 1 : 0);
1595
1596 if ((ub & 0x1F) == 0x1F) {
1597 /* fixed pattern, ID follows */
1598 GET_NEXT_BYTE; /* ID */
1599 id_value = ub & 0x7F;
1600 if (ub & 0x80) {
1601 /* extension bit */
1602 GET_NEXT_BYTE; /* ID low part */
1603 id_value = (id_value << 7) | (ub & 0x7F);
1604 }
1605
1606 } else {
1607 id_value = (ub & 0x3F);
1608 }
1609
1610 GET_NEXT_BYTE; /* length */
1611
1612 printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value,
1613 get_element_name_string(id_value),
1614 constructed ? "** constructed **" : "");
1615 printf("%s length = %d\n", indent, ub);
1616 printf("%s %s\n", indent, osmo_hexdump(data + idx, ub));
1617
1618 if (constructed) {
1619 int indent_len = strlen(indent);
1620 strcat(indent, " ");
1621
1622 dump_elements(data + idx, ub);
1623
1624 indent[indent_len] = 0;
1625 }
1626 /* skip data */
1627 uint8_t n = ub;
1628 uint8_t i;
1629 for (i = 0; i < n; i++) {
1630 GET_NEXT_BYTE;
1631 }
1632 }
1633 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001634}
1635
1636/* TODO: put in a separate file ? */
1637
1638/* taken from abis_nm.c */
1639
1640static void abis_nm_queue_send_next(struct gsm_bts *bts)
1641{
Harald Weltebda367c2011-07-28 00:03:49 +02001642 int wait = 0;
1643 struct msgb *msg;
1644 /* the queue is empty */
1645 while (!llist_empty(&bts->abis_queue)) {
1646 msg = msgb_dequeue(&bts->abis_queue);
1647 wait = OBSC_NM_W_ACK_CB(msg);
1648 _abis_nm_sendmsg(msg, 0);
Dieter Spaar16646022011-07-28 00:01:50 +02001649
Harald Weltebda367c2011-07-28 00:03:49 +02001650 if (wait)
1651 break;
1652 }
Dieter Spaar16646022011-07-28 00:01:50 +02001653
Harald Weltebda367c2011-07-28 00:03:49 +02001654 bts->abis_nm_pend = wait;
Dieter Spaar16646022011-07-28 00:01:50 +02001655}
1656
1657/* TODO: put in a separate file ? */
1658
1659/* timer for restarting OML after BTS reset */
1660
1661static void reset_timer_cb(void *_bts)
1662{
Harald Weltebda367c2011-07-28 00:03:49 +02001663 struct gsm_bts *bts = _bts;
1664 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1665 struct e1inp_line *line;
1666
Harald Weltec8755af2011-07-28 00:22:17 +02001667 bts->nokia.wait_reset = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001668
1669 /* OML link */
1670 line = e1inp_line_get(e1_link->e1_nr);
1671 if (!line) {
1672 LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to "
1673 "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
1674 return;
1675 }
1676
1677 start_sabm_in_line(line, 0, -1); /* stop all first */
1678 start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */
Dieter Spaar16646022011-07-28 00:01:50 +02001679}
1680
1681/* TODO: put in a separate file ? */
1682
1683/*
1684 This is how the configuration is done:
Dieter Spaar16646022011-07-28 00:01:50 +02001685 - start OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001686 - reset BTS
Dieter Spaar16646022011-07-28 00:01:50 +02001687 - receive ACK, wait some time and restart OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001688 - receive OMU STARTED message, send START DOWNLOAD REQ
Dieter Spaar16646022011-07-28 00:01:50 +02001689 - receive CNF REQ message, send CONF DATA
Dieter Spaar16646022011-07-28 00:01:50 +02001690 - receive ACK, start RSL link(s)
Dieter Spaar16646022011-07-28 00:01:50 +02001691 ACK some other messages received from the BTS.
Harald Weltecde57942011-07-28 00:13:46 +02001692
Dieter Spaar16646022011-07-28 00:01:50 +02001693 Probably its also possible to configure the BTS without a reset, this
1694 has not been tested yet.
1695*/
1696
1697static int abis_nm_rcvmsg_fom(struct msgb *mb)
1698{
Harald Weltebda367c2011-07-28 00:03:49 +02001699 struct gsm_bts *bts = mb->trx->bts;
1700 struct abis_om_hdr *oh = msgb_l2(mb);
1701 struct abis_om_nokia_hdr *noh = msgb_l3(mb);
1702 uint8_t mt = noh->msg_type;
1703 int ret = 0;
1704 uint16_t ref = ntohs(noh->reference);
Harald Weltebda367c2011-07-28 00:03:49 +02001705 uint8_t info[256];
1706 uint8_t ack = 0xFF;
1707 uint8_t severity = 0xFF;
1708 int str_len;
1709 int len_data;
Dieter Spaar16646022011-07-28 00:01:50 +02001710
Harald Weltec8755af2011-07-28 00:22:17 +02001711 if (bts->nokia.wait_reset) {
Harald Weltebda367c2011-07-28 00:03:49 +02001712 LOGP(DNM, LOGL_INFO,
1713 "Ignore message while waiting for reset\n");
1714 return ret;
1715 }
Dieter Spaar16646022011-07-28 00:01:50 +02001716
Harald Weltebda367c2011-07-28 00:03:49 +02001717 if (oh->length < sizeof(struct abis_om_nokia_hdr)) {
1718 LOGP(DNM, LOGL_ERROR, "Message too short\n");
1719 return -EINVAL;
1720 }
1721
1722 len_data = oh->length - sizeof(struct abis_om_nokia_hdr);
1723 LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt));
1724#if 0 /* debugging */
1725 dump_elements(noh->data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001726#endif
Dieter Spaar16646022011-07-28 00:01:50 +02001727
Harald Weltebda367c2011-07-28 00:03:49 +02001728 switch (mt) {
1729 case NOKIA_MSG_OMU_STARTED:
Harald Welte9d2f3772011-07-28 00:19:06 +02001730 if (find_element(noh->data, len_data,
1731 NOKIA_EI_BTS_TYPE, &bts->nokia.bts_type,
1732 sizeof(uint8_t)) == sizeof(uint8_t))
1733 LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n",
1734 bts->nokia.bts_type,
1735 get_bts_type_string(bts->nokia.bts_type));
Harald Weltebda367c2011-07-28 00:03:49 +02001736 else
1737 LOGP(DNM, LOGL_ERROR, "BTS type not found\n");
1738 /* send START_DOWNLOAD_REQ */
1739 abis_nm_download_req(bts, ref);
1740 break;
1741 case NOKIA_MSG_MF_REQ:
1742 break;
1743 case NOKIA_MSG_CONF_REQ:
1744 /* send ACK */
1745 abis_nm_ack(bts, ref);
1746 abis_nm_queue_send_next(bts);
1747 /* send CONF_DATA */
Harald Welte9d2f3772011-07-28 00:19:06 +02001748 abis_nm_send_config(bts, bts->nokia.bts_type);
1749 bts->nokia.configured = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001750 break;
1751 case NOKIA_MSG_ACK:
1752 if (find_element
1753 (noh->data, len_data, NOKIA_EI_ACK, &ack,
1754 sizeof(uint8_t)) == sizeof(uint8_t)) {
1755 LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack);
1756 if (ack != 1) {
1757 LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n",
1758 ack);
1759 /* TODO: properly handle failures (NACK) */
1760 }
1761 } else
1762 LOGP(DNM, LOGL_ERROR, "ACK not found\n");
Dieter Spaar16646022011-07-28 00:01:50 +02001763
Harald Weltebda367c2011-07-28 00:03:49 +02001764 /* TODO: the assumption for the following is that no NACK was received */
1765
1766 /* ACK for reset message ? */
Harald Weltec8755af2011-07-28 00:22:17 +02001767 if (bts->nokia.do_reset != 0) {
1768 bts->nokia.do_reset = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001769
1770 /*
1771 TODO: For the InSite processing the received data is
1772 blocked in the driver during reset.
1773 Otherwise the LAPD module might assert because the InSite
1774 sends garbage on the E1 line during reset.
1775 This is done by looking at "wait_reset" in the driver
1776 (function handle_ts1_read()) and ignoring the received data.
1777 It seems to be necessary for the MetroSite too.
1778 */
Harald Weltec8755af2011-07-28 00:22:17 +02001779 bts->nokia.wait_reset = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001780
Harald Weltec8755af2011-07-28 00:22:17 +02001781 bts->nokia.reset_timer.cb = &reset_timer_cb;
1782 bts->nokia.reset_timer.data = bts;
1783 osmo_timer_schedule(&bts->nokia.reset_timer, RESET_INTERVAL);
Harald Weltebda367c2011-07-28 00:03:49 +02001784
1785 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1786 struct e1inp_line *line;
1787 /* OML link */
1788 line = e1inp_line_get(e1_link->e1_nr);
1789 if (!line) {
1790 LOGP(DINP, LOGL_ERROR,
1791 "BTS %u OML link referring to "
1792 "non-existing E1 line %u\n", bts->nr,
1793 e1_link->e1_nr);
1794 return -ENOMEM;
1795 }
1796
1797 start_sabm_in_line(line, 0, -1); /* stop all first */
1798 }
1799
1800 /* ACK for CONF DATA message ? */
Harald Welte9d2f3772011-07-28 00:19:06 +02001801 if (bts->nokia.configured != 0) {
Harald Weltebda367c2011-07-28 00:03:49 +02001802 /* start TRX (RSL link) */
1803
1804 struct gsm_e1_subslot *e1_link = &mb->trx->rsl_e1_link;
1805 struct e1inp_line *line;
1806
Harald Welte9d2f3772011-07-28 00:19:06 +02001807 bts->nokia.configured = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001808
1809 /* RSL Link */
1810 line = e1inp_line_get(e1_link->e1_nr);
1811 if (!line) {
1812 LOGP(DINP, LOGL_ERROR,
1813 "TRX (%u/%u) RSL link referring "
1814 "to non-existing E1 line %u\n",
1815 mb->trx->bts->nr, mb->trx->nr,
1816 e1_link->e1_nr);
1817 return -ENOMEM;
1818 }
1819 /* start TRX */
1820 start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */
1821 }
1822 break;
1823 case NOKIA_MSG_STATE_CHANGED:
1824 /* send ACK */
1825 abis_nm_ack(bts, ref);
1826 break;
1827 case NOKIA_MSG_CONF_COMPLETE:
1828 /* send ACK */
1829 abis_nm_ack(bts, ref);
1830 break;
1831 case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */
1832 /* send ACK (do we have to send an ACK ?) */
1833 abis_nm_ack(bts, ref);
1834 break;
1835 case NOKIA_MSG_ALARM:
1836 find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity,
1837 sizeof(severity));
1838 /* TODO: there might be alarms with both elements set */
1839 str_len =
1840 find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info,
1841 sizeof(info));
1842 if (str_len > 0) {
1843 info[str_len] = 0;
1844 LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n",
1845 get_severity_string(severity), severity, info);
1846 } else { /* nothing found, try details */
1847 str_len =
1848 find_element(noh->data, len_data,
1849 NOKIA_EI_ALARM_DETAIL, info,
1850 sizeof(info));
1851 if (str_len > 0) {
1852 uint16_t code;
1853 info[str_len] = 0;
1854 code = (info[0] << 8) + info[1];
1855 LOGP(DNM, LOGL_INFO,
1856 "ALARM Severity %s (%d), code 0x%X : %s\n",
1857 get_severity_string(severity), severity,
1858 code, info + 2);
1859 }
1860 }
1861 /* send ACK */
1862 abis_nm_ack(bts, ref);
1863 break;
1864 }
1865
1866 abis_nm_queue_send_next(bts);
1867
1868 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001869}
1870
1871/* TODO: put in a separate file ? */
1872
1873int abis_nokia_rcvmsg(struct msgb *msg)
1874{
Harald Weltebda367c2011-07-28 00:03:49 +02001875 struct abis_om_hdr *oh = msgb_l2(msg);
1876 int rc = 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001877
Harald Weltebda367c2011-07-28 00:03:49 +02001878 /* Various consistency checks */
1879 if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
1880 LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
1881 oh->placement);
1882 if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
1883 return -EINVAL;
1884 }
1885 if (oh->sequence != 0) {
1886 LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
1887 oh->sequence);
1888 return -EINVAL;
1889 }
1890 msg->l3h = (unsigned char *)oh + sizeof(*oh);
Dieter Spaar16646022011-07-28 00:01:50 +02001891
Harald Weltebda367c2011-07-28 00:03:49 +02001892 switch (oh->mdisc) {
1893 case ABIS_OM_MDISC_FOM:
1894 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n");
1895 rc = abis_nm_rcvmsg_fom(msg);
1896 break;
1897 case ABIS_OM_MDISC_MANUF:
1898 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n");
1899 break;
1900 case ABIS_OM_MDISC_MMI:
1901 case ABIS_OM_MDISC_TRAU:
1902 LOGP(DNM, LOGL_ERROR,
1903 "unimplemented ABIS OML message discriminator 0x%x\n",
1904 oh->mdisc);
1905 break;
1906 default:
1907 LOGP(DNM, LOGL_ERROR,
1908 "unknown ABIS OML message discriminator 0x%x\n",
1909 oh->mdisc);
1910 return -EINVAL;
1911 }
Dieter Spaar16646022011-07-28 00:01:50 +02001912
Harald Weltebda367c2011-07-28 00:03:49 +02001913 msgb_free(msg);
1914 return rc;
Dieter Spaar16646022011-07-28 00:01:50 +02001915}
1916
1917static int bts_model_nokia_site_start(struct gsm_network *net);
1918
1919static struct gsm_bts_model model_nokia_site = {
Harald Weltebda367c2011-07-28 00:03:49 +02001920 .type = GSM_BTS_TYPE_NOKIA_SITE,
1921 .name = "nokia_site",
1922 .start = bts_model_nokia_site_start,
1923 .oml_rcvmsg = &abis_nokia_rcvmsg
Dieter Spaar16646022011-07-28 00:01:50 +02001924};
1925
1926static struct gsm_network *my_net;
1927
1928static int bts_model_nokia_site_start(struct gsm_network *net)
1929{
Harald Weltebda367c2011-07-28 00:03:49 +02001930 model_nokia_site.features.data = &model_nokia_site._features_data[0];
1931 model_nokia_site.features.data_len =
1932 sizeof(model_nokia_site._features_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001933
Harald Weltebda367c2011-07-28 00:03:49 +02001934 gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HOPPING);
1935 gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HSCSD);
Dieter Spaar16646022011-07-28 00:01:50 +02001936
Harald Weltebda367c2011-07-28 00:03:49 +02001937 osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL);
1938 osmo_signal_register_handler(SS_GLOBAL, gbl_sig_cb, NULL);
1939 osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
Dieter Spaar16646022011-07-28 00:01:50 +02001940
Harald Weltebda367c2011-07-28 00:03:49 +02001941 my_net = net;
1942
1943 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001944}
1945
1946int bts_model_nokia_site_init(void)
1947{
Harald Weltebda367c2011-07-28 00:03:49 +02001948 return gsm_bts_model_register(&model_nokia_site);
Dieter Spaar16646022011-07-28 00:01:50 +02001949}