blob: 033f6fec7a0dc6711b9a32fc7e4ece3368565875 [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
45/* TODO: move statics to BTS context */
46static int do_reset = 1;
47/*static*/ int wait_reset = 0;
Harald Weltebda367c2011-07-28 00:03:49 +020048struct osmo_timer_list reset_timer; /* timer to re-start after reset */
Dieter Spaar16646022011-07-28 00:01:50 +020049
Harald Weltebda367c2011-07-28 00:03:49 +020050#define RESET_INTERVAL 0, 3000000 /* 3 seconds */
Dieter Spaar16646022011-07-28 00:01:50 +020051
52extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg);
53/* was static in system_information.c */
Harald Weltebda367c2011-07-28 00:03:49 +020054extern int generate_cell_chan_list(uint8_t * chan_list, struct gsm_bts *bts);
Dieter Spaar16646022011-07-28 00:01:50 +020055
56static void abis_nm_queue_send_next(struct gsm_bts *bts);
57static void reset_timer_cb(void *_bts);
58static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref);
Harald Weltebda367c2011-07-28 00:03:49 +020059static int dump_elements(uint8_t * data, int len);
Dieter Spaar16646022011-07-28 00:01:50 +020060
61static void bootstrap_om_bts(struct gsm_bts *bts)
62{
Harald Weltebda367c2011-07-28 00:03:49 +020063 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
64
65 if (do_reset)
66 abis_nm_reset(bts, 1);
Dieter Spaar16646022011-07-28 00:01:50 +020067}
68
69static void bootstrap_om_trx(struct gsm_bts_trx *trx)
70{
Harald Weltebda367c2011-07-28 00:03:49 +020071 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
72 trx->bts->nr, trx->nr);
Dieter Spaar16646022011-07-28 00:01:50 +020073}
74
75static int shutdown_om(struct gsm_bts *bts)
76{
Harald Weltebda367c2011-07-28 00:03:49 +020077 /* TODO !? */
78 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +020079}
80
81#define SAPI_OML 62
82#define SAPI_RSL 0
83
84/*
85
86 Tell LAPD to start start the SAP (send SABM requests) for all signalling
87 timeslots in this line
88
89 Attention: this has to be adapted for MISDN
90*/
Harald Weltebda367c2011-07-28 00:03:49 +020091
Dieter Spaar16646022011-07-28 00:01:50 +020092static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi)
93{
Harald Weltebda367c2011-07-28 00:03:49 +020094 struct e1inp_sign_link *link;
95 int i;
Dieter Spaar16646022011-07-28 00:01:50 +020096
Harald Weltebda367c2011-07-28 00:03:49 +020097 for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
98 struct e1inp_ts *ts = &line->ts[i];
Dieter Spaar16646022011-07-28 00:01:50 +020099
Harald Weltebda367c2011-07-28 00:03:49 +0200100 if (ts->type != E1INP_TS_TYPE_SIGN)
101 continue;
Dieter Spaar16646022011-07-28 00:01:50 +0200102
Harald Weltebda367c2011-07-28 00:03:49 +0200103 llist_for_each_entry(link, &ts->sign.sign_links, list) {
104 if (sapi != -1 && link->sapi != sapi)
105 continue;
106
107#if 0 /* debugging */
108 printf("sap start/stop (%d): %d tei=%d sapi=%d\n",
109 start, i + 1, link->tei, link->sapi);
Dieter Spaar16646022011-07-28 00:01:50 +0200110#endif
Harald Weltebda367c2011-07-28 00:03:49 +0200111
112 if (start)
113 lapd_sap_start(ts->driver.dahdi.lapd, link->tei,
114 link->sapi);
115 else
116 lapd_sap_stop(ts->driver.dahdi.lapd, link->tei,
117 link->sapi);
118 }
119 }
Dieter Spaar16646022011-07-28 00:01:50 +0200120}
121
122/* Callback function to be called every time we receive a signal from INPUT */
123static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200124 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200125{
Harald Weltebda367c2011-07-28 00:03:49 +0200126 struct gsm_bts *bts;
Dieter Spaar16646022011-07-28 00:01:50 +0200127
Harald Weltebda367c2011-07-28 00:03:49 +0200128 if (subsys != SS_GLOBAL)
129 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200130
Harald Weltebda367c2011-07-28 00:03:49 +0200131 switch (signal) {
132 case S_GLOBAL_BTS_CLOSE_OM:
133 bts = signal_data;
134 if (bts->type == GSM_BTS_TYPE_NOKIA_SITE)
135 shutdown_om(signal_data);
136 break;
137 }
Dieter Spaar16646022011-07-28 00:01:50 +0200138
Harald Weltebda367c2011-07-28 00:03:49 +0200139 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200140}
141
142/* Callback function to be called every time we receive a signal from INPUT */
143static int inp_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200144 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200145{
Harald Weltebda367c2011-07-28 00:03:49 +0200146 struct input_signal_data *isd = signal_data;
Dieter Spaar16646022011-07-28 00:01:50 +0200147
Harald Weltebda367c2011-07-28 00:03:49 +0200148 if (subsys != SS_INPUT)
149 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200150
Harald Weltebda367c2011-07-28 00:03:49 +0200151 switch (signal) {
152 case S_INP_LINE_INIT:
153 start_sabm_in_line(isd->line, 1, SAPI_OML); /* start only OML */
154 break;
155 case S_INP_TEI_DN:
156 break;
157 case S_INP_TEI_UP:
158 switch (isd->link_type) {
159 case E1INP_SIGN_OML:
160 if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
161 break;
Dieter Spaar16646022011-07-28 00:01:50 +0200162
Harald Weltebda367c2011-07-28 00:03:49 +0200163 if (isd->tei == isd->trx->bts->oml_tei)
164 bootstrap_om_bts(isd->trx->bts);
165 else
166 bootstrap_om_trx(isd->trx);
167 break;
168 }
169 break;
170 }
171
172 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200173}
174
175static void nm_statechg_evt(unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200176 struct nm_statechg_signal_data *nsd)
Dieter Spaar16646022011-07-28 00:01:50 +0200177{
Harald Weltebda367c2011-07-28 00:03:49 +0200178 if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
179 return;
Dieter Spaar16646022011-07-28 00:01:50 +0200180}
181
182static int nm_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200183 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200184{
Harald Weltebda367c2011-07-28 00:03:49 +0200185 if (subsys != SS_NM)
186 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200187
Harald Weltebda367c2011-07-28 00:03:49 +0200188 switch (signal) {
189 case S_NM_STATECHG_OPER:
190 case S_NM_STATECHG_ADM:
191 nm_statechg_evt(signal, signal_data);
192 break;
193 default:
194 break;
195 }
Dieter Spaar16646022011-07-28 00:01:50 +0200196
Harald Weltebda367c2011-07-28 00:03:49 +0200197 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200198}
199
200/* TODO: put in a separate file ? */
201
202static char *get_msg_type_name_string(uint8_t msg_type)
203{
Harald Weltebda367c2011-07-28 00:03:49 +0200204 switch (msg_type) {
205 case 0x80:
206 return "NOKIA_BTS_CONF_DATA";
207 case 0x81:
208 return "NOKIA_BTS_ACK";
209 case 0x82:
210 return "NOKIA_BTS_OMU_STARTED";
211 case 0x83:
212 return "NOKIA_BTS_START_DOWNLOAD_REQ";
213 case 0x84:
214 return "NOKIA_BTS_MF_REQ";
215 case 0x85:
216 return "NOKIA_BTS_AF_REQ";
217 case 0x86:
218 return "NOKIA_BTS_RESET_REQ";
219 case 0x87:
220 return "NOKIA_reserved";
221 case 0x88:
222 return "NOKIA_BTS_CONF_REQ";
223 case 0x89:
224 return "NOKIA_BTS_TEST_REQ";
225 case 0x8A:
226 return "NOKIA_BTS_TEST_REPORT";
227 case 0x8B:
228 return "NOKIA_reserved";
229 case 0x8C:
230 return "NOKIA_reserved";
231 case 0x8D:
232 return "NOKIA_reserved";
233 case 0x8E:
234 return "NOKIA_BTS_CONF_COMPL";
235 case 0x8F:
236 return "NOKIA_reserved";
237 case 0x90:
238 return "NOKIA_BTS_STM_TEST_REQ";
239 case 0x91:
240 return "NOKIA_BTS_STM_TEST_REPORT";
241 case 0x92:
242 return "NOKIA_BTS_TRANSMISSION_COMMAND";
243 case 0x93:
244 return "NOKIA_BTS_TRANSMISSION_ANSWER";
245 case 0x94:
246 return "NOKIA_BTS_HW_DB_UPLOAD_REQ";
247 case 0x95:
248 return "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ";
249 case 0x96:
250 return "NOKIA_BTS_HW_DB_SAVE_REQ";
251 case 0x97:
252 return "NOKIA_BTS_FLASH_ERASURE_REQ";
253 case 0x98:
254 return "NOKIA_BTS_HW_DB_DOWNLOAD_REQ";
255 case 0x99:
256 return "NOKIA_BTS_PWR_SUPPLY_CONTROL";
257 case 0x9A:
258 return "NOKIA_BTS_ATTRIBUTE_REQ";
259 case 0x9B:
260 return "NOKIA_BTS_ATTRIBUTE_REPORT";
261 case 0x9C:
262 return "NOKIA_BTS_HW_REQ";
263 case 0x9D:
264 return "NOKIA_BTS_HW_REPORT";
265 case 0x9E:
266 return "NOKIA_BTS_RTE_TEST_REQ";
267 case 0x9F:
268 return "NOKIA_BTS_RTE_TEST_REPORT";
269 case 0xA0:
270 return "NOKIA_BTS_HW_DB_VERIFICATION_REQ";
271 case 0xA1:
272 return "NOKIA_BTS_CLOCK_REQ";
273 case 0xA2:
274 return "NOKIA_AC_CIRCUIT_REQ_NACK";
275 case 0xA3:
276 return "NOKIA_AC_INTERRUPTED";
277 case 0xA4:
278 return "NOKIA_BTS_NEW_TRE_INFO";
279 case 0xA5:
280 return "NOKIA_AC_BSC_CIRCUITS_ALLOCATED";
281 case 0xA6:
282 return "NOKIA_BTS_TRE_POLL_LIST";
283 case 0xA7:
284 return "NOKIA_AC_CIRCUIT_REQ";
285 case 0xA8:
286 return "NOKIA_BTS_BLOCK_CTRL_REQ";
287 case 0xA9:
288 return "NOKIA_BTS_GSM_TIME_REQ";
289 case 0xAA:
290 return "NOKIA_BTS_GSM_TIME";
291 case 0xAB:
292 return "NOKIA_BTS_OUTPUT_CONTROL";
293 case 0xAC:
294 return "NOKIA_BTS_STATE_CHANGED";
295 case 0xAD:
296 return "NOKIA_BTS_SW_SAVE_REQ";
297 case 0xAE:
298 return "NOKIA_BTS_ALARM";
299 case 0xAF:
300 return "NOKIA_BTS_CHA_ADM_STATE";
301 case 0xB0:
302 return "NOKIA_AC_POOL_SIZE_REPORT";
303 case 0xB1:
304 return "NOKIA_AC_POOL_SIZE_INQUIRY";
305 case 0xB2:
306 return "NOKIA_BTS_COMMISS_TEST_COMPLETED";
307 case 0xB3:
308 return "NOKIA_BTS_COMMISS_TEST_REQ";
309 case 0xB4:
310 return "NOKIA_BTS_TRANSP_BTS_TO_BSC";
311 case 0xB5:
312 return "NOKIA_BTS_TRANSP_BSC_TO_BTS";
313 case 0xB6:
314 return "NOKIA_BTS_LCS_COMMAND";
315 case 0xB7:
316 return "NOKIA_BTS_LCS_ANSWER";
317 case 0xB8:
318 return "NOKIA_BTS_LMU_FN_OFFSET_COMMAND";
319 case 0xB9:
320 return "NOKIA_BTS_LMU_FN_OFFSET_ANSWER";
321 default:
322 return "unknown";
323 }
Dieter Spaar16646022011-07-28 00:01:50 +0200324}
325
326static char *get_element_name_string(uint16_t element)
327{
Harald Weltebda367c2011-07-28 00:03:49 +0200328 switch (element) {
329 case 0x01:
330 return "Ny1";
331 case 0x02:
332 return "T3105_F";
333 case 0x03:
334 return "Interference band limits";
335 case 0x04:
336 return "Interference report timer in secs";
337 case 0x05:
338 return "Channel configuration per TS";
339 case 0x06:
340 return "BSIC";
341 case 0x07:
342 return "RACH report timer in secs";
343 case 0x08:
344 return "Hardware database status";
345 case 0x09:
346 return "BTS RX level";
347 case 0x0A:
348 return "ARFN";
349 case 0x0B:
350 return "STM antenna attenuation";
351 case 0x0C:
352 return "Cell allocation bitmap";
353 case 0x0D:
354 return "Radio definition per TS";
355 case 0x0E:
356 return "Frame number";
357 case 0x0F:
358 return "Antenna diversity";
359 case 0x10:
360 return "T3105_D";
361 case 0x11:
362 return "File format";
363 case 0x12:
364 return "Last File";
365 case 0x13:
366 return "BTS type";
367 case 0x14:
368 return "Erasure mode";
369 case 0x15:
370 return "Hopping mode";
371 case 0x16:
372 return "Floating TRX";
373 case 0x17:
374 return "Power supplies";
375 case 0x18:
376 return "Reset type";
377 case 0x19:
378 return "Averaging period";
379 case 0x1A:
380 return "RBER2";
381 case 0x1B:
382 return "LAC";
383 case 0x1C:
384 return "CI";
385 case 0x1D:
386 return "Failure parameters";
387 case 0x1E:
388 return "(RF max power reduction)";
389 case 0x1F:
390 return "Measured RX_SENS";
391 case 0x20:
392 return "Extended cell radius";
393 case 0x21:
394 return "reserved";
395 case 0x22:
396 return "Success-Failure";
397 case 0x23:
398 return "Ack-Nack";
399 case 0x24:
400 return "OMU test results";
401 case 0x25:
402 return "File identity";
403 case 0x26:
404 return "Generation and version code";
405 case 0x27:
406 return "SW description";
407 case 0x28:
408 return "BCCH LEV";
409 case 0x29:
410 return "Test type";
411 case 0x2A:
412 return "Subscriber number";
413 case 0x2B:
414 return "reserved";
415 case 0x2C:
416 return "HSN";
417 case 0x2D:
418 return "reserved";
419 case 0x2E:
420 return "MS RXLEV";
421 case 0x2F:
422 return "MS TXLEV";
423 case 0x30:
424 return "RXQUAL";
425 case 0x31:
426 return "RX SENS";
427 case 0x32:
428 return "Alarm block";
429 case 0x33:
430 return "Neighbouring BCCH levels";
431 case 0x34:
432 return "STM report type";
433 case 0x35:
434 return "MA";
435 case 0x36:
436 return "MAIO";
437 case 0x37:
438 return "H_FLAG";
439 case 0x38:
440 return "TCH_ARFN";
441 case 0x39:
442 return "Clock output";
443 case 0x3A:
444 return "Transmitted power";
445 case 0x3B:
446 return "Clock sync";
447 case 0x3C:
448 return "TMS protocol discriminator";
449 case 0x3D:
450 return "TMS protocol data";
451 case 0x3E:
452 return "FER";
453 case 0x3F:
454 return "SWR result";
455 case 0x40:
456 return "Object identity";
457 case 0x41:
458 return "STM RX Antenna Test";
459 case 0x42:
460 return "reserved";
461 case 0x43:
462 return "reserved";
463 case 0x44:
464 return "Object current state";
465 case 0x45:
466 return "reserved";
467 case 0x46:
468 return "FU channel configuration";
469 case 0x47:
470 return "reserved";
471 case 0x48:
472 return "ARFN of a CU";
473 case 0x49:
474 return "FU radio definition";
475 case 0x4A:
476 return "reserved";
477 case 0x4B:
478 return "Severity";
479 case 0x4C:
480 return "Diversity selection";
481 case 0x4D:
482 return "RX antenna test";
483 case 0x4E:
484 return "RX antenna supervision period";
485 case 0x4F:
486 return "RX antenna state";
487 case 0x50:
488 return "Sector configuration";
489 case 0x51:
490 return "Additional info";
491 case 0x52:
492 return "SWR parameters";
493 case 0x53:
494 return "HW inquiry mode";
495 case 0x54:
496 return "reserved";
497 case 0x55:
498 return "Availability status";
499 case 0x56:
500 return "reserved";
501 case 0x57:
502 return "EAC inputs";
503 case 0x58:
504 return "EAC outputs";
505 case 0x59:
506 return "reserved";
507 case 0x5A:
508 return "Position";
509 case 0x5B:
510 return "HW unit identity";
511 case 0x5C:
512 return "RF test signal attenuation";
513 case 0x5D:
514 return "Operational state";
515 case 0x5E:
516 return "Logical object identity";
517 case 0x5F:
518 return "reserved";
519 case 0x60:
520 return "BS_TXPWR_OM";
521 case 0x61:
522 return "Loop_Duration";
523 case 0x62:
524 return "LNA_Path_Selection";
525 case 0x63:
526 return "Serial number";
527 case 0x64:
528 return "HW version";
529 case 0x65:
530 return "Obj. identity and obj. state";
531 case 0x66:
532 return "reserved";
533 case 0x67:
534 return "EAC input definition";
535 case 0x68:
536 return "EAC id and text";
537 case 0x69:
538 return "HW unit status";
539 case 0x6A:
540 return "SW release version";
541 case 0x6B:
542 return "FW version";
543 case 0x6C:
544 return "Bit_Error_Ratio";
545 case 0x6D:
546 return "RXLEV_with_Attenuation";
547 case 0x6E:
548 return "RXLEV_without_Attenuation";
549 case 0x6F:
550 return "reserved";
551 case 0x70:
552 return "CU_Results";
553 case 0x71:
554 return "reserved";
555 case 0x72:
556 return "LNA_Path_Results";
557 case 0x73:
558 return "RTE Results";
559 case 0x74:
560 return "Real Time";
561 case 0x75:
562 return "RX diversity selection";
563 case 0x76:
564 return "EAC input config";
565 case 0x77:
566 return "Feature support";
567 case 0x78:
568 return "File version";
569 case 0x79:
570 return "Outputs";
571 case 0x7A:
572 return "FU parameters";
573 case 0x7B:
574 return "Diagnostic info";
575 case 0x7C:
576 return "FU BSIC";
577 case 0x7D:
578 return "TRX Configuration";
579 case 0x7E:
580 return "Download status";
581 case 0x7F:
582 return "RX difference limit";
583 case 0x80:
584 return "TRX HW capability";
585 case 0x81:
586 return "Common HW config";
587 case 0x82:
588 return "Autoconfiguration pool size";
589 case 0x83:
590 return "TRE diagnostic info";
591 case 0x84:
592 return "TRE object identity";
593 case 0x85:
594 return "New TRE Info";
595 case 0x86:
596 return "Acknowledgement period";
597 case 0x87:
598 return "Synchronization mode";
599 case 0x88:
600 return "reserved";
601 case 0x89:
602 return "Block Control Data";
603 case 0x8A:
604 return "SW load mode";
605 case 0x8B:
606 return "Recommended recovery action";
607 case 0x8C:
608 return "BSC BCF id";
609 case 0x8D:
610 return "Q1 baud rate";
611 case 0x8E:
612 return "Allocation status";
613 case 0x8F:
614 return "Functional entity number";
615 case 0x90:
616 return "Transmission delay";
617 case 0x91:
618 return "Loop Duration ms";
619 case 0x92:
620 return "Logical channel";
621 case 0x93:
622 return "Q1 address";
623 case 0x94:
624 return "Alarm detail";
625 case 0x95:
626 return "Cabinet type";
627 case 0x96:
628 return "HW unit existence";
629 case 0x97:
630 return "RF power parameters";
631 case 0x98:
632 return "Message scenario";
633 case 0x99:
634 return "HW unit max amount";
635 case 0x9A:
636 return "Master TRX";
637 case 0x9B:
638 return "Transparent data";
639 case 0x9C:
640 return "BSC topology info";
641 case 0x9D:
642 return "Air i/f modulation";
643 case 0x9E:
644 return "LCS Q1 command data";
645 case 0x9F:
646 return "Frame number offset";
647 case 0xA0:
648 return "Abis TSL";
649 case 0xA1:
650 return "Dynamic pool info";
651 case 0xA2:
652 return "LCS LLP data";
653 case 0xA3:
654 return "LCS Q1 answer data";
655 case 0xA4:
656 return "DFCA FU Radio Definition";
657 case 0xA5:
658 return "Antenna hopping";
659 case 0xA6:
660 return "Field record sequence number";
661 case 0xA7:
662 return "Timeslot offslot";
663 case 0xA8:
664 return "EPCR capability";
665 case 0xA9:
666 return "Connectsite optional element";
667 case 0xAA:
668 return "TSC";
669 case 0xAB:
670 return "Special TX Power Setting";
671 case 0xAC:
672 return "Optional sync settings";
673 case 0xFA:
674 return "Abis If parameters";
675 default:
676 return "unknown";
677 }
Dieter Spaar16646022011-07-28 00:01:50 +0200678}
679
680static char *get_bts_type_string(uint8_t type)
681{
Harald Weltebda367c2011-07-28 00:03:49 +0200682 switch (type) {
683 case 0x0A:
684 return "MetroSite GSM 900";
685 case 0x0B:
686 return "MetroSite GSM 1800";
687 case 0x0C:
688 return "MetroSite GSM 1900 (PCS)";
689 case 0x0D:
690 return "MetroSite GSM 900 & 1800";
691 case 0x0E:
692 return "InSite GSM 900";
693 case 0x0F:
694 return "InSite GSM 1800";
695 case 0x10:
696 return "InSite GSM 1900";
697 case 0x11:
698 return "UltraSite GSM 900";
699 case 0x12:
700 return "UltraSite GSM 1800";
701 case 0x13:
702 return "UltraSite GSM/US-TDMA 1900";
703 case 0x14:
704 return "UltraSite GSM 900 & 1800";
705 case 0x16:
706 return "UltraSite GSM/US-TDMA 850";
707 case 0x18:
708 return "MetroSite GSM/US-TDMA 850";
709 case 0x19:
710 return "UltraSite GSM 800/1900";
711 default:
712 return "unknown";
713 }
Dieter Spaar16646022011-07-28 00:01:50 +0200714}
715
716static char *get_severity_string(uint8_t severity)
717{
Harald Weltebda367c2011-07-28 00:03:49 +0200718 switch (severity) {
719 case 0:
720 return "indeterminate";
721 case 1:
722 return "critical";
723 case 2:
724 return "major";
725 case 3:
726 return "minor";
727 case 4:
728 return "warning";
729 default:
730 return "unknown";
731 }
Dieter Spaar16646022011-07-28 00:01:50 +0200732}
733
734/* TODO: put in a separate file ? */
735
736/* some message IDs */
737
738#define NOKIA_MSG_CONF_DATA 128
739#define NOKIA_MSG_ACK 129
740#define NOKIA_MSG_OMU_STARTED 130
741#define NOKIA_MSG_START_DOWNLOAD_REQ 131
742#define NOKIA_MSG_MF_REQ 132
743#define NOKIA_MSG_RESET_REQ 134
744#define NOKIA_MSG_CONF_REQ 136
745#define NOKIA_MSG_CONF_COMPLETE 142
746#define NOKIA_MSG_BLOCK_CTRL_REQ 168
747#define NOKIA_MSG_STATE_CHANGED 172
748#define NOKIA_MSG_ALARM 174
749
750/* some element IDs */
751
752#define NOKIA_EI_BTS_TYPE 0x13
753#define NOKIA_EI_ACK 0x23
754#define NOKIA_EI_ADD_INFO 0x51
755#define NOKIA_EI_SEVERITY 0x4B
756#define NOKIA_EI_ALARM_DETAIL 0x94
757
758#define OM_ALLOC_SIZE 1024
759#define OM_HEADROOM_SIZE 128
760
Harald Weltebda367c2011-07-28 00:03:49 +0200761static uint8_t fu_config_template[] = {
762 0x7F, 0x7A, 0x39,
763 /* ID = 0x7A (FU parameters) ## constructed ## */
764 /* length = 57 */
765 /* [3] */
Dieter Spaar16646022011-07-28 00:01:50 +0200766
Harald Weltebda367c2011-07-28 00:03:49 +0200767 0x5F, 0x40, 0x04,
768 /* ID = 0x40 (Object identity) */
769 /* length = 4 */
770 /* [6] */
771 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200772
Harald Weltebda367c2011-07-28 00:03:49 +0200773 0x41, 0x02,
774 /* ID = 0x01 (Ny1) */
775 /* length = 2 */
776 /* [12] */
777 0x00, 0x05,
Dieter Spaar16646022011-07-28 00:01:50 +0200778
Harald Weltebda367c2011-07-28 00:03:49 +0200779 0x42, 0x02,
780 /* ID = 0x02 (T3105_F) */
781 /* length = 2 */
782 /* [16] */
783 0x00, 0x28,
Dieter Spaar16646022011-07-28 00:01:50 +0200784
Harald Weltebda367c2011-07-28 00:03:49 +0200785 0x50, 0x02,
786 /* ID = 0x10 (T3105_D) */
787 /* length = 2 */
788 /* [20] */
789 0x00, 0x28,
Dieter Spaar16646022011-07-28 00:01:50 +0200790
Harald Weltebda367c2011-07-28 00:03:49 +0200791 0x43, 0x05,
792 /* ID = 0x03 (Interference band limits) */
793 /* length = 5 */
794 /* [24] */
795 0x0F, 0x1B, 0x27, 0x33, 0x3F,
Dieter Spaar16646022011-07-28 00:01:50 +0200796
Harald Weltebda367c2011-07-28 00:03:49 +0200797 0x44, 0x02,
798 /* ID = 0x04 (Interference report timer in secs) */
799 /* length = 2 */
800 /* [31] */
801 0x00, 0x10,
Dieter Spaar16646022011-07-28 00:01:50 +0200802
Harald Weltebda367c2011-07-28 00:03:49 +0200803 0x47, 0x01,
804 /* ID = 0x07 (RACH report timer in secs) */
805 /* length = 1 */
806 /* [35] */
807 0x1E,
Dieter Spaar16646022011-07-28 00:01:50 +0200808
Harald Weltebda367c2011-07-28 00:03:49 +0200809 0x4C, 0x10,
810 /* ID = 0x0C (Cell allocation bitmap) ####### */
811 /* length = 16 */
812 /* [38] */
813 0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
814 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200815
Harald Weltebda367c2011-07-28 00:03:49 +0200816 0x59, 0x01,
817 /* ID = 0x19 (Averaging period) */
818 /* length = 1 */
819 /* [56] */
820 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +0200821
Harald Weltebda367c2011-07-28 00:03:49 +0200822 0x5E, 0x01,
823 /* ID = 0x1E ((RF max power reduction)) */
824 /* length = 1 */
825 /* [59] */
826 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200827
Harald Weltebda367c2011-07-28 00:03:49 +0200828 0x7F, 0x46, 0x11,
829 /* ID = 0x46 (FU channel configuration) ## constructed ## */
830 /* length = 17 */
831 /* [63] */
Dieter Spaar16646022011-07-28 00:01:50 +0200832
Harald Weltebda367c2011-07-28 00:03:49 +0200833 0x5F, 0x40, 0x04,
834 /* ID = 0x40 (Object identity) */
835 /* length = 4 */
836 /* [66] */
837 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200838
Harald Weltebda367c2011-07-28 00:03:49 +0200839 0x45, 0x08,
840 /* ID = 0x05 (Channel configuration per TS) */
841 /* length = 8 */
842 /* [72] */
843 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
Dieter Spaar16646022011-07-28 00:01:50 +0200844
Harald Weltebda367c2011-07-28 00:03:49 +0200845 0x7F, 0x65, 0x0B,
846 /* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */
847 /* length = 11 */
848 /* [83] */
Dieter Spaar16646022011-07-28 00:01:50 +0200849
Harald Weltebda367c2011-07-28 00:03:49 +0200850 0x5F, 0x40, 0x04,
851 /* ID = 0x40 (Object identity) */
852 /* length = 4 */
853 /* [86] */
854 0x00, 0x04, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200855
Harald Weltebda367c2011-07-28 00:03:49 +0200856 0x5F, 0x44, 0x01,
857 /* ID = 0x44 (Object current state) */
858 /* length = 1 */
859 /* [93] */
860 0x03,
Dieter Spaar16646022011-07-28 00:01:50 +0200861
Harald Weltebda367c2011-07-28 00:03:49 +0200862 0x7F, 0x7C, 0x0A,
863 /* ID = 0x7C (FU BSIC) ## constructed ## */
864 /* length = 10 */
865 /* [97] */
Dieter Spaar16646022011-07-28 00:01:50 +0200866
Harald Weltebda367c2011-07-28 00:03:49 +0200867 0x5F, 0x40, 0x04,
868 /* ID = 0x40 (Object identity) */
869 /* length = 4 */
870 /* [100] */
871 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200872
Harald Weltebda367c2011-07-28 00:03:49 +0200873 0x46, 0x01,
874 /* ID = 0x06 (BSIC) */
875 /* length = 1 */
876 /* [106] */
877 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200878
Harald Weltebda367c2011-07-28 00:03:49 +0200879 0x7F, 0x48, 0x0B,
880 /* ID = 0x48 (ARFN of a CU) ## constructed ## */
881 /* length = 11 */
882 /* [110] */
Dieter Spaar16646022011-07-28 00:01:50 +0200883
Harald Weltebda367c2011-07-28 00:03:49 +0200884 0x5F, 0x40, 0x04,
885 /* ID = 0x40 (Object identity) */
886 /* length = 4 */
887 /* [113] */
888 0x00, 0x08, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200889
Harald Weltebda367c2011-07-28 00:03:49 +0200890 0x4A, 0x02,
891 /* ID = 0x0A (ARFN) ####### */
892 /* length = 2 */
893 /* [119] */
894 0x03, 0x62,
Dieter Spaar16646022011-07-28 00:01:50 +0200895
Harald Weltebda367c2011-07-28 00:03:49 +0200896 0x7F, 0x49, 0x59,
897 /* ID = 0x49 (FU radio definition) ## constructed ## */
898 /* length = 89 */
899 /* [124] */
Dieter Spaar16646022011-07-28 00:01:50 +0200900
Harald Weltebda367c2011-07-28 00:03:49 +0200901 0x5F, 0x40, 0x04,
902 /* ID = 0x40 (Object identity) */
903 /* length = 4 */
904 /* [127] */
905 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200906
Harald Weltebda367c2011-07-28 00:03:49 +0200907 0x4D, 0x50,
908 /* ID = 0x0D (Radio definition per TS) ####### */
909 /* length = 80 */
910 /* [133] */
911 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MA */
912 0x03, 0x62, /* HSN, MAIO or ARFCN if no hopping */
913 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
914 0x03, 0x62,
915 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
916 0x03, 0x62,
917 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
918 0x03, 0x62,
919 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
920 0x03, 0x62,
921 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
922 0x03, 0x62,
923 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
924 0x03, 0x62,
925 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
926 0x03, 0x62,
Dieter Spaar16646022011-07-28 00:01:50 +0200927};
928
929/* TODO: put in a separate file ? */
930
931/*
932 build the configuration for each TRX
933*/
934
Harald Weltebda367c2011-07-28 00:03:49 +0200935static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id,
936 uint8_t * fu_config, int *hopping)
Dieter Spaar16646022011-07-28 00:01:50 +0200937{
Harald Weltebda367c2011-07-28 00:03:49 +0200938 int i;
Dieter Spaar16646022011-07-28 00:01:50 +0200939
Harald Weltebda367c2011-07-28 00:03:49 +0200940 *hopping = 0;
941
942 memcpy(fu_config, fu_config_template, sizeof(fu_config_template));
943
944 /* set ID */
945
946 fu_config[6 + 2] = id;
947 fu_config[66 + 2] = id;
948 fu_config[86 + 2] = id;
949 fu_config[100 + 2] = id;
950 fu_config[113 + 2] = id;
951 fu_config[127 + 2] = id;
952
953 /* set ARFCN */
954
955 uint16_t arfcn = trx->arfcn;
956
957 fu_config[119] = arfcn >> 8;
958 fu_config[119 + 1] = arfcn & 0xFF;
959
960 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
961 struct gsm_bts_trx_ts *ts = &trx->ts[i];
962
963 if (ts->hopping.enabled) {
964 /* reverse order */
965 int j;
966 for (j = 0; j < ts->hopping.ma_len; j++)
967 fu_config[133 + (i * 10) + (7 - j)] =
968 ts->hopping.ma_data[j];
969 fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn;
970 fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio;
971 *hopping = 1;
972 } else {
973 fu_config[133 + 8 + (i * 10)] = arfcn >> 8;
974 fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF;
975 }
976 }
977
978 /* set BSIC */
979
980 /*
981 Attention: all TRX except the first one seem to get the TSC
982 from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION,
983 GSM 04.08 CHANNEL DESCRIPTION).
984 There was a bug in rsl_chan_activate_lchan() setting this parameter.
985 */
986
987 uint8_t bsic = trx->bts->bsic;
988
989 fu_config[106] = bsic;
990
991 /* set CA */
992
993 if (generate_cell_chan_list(&fu_config[38], trx->bts) != 0) {
994 fprintf(stderr, "generate_cell_chan_list failed\n");
995 return 0;
996 }
997
998 /* set channel configuration */
999
1000 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
1001 struct gsm_bts_trx_ts *ts = &trx->ts[i];
1002 uint8_t chan_config;
1003
1004 /*
1005 0 = FCCH + SCH + BCCH + CCCH
1006 1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4
1007 2 = BCCH + CCCH (This combination is not used in any BTS)
1008 3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH
1009 4 = SDCCH/8 + SACCH/8
1010 5 = SDCCH/8 with SDCCH2 used as CBCH
1011 6 = TCH/F + FACCH/F + SACCH/F
1012 7 = E-RACH (Talk family)
1013 9 = Dual rate (capability for TCH/F and TCH/H)
1014 10 = reserved for BTS internal use
1015 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (This channel configuration type can be used in GPRS release 2).
1016 0xFF = spare TS
1017 */
1018
1019 if (ts->pchan == GSM_PCHAN_NONE)
1020 chan_config = 0xFF;
1021 else if (ts->pchan == GSM_PCHAN_CCCH)
1022 chan_config = 0;
1023 else if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4)
1024 chan_config = 1;
1025 else if (ts->pchan == GSM_PCHAN_TCH_F)
1026 chan_config = 6; /* 9 should work too */
1027 else if (ts->pchan == GSM_PCHAN_TCH_H)
1028 chan_config = 9;
1029 else if (ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C)
1030 chan_config = 4;
1031 else if (ts->pchan == GSM_PCHAN_PDCH)
1032 chan_config = 11;
1033 else {
1034 fprintf(stderr,
1035 "unsupported channel config %d for timeslot %d\n",
1036 ts->pchan, i);
1037 return 0;
1038 }
1039
1040 fu_config[72 + i] = chan_config;
1041 }
1042 return sizeof(fu_config_template);
Dieter Spaar16646022011-07-28 00:01:50 +02001043}
1044
1045/* TODO: put in a separate file ? */
1046
Harald Weltebda367c2011-07-28 00:03:49 +02001047static uint8_t bts_config_1[] = {
1048 0x4E, 0x02,
1049 /* ID = 0x0E (Frame number) */
1050 /* length = 2 */
1051 /* [2] */
1052 0xFF, 0xFF,
1053
1054 0x5F, 0x4E, 0x02,
1055 /* ID = 0x4E (RX antenna supervision period) */
1056 /* length = 2 */
1057 /* [7] */
1058 0xFF, 0xFF,
1059
1060 0x5F, 0x50, 0x02,
1061 /* ID = 0x50 (Sector configuration) */
1062 /* length = 2 */
1063 /* [12] */
1064 0x01, 0x01,
1065};
1066
1067static uint8_t bts_config_2[] = {
1068 0x55, 0x02,
1069 /* ID = 0x15 (Hopping mode) */
1070 /* length = 2 */
1071 /* [2] */
1072 0x01, 0x00,
1073
1074 0x5F, 0x75, 0x02,
1075 /* ID = 0x75 (RX diversity selection) */
1076 /* length = 2 */
1077 /* [7] */
1078 0x01, 0x01,
1079};
1080
1081static uint8_t bts_config_3[] = {
1082 0x5F, 0x20, 0x02,
1083 /* ID = 0x20 (Extended cell radius) */
1084 /* length = 2 */
1085 /* [3] */
1086 0x01, 0x00,
1087};
1088
1089static uint8_t bts_config_4[] = {
1090 0x5F, 0x74, 0x09,
1091 /* ID = 0x74 (Real Time) */
1092 /* length = 9 */
1093 /* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
1094 0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00,
1095 0x00,
1096
1097 0x5F, 0x76, 0x03,
1098 /* ID = 0x76 (EAC input config) */
1099 /* length = 3 */
1100 /* [15] */
1101 0x01, 0x01, 0x00,
1102
1103 0x5F, 0x76, 0x03,
1104 /* ID = 0x76 (EAC input config) */
1105 /* length = 3 */
1106 /* [21] */
1107 0x02, 0x01, 0x00,
1108
1109 0x5F, 0x76, 0x03,
1110 /* ID = 0x76 (EAC input config) */
1111 /* length = 3 */
1112 /* [27] */
1113 0x03, 0x01, 0x00,
1114
1115 0x5F, 0x76, 0x03,
1116 /* ID = 0x76 (EAC input config) */
1117 /* length = 3 */
1118 /* [33] */
1119 0x04, 0x01, 0x00,
1120
1121 0x5F, 0x76, 0x03,
1122 /* ID = 0x76 (EAC input config) */
1123 /* length = 3 */
1124 /* [39] */
1125 0x05, 0x01, 0x00,
1126
1127 0x5F, 0x76, 0x03,
1128 /* ID = 0x76 (EAC input config) */
1129 /* length = 3 */
1130 /* [45] */
1131 0x06, 0x01, 0x00,
1132
1133 0x5F, 0x76, 0x03,
1134 /* ID = 0x76 (EAC input config) */
1135 /* length = 3 */
1136 /* [51] */
1137 0x07, 0x01, 0x00,
1138
1139 0x5F, 0x76, 0x03,
1140 /* ID = 0x76 (EAC input config) */
1141 /* length = 3 */
1142 /* [57] */
1143 0x08, 0x01, 0x00,
1144
1145 0x5F, 0x76, 0x03,
1146 /* ID = 0x76 (EAC input config) */
1147 /* length = 3 */
1148 /* [63] */
1149 0x09, 0x01, 0x00,
1150
1151 0x5F, 0x76, 0x03,
1152 /* ID = 0x76 (EAC input config) */
1153 /* length = 3 */
1154 /* [69] */
1155 0x0A, 0x01, 0x00,
1156};
1157
1158static uint8_t bts_config_insite[] = {
1159 0x4E, 0x02,
1160 /* ID = 0x0E (Frame number) */
1161 /* length = 2 */
1162 /* [2] */
1163 0xFF, 0xFF,
1164
1165 0x5F, 0x4E, 0x02,
1166 /* ID = 0x4E (RX antenna supervision period) */
1167 /* length = 2 */
1168 /* [7] */
1169 0xFF, 0xFF,
1170
1171 0x5F, 0x50, 0x02,
1172 /* ID = 0x50 (Sector configuration) */
1173 /* length = 2 */
1174 /* [12] */
1175 0x01, 0x01,
1176
1177 0x55, 0x02,
1178 /* ID = 0x15 (Hopping mode) */
1179 /* length = 2 */
1180 /* [16] */
1181 0x01, 0x00,
1182
1183 0x5F, 0x20, 0x02,
1184 /* ID = 0x20 (Extended cell radius) */
1185 /* length = 2 */
1186 /* [21] */
1187 0x01, 0x00,
1188
1189 0x5F, 0x74, 0x09,
1190 /* ID = 0x74 (Real Time) */
1191 /* length = 9 */
1192 /* [26] */
1193 0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00,
1194 0x00,
1195};
1196
1197void set_real_time(uint8_t * real_time)
Dieter Spaar16646022011-07-28 00:01:50 +02001198{
Harald Weltebda367c2011-07-28 00:03:49 +02001199 time_t t;
1200 struct tm *tm;
Dieter Spaar16646022011-07-28 00:01:50 +02001201
Harald Weltebda367c2011-07-28 00:03:49 +02001202 t = time(NULL);
1203 tm = localtime(&t);
Dieter Spaar16646022011-07-28 00:01:50 +02001204
Harald Weltebda367c2011-07-28 00:03:49 +02001205 /* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
Dieter Spaar16646022011-07-28 00:01:50 +02001206
Harald Weltebda367c2011-07-28 00:03:49 +02001207 real_time[0] = (1900 + tm->tm_year) >> 8;
1208 real_time[1] = (1900 + tm->tm_year) & 0xFF;
1209 real_time[2] = tm->tm_mon + 1;
1210 real_time[3] = tm->tm_mday;
1211 real_time[4] = tm->tm_hour;
1212 real_time[5] = tm->tm_min;
1213 real_time[6] = tm->tm_sec;
1214 real_time[7] = 0;
1215 real_time[8] = 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001216}
1217
1218/* TODO: put in a separate file ? */
1219
1220/*
1221
1222 build the configuration data
1223
1224*/
1225
Harald Weltebda367c2011-07-28 00:03:49 +02001226static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config,
1227 int need_hopping)
Dieter Spaar16646022011-07-28 00:01:50 +02001228{
Harald Weltebda367c2011-07-28 00:03:49 +02001229 /* is it an InSite BTS ? */
1230 if (bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */
1231 if (n_trx != 1) {
1232 fprintf(stderr, "InSite has only one TRX\n");
1233 return 0;
1234 }
1235 if (need_hopping != 0) {
1236 fprintf(stderr, "InSite does not support hopping\n");
1237 return 0;
1238 }
1239 memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite));
1240 set_real_time(&fu_config[26]);
1241 return sizeof(bts_config_insite);
1242 }
Dieter Spaar16646022011-07-28 00:01:50 +02001243
Harald Weltebda367c2011-07-28 00:03:49 +02001244 int len = 0;
1245 int i;
1246
1247 memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1));
1248
1249 /* set sector configuration */
1250 fu_config[len + 12 - 1] = 1 + n_trx; /* len */
1251 for (i = 0; i < n_trx; i++)
1252 fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF);
1253
1254 len += (sizeof(bts_config_1) + (n_trx - 1));
1255
1256 memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2));
1257 /* set hopping mode (Baseband and RF hopping work for the MetroSite) */
1258 if (need_hopping)
1259 fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */
1260 len += sizeof(bts_config_2);
1261
1262 /* set extended cell radius for each TRX */
1263 for (i = 0; i < n_trx; i++) {
1264 memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3));
1265 fu_config[len + 3] = ((i + 1) & 0xFF);
1266 len += sizeof(bts_config_3);
1267 }
1268
1269 memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4));
1270 set_real_time(&fu_config[len + 3]);
1271 len += sizeof(bts_config_4);
1272
1273 return len;
Dieter Spaar16646022011-07-28 00:01:50 +02001274}
1275
1276/* TODO: put in a separate file ? */
1277
1278static struct msgb *nm_msgb_alloc(void)
1279{
Harald Weltebda367c2011-07-28 00:03:49 +02001280 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
Dieter Spaar16646022011-07-28 00:01:50 +02001281}
1282
1283/* TODO: put in a separate file ? */
1284
1285struct abis_om_nokia_hdr {
Harald Weltebda367c2011-07-28 00:03:49 +02001286 uint8_t msg_type;
1287 uint8_t spare;
1288 uint16_t reference;
1289 uint8_t data[0];
Dieter Spaar16646022011-07-28 00:01:50 +02001290} __attribute__ ((packed));
1291
1292#define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr))
1293
Harald Weltebda367c2011-07-28 00:03:49 +02001294static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref,
1295 uint8_t * data, int len_data)
Dieter Spaar16646022011-07-28 00:01:50 +02001296{
Harald Weltebda367c2011-07-28 00:03:49 +02001297 struct abis_om_hdr *oh;
1298 struct abis_om_nokia_hdr *noh;
1299 struct msgb *msg = nm_msgb_alloc();
Dieter Spaar16646022011-07-28 00:01:50 +02001300
Harald Weltebda367c2011-07-28 00:03:49 +02001301 oh = (struct abis_om_hdr *)msgb_put(msg,
1302 ABIS_OM_NOKIA_HDR_SIZE + len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001303
Harald Weltebda367c2011-07-28 00:03:49 +02001304 oh->mdisc = ABIS_OM_MDISC_FOM;
1305 oh->placement = ABIS_OM_PLACEMENT_ONLY;
1306 oh->sequence = 0;
1307 oh->length = sizeof(struct abis_om_nokia_hdr) + len_data;
1308
1309 noh = (struct abis_om_nokia_hdr *)oh->data;
1310
1311 noh->msg_type = msg_type;
1312 noh->spare = 0;
1313 noh->reference = htons(ref);
1314 memcpy(noh->data, data, len_data);
1315
1316 DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type));
1317
1318 return abis_nm_sendmsg(bts, msg);
Dieter Spaar16646022011-07-28 00:01:50 +02001319}
1320
1321/* TODO: put in a separate file ? */
1322
1323static uint8_t download_req[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001324 0x5F, 0x25, 0x0B,
1325 /* ID = 0x25 (File identity) */
1326 /* length = 11 */
1327 /* [3] */
1328 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
1329 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001330
Harald Weltebda367c2011-07-28 00:03:49 +02001331 0x5F, 0x78, 0x03,
1332 /* ID = 0x78 (File version) */
1333 /* length = 3 */
1334 /* [17] */
1335 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001336
Harald Weltebda367c2011-07-28 00:03:49 +02001337 0x5F, 0x81, 0x0A, 0x01,
1338 /* ID = 0x8A (SW load mode) */
1339 /* length = 1 */
1340 /* [24] */
1341 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001342
Harald Weltebda367c2011-07-28 00:03:49 +02001343 0x5F, 0x81, 0x06, 0x01,
1344 /* ID = 0x86 (Acknowledgement period) */
1345 /* length = 1 */
1346 /* [29] */
1347 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001348};
1349
1350static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref)
1351{
Harald Weltebda367c2011-07-28 00:03:49 +02001352 uint8_t *data = download_req;
1353 int len_data = sizeof(download_req);
1354
1355 return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data,
1356 len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001357}
1358
1359/* TODO: put in a separate file ? */
1360
1361static uint8_t ack[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001362 0x5F, 0x23, 0x01,
1363 /* ID = 0x23 (Ack-Nack) */
1364 /* length = 1 */
1365 /* [3] */
1366 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001367};
1368
1369static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref)
1370{
Harald Weltebda367c2011-07-28 00:03:49 +02001371 uint8_t *data = ack;
1372 int len_data = sizeof(ack);
1373
1374 return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001375}
1376
1377/* TODO: put in a separate file ? */
1378
1379static uint8_t reset[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001380 0x5F, 0x40, 0x04,
1381 /* ID = 0x40 (Object identity) */
1382 /* length = 4 */
1383 /* [3] */
1384 0x00, 0x01, 0xFF, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +02001385};
1386
1387static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref)
1388{
Harald Weltebda367c2011-07-28 00:03:49 +02001389 uint8_t *data = reset;
1390 int len_data = sizeof(reset);
1391
1392 return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001393}
1394
1395/* TODO: put in a separate file ? */
1396
Harald Weltebda367c2011-07-28 00:03:49 +02001397static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type,
1398 uint16_t ref, uint8_t * data, int len)
Dieter Spaar16646022011-07-28 00:01:50 +02001399{
Harald Weltebda367c2011-07-28 00:03:49 +02001400 int len_remain, len_to_send, max_send;
1401 int seq = 0;
1402 int ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001403
Harald Weltebda367c2011-07-28 00:03:49 +02001404 len_remain = len;
1405
1406 while (len_remain) {
1407 struct abis_om_hdr *oh;
1408 struct abis_om_nokia_hdr *noh;
1409 struct msgb *msg = nm_msgb_alloc();
1410
1411 if (seq == 0)
1412 max_send = 256 - sizeof(struct abis_om_nokia_hdr);
1413 else
1414 max_send = 256;
1415
1416 if (len_remain > max_send) {
1417 len_to_send = max_send;
1418
1419 if (seq == 0) {
1420 /* first segment */
1421 oh = (struct abis_om_hdr *)msgb_put(msg,
1422 ABIS_OM_NOKIA_HDR_SIZE
1423 +
1424 len_to_send);
1425
1426 oh->mdisc = ABIS_OM_MDISC_FOM;
1427 oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */
1428 oh->sequence = seq;
1429 oh->length = 0; /* 256 bytes */
1430
1431 noh = (struct abis_om_nokia_hdr *)oh->data;
1432
1433 noh->msg_type = msg_type;
1434 noh->spare = 0;
1435 noh->reference = htons(ref);
1436 memcpy(noh->data, data, len_to_send);
1437 } else {
1438 /* segment in between */
1439 oh = (struct abis_om_hdr *)msgb_put(msg,
1440 sizeof
1441 (struct
1442 abis_om_hdr)
1443 +
1444 len_to_send);
1445
1446 oh->mdisc = ABIS_OM_MDISC_FOM;
1447 oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */
1448 oh->sequence = seq;
1449 oh->length = 0; /* 256 bytes */
1450
1451 memcpy(oh->data, data, len_to_send);
1452 }
1453 } else {
1454
1455 len_to_send = len_remain;
1456
1457 /* check if message fits in a single segment */
1458
1459 if (seq == 0)
1460 return abis_nm_send(bts, msg_type, ref, data,
1461 len_to_send);
1462
1463 /* last segment */
1464
1465 oh = (struct abis_om_hdr *)msgb_put(msg,
1466 sizeof(struct
1467 abis_om_hdr)
1468 + len_to_send);
1469
1470 oh->mdisc = ABIS_OM_MDISC_FOM;
1471 oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */
1472 oh->sequence = seq;
1473 oh->length = len_to_send;
1474
1475 memcpy(oh->data, data, len_to_send);
1476 }
1477
1478 DEBUGPC(DNM, "Sending multi-segment %d\n", seq);
1479
1480 ret = abis_nm_sendmsg(bts, msg);
1481 if (ret < 0)
1482 return ret;
1483
1484 abis_nm_queue_send_next(bts);
1485
1486 /* next segment */
1487 len_remain -= len_to_send;
1488 data += len_to_send;
1489 seq++;
1490 }
1491 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001492}
1493
1494/* TODO: put in a separate file ? */
1495
1496static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type)
1497{
Harald Weltebda367c2011-07-28 00:03:49 +02001498 struct gsm_bts_trx *trx;
1499 uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */
1500 int len = 0;
1501 int idx = 0;
1502 int ret;
1503 int hopping = 0;
1504 int need_hopping = 0;
1505
1506 memset(config, 0, sizeof(config));
1507
1508 llist_for_each_entry(trx, &bts->trx_list, list) {
1509#if 0 /* debugging */
1510 printf("TRX\n");
1511 printf(" arfcn: %d\n", trx->arfcn);
1512 printf(" bsic: %d\n", trx->bts->bsic);
1513 uint8_t ca[20];
1514 memset(ca, 0xFF, sizeof(ca));
1515 ret = generate_cell_chan_list(ca, trx->bts);
1516 printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca)));
1517 int i;
1518 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
1519 struct gsm_bts_trx_ts *ts = &trx->ts[i];
1520
1521 printf(" pchan %d: %d\n", i, ts->pchan);
1522 }
Dieter Spaar16646022011-07-28 00:01:50 +02001523#endif
Harald Weltebda367c2011-07-28 00:03:49 +02001524 ret = make_fu_config(trx, idx + 1, config + len, &hopping);
1525 need_hopping |= hopping;
1526 len += ret;
1527
1528 idx++;
1529 }
1530
1531 ret = make_bts_config(bts_type, idx, config + len, need_hopping);
1532 len += ret;
1533
1534#if 0 /* debugging */
1535 dump_elements(config, len);
1536#endif
1537
1538 return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config,
1539 len);
Dieter Spaar16646022011-07-28 00:01:50 +02001540}
1541
1542#define GET_NEXT_BYTE if(idx >= len) return 0; \
Harald Weltebda367c2011-07-28 00:03:49 +02001543 ub = data[idx++];
Dieter Spaar16646022011-07-28 00:01:50 +02001544
Harald Weltebda367c2011-07-28 00:03:49 +02001545static int find_element(uint8_t * data, int len, uint16_t id, uint8_t * value,
1546 int max_value)
1547{
1548 uint8_t ub;
1549 int idx = 0;
1550 int found = 0;
1551 int constructed;
1552 uint16_t id_value;
1553
1554 for (;;) {
1555
1556 GET_NEXT_BYTE;
1557
1558 /* encoding bit, construced means that other elements are contained */
1559 constructed = ((ub & 0x20) ? 1 : 0);
1560
1561 if ((ub & 0x1F) == 0x1F) {
1562 /* fixed pattern, ID follows */
1563 GET_NEXT_BYTE; /* ID */
1564 id_value = ub & 0x7F;
1565 if (ub & 0x80) {
1566 /* extension bit */
1567 GET_NEXT_BYTE; /* ID low part */
1568 id_value = (id_value << 7) | (ub & 0x7F);
1569 }
1570 if (id_value == id)
1571 found = 1;
1572 } else {
1573 id_value = (ub & 0x3F);
1574 if (id_value == id)
1575 found = 1;
1576 }
1577
1578 GET_NEXT_BYTE; /* length */
1579
1580 if (found) {
1581 /* get data */
1582 uint8_t n = ub;
1583 uint8_t i;
1584 for (i = 0; i < n; i++) {
1585 GET_NEXT_BYTE;
1586 if (max_value <= 0)
1587 return -1; /* buffer too small */
1588 *value = ub;
1589 value++;
1590 max_value--;
1591 }
1592 return n; /* length */
1593 } else {
1594 /* skip data */
1595 uint8_t n = ub;
1596 uint8_t i;
1597 for (i = 0; i < n; i++) {
1598 GET_NEXT_BYTE;
1599 }
1600 }
1601 }
1602 return 0; /* not found */
Dieter Spaar16646022011-07-28 00:01:50 +02001603}
1604
Harald Weltebda367c2011-07-28 00:03:49 +02001605static int dump_elements(uint8_t * data, int len)
1606{
1607 uint8_t ub;
1608 int idx = 0;
1609 int constructed;
1610 uint16_t id_value;
1611 static char indent[100] = ""; /* TODO: move static to BTS context */
Dieter Spaar16646022011-07-28 00:01:50 +02001612
Harald Weltebda367c2011-07-28 00:03:49 +02001613 for (;;) {
1614
1615 GET_NEXT_BYTE;
1616
1617 /* encoding bit, construced means that other elements are contained */
1618 constructed = ((ub & 0x20) ? 1 : 0);
1619
1620 if ((ub & 0x1F) == 0x1F) {
1621 /* fixed pattern, ID follows */
1622 GET_NEXT_BYTE; /* ID */
1623 id_value = ub & 0x7F;
1624 if (ub & 0x80) {
1625 /* extension bit */
1626 GET_NEXT_BYTE; /* ID low part */
1627 id_value = (id_value << 7) | (ub & 0x7F);
1628 }
1629
1630 } else {
1631 id_value = (ub & 0x3F);
1632 }
1633
1634 GET_NEXT_BYTE; /* length */
1635
1636 printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value,
1637 get_element_name_string(id_value),
1638 constructed ? "** constructed **" : "");
1639 printf("%s length = %d\n", indent, ub);
1640 printf("%s %s\n", indent, osmo_hexdump(data + idx, ub));
1641
1642 if (constructed) {
1643 int indent_len = strlen(indent);
1644 strcat(indent, " ");
1645
1646 dump_elements(data + idx, ub);
1647
1648 indent[indent_len] = 0;
1649 }
1650 /* skip data */
1651 uint8_t n = ub;
1652 uint8_t i;
1653 for (i = 0; i < n; i++) {
1654 GET_NEXT_BYTE;
1655 }
1656 }
1657 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001658}
1659
1660/* TODO: put in a separate file ? */
1661
1662/* taken from abis_nm.c */
1663
1664static void abis_nm_queue_send_next(struct gsm_bts *bts)
1665{
Harald Weltebda367c2011-07-28 00:03:49 +02001666 int wait = 0;
1667 struct msgb *msg;
1668 /* the queue is empty */
1669 while (!llist_empty(&bts->abis_queue)) {
1670 msg = msgb_dequeue(&bts->abis_queue);
1671 wait = OBSC_NM_W_ACK_CB(msg);
1672 _abis_nm_sendmsg(msg, 0);
Dieter Spaar16646022011-07-28 00:01:50 +02001673
Harald Weltebda367c2011-07-28 00:03:49 +02001674 if (wait)
1675 break;
1676 }
Dieter Spaar16646022011-07-28 00:01:50 +02001677
Harald Weltebda367c2011-07-28 00:03:49 +02001678 bts->abis_nm_pend = wait;
Dieter Spaar16646022011-07-28 00:01:50 +02001679}
1680
1681/* TODO: put in a separate file ? */
1682
1683/* timer for restarting OML after BTS reset */
1684
1685static void reset_timer_cb(void *_bts)
1686{
Harald Weltebda367c2011-07-28 00:03:49 +02001687 struct gsm_bts *bts = _bts;
1688 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1689 struct e1inp_line *line;
1690
1691 wait_reset = 0;
1692
1693 /* OML link */
1694 line = e1inp_line_get(e1_link->e1_nr);
1695 if (!line) {
1696 LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to "
1697 "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
1698 return;
1699 }
1700
1701 start_sabm_in_line(line, 0, -1); /* stop all first */
1702 start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */
Dieter Spaar16646022011-07-28 00:01:50 +02001703}
1704
1705/* TODO: put in a separate file ? */
1706
1707/*
1708 This is how the configuration is done:
1709
1710 - start OML link
1711
1712 - reset BTS
1713
1714 - receive ACK, wait some time and restart OML link
1715
1716 - receive OMU STARTED message, send START DOWNLOAD REQ
1717
1718 - receive CNF REQ message, send CONF DATA
1719
1720 - receive ACK, start RSL link(s)
1721
1722 ACK some other messages received from the BTS.
1723
1724 Probably its also possible to configure the BTS without a reset, this
1725 has not been tested yet.
1726*/
1727
1728static int abis_nm_rcvmsg_fom(struct msgb *mb)
1729{
Harald Weltebda367c2011-07-28 00:03:49 +02001730 struct gsm_bts *bts = mb->trx->bts;
1731 struct abis_om_hdr *oh = msgb_l2(mb);
1732 struct abis_om_nokia_hdr *noh = msgb_l3(mb);
1733 uint8_t mt = noh->msg_type;
1734 int ret = 0;
1735 uint16_t ref = ntohs(noh->reference);
1736 /* TODO: move statics to BTS context */
1737 static int conf = 0;
1738 static uint8_t bts_type = 0xFF;
1739 uint8_t info[256];
1740 uint8_t ack = 0xFF;
1741 uint8_t severity = 0xFF;
1742 int str_len;
1743 int len_data;
Dieter Spaar16646022011-07-28 00:01:50 +02001744
Harald Weltebda367c2011-07-28 00:03:49 +02001745 if (wait_reset) {
1746 LOGP(DNM, LOGL_INFO,
1747 "Ignore message while waiting for reset\n");
1748 return ret;
1749 }
Dieter Spaar16646022011-07-28 00:01:50 +02001750
Harald Weltebda367c2011-07-28 00:03:49 +02001751 if (oh->length < sizeof(struct abis_om_nokia_hdr)) {
1752 LOGP(DNM, LOGL_ERROR, "Message too short\n");
1753 return -EINVAL;
1754 }
1755
1756 len_data = oh->length - sizeof(struct abis_om_nokia_hdr);
1757 LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt));
1758#if 0 /* debugging */
1759 dump_elements(noh->data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001760#endif
Dieter Spaar16646022011-07-28 00:01:50 +02001761
Harald Weltebda367c2011-07-28 00:03:49 +02001762 switch (mt) {
1763 case NOKIA_MSG_OMU_STARTED:
1764 if (find_element
1765 (noh->data, len_data, NOKIA_EI_BTS_TYPE, &bts_type,
1766 sizeof(uint8_t)) == sizeof(uint8_t))
1767 LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n", bts_type,
1768 get_bts_type_string(bts_type));
1769 else
1770 LOGP(DNM, LOGL_ERROR, "BTS type not found\n");
1771 /* send START_DOWNLOAD_REQ */
1772 abis_nm_download_req(bts, ref);
1773 break;
1774 case NOKIA_MSG_MF_REQ:
1775 break;
1776 case NOKIA_MSG_CONF_REQ:
1777 /* send ACK */
1778 abis_nm_ack(bts, ref);
1779 abis_nm_queue_send_next(bts);
1780 /* send CONF_DATA */
1781 abis_nm_send_config(bts, bts_type);
1782 conf = 1;
1783 break;
1784 case NOKIA_MSG_ACK:
1785 if (find_element
1786 (noh->data, len_data, NOKIA_EI_ACK, &ack,
1787 sizeof(uint8_t)) == sizeof(uint8_t)) {
1788 LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack);
1789 if (ack != 1) {
1790 LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n",
1791 ack);
1792 /* TODO: properly handle failures (NACK) */
1793 }
1794 } else
1795 LOGP(DNM, LOGL_ERROR, "ACK not found\n");
Dieter Spaar16646022011-07-28 00:01:50 +02001796
Harald Weltebda367c2011-07-28 00:03:49 +02001797 /* TODO: the assumption for the following is that no NACK was received */
1798
1799 /* ACK for reset message ? */
1800 if (do_reset != 0) {
1801 do_reset = 0;
1802
1803 /*
1804 TODO: For the InSite processing the received data is
1805 blocked in the driver during reset.
1806 Otherwise the LAPD module might assert because the InSite
1807 sends garbage on the E1 line during reset.
1808 This is done by looking at "wait_reset" in the driver
1809 (function handle_ts1_read()) and ignoring the received data.
1810 It seems to be necessary for the MetroSite too.
1811 */
1812 wait_reset = 1;
1813
1814 reset_timer.cb = &reset_timer_cb;
1815 reset_timer.data = bts;
1816 osmo_timer_schedule(&reset_timer, RESET_INTERVAL);
1817
1818 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1819 struct e1inp_line *line;
1820 /* OML link */
1821 line = e1inp_line_get(e1_link->e1_nr);
1822 if (!line) {
1823 LOGP(DINP, LOGL_ERROR,
1824 "BTS %u OML link referring to "
1825 "non-existing E1 line %u\n", bts->nr,
1826 e1_link->e1_nr);
1827 return -ENOMEM;
1828 }
1829
1830 start_sabm_in_line(line, 0, -1); /* stop all first */
1831 }
1832
1833 /* ACK for CONF DATA message ? */
1834 if (conf != 0) {
1835 /* start TRX (RSL link) */
1836
1837 struct gsm_e1_subslot *e1_link = &mb->trx->rsl_e1_link;
1838 struct e1inp_line *line;
1839
1840 conf = 0;
1841
1842 /* RSL Link */
1843 line = e1inp_line_get(e1_link->e1_nr);
1844 if (!line) {
1845 LOGP(DINP, LOGL_ERROR,
1846 "TRX (%u/%u) RSL link referring "
1847 "to non-existing E1 line %u\n",
1848 mb->trx->bts->nr, mb->trx->nr,
1849 e1_link->e1_nr);
1850 return -ENOMEM;
1851 }
1852 /* start TRX */
1853 start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */
1854 }
1855 break;
1856 case NOKIA_MSG_STATE_CHANGED:
1857 /* send ACK */
1858 abis_nm_ack(bts, ref);
1859 break;
1860 case NOKIA_MSG_CONF_COMPLETE:
1861 /* send ACK */
1862 abis_nm_ack(bts, ref);
1863 break;
1864 case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */
1865 /* send ACK (do we have to send an ACK ?) */
1866 abis_nm_ack(bts, ref);
1867 break;
1868 case NOKIA_MSG_ALARM:
1869 find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity,
1870 sizeof(severity));
1871 /* TODO: there might be alarms with both elements set */
1872 str_len =
1873 find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info,
1874 sizeof(info));
1875 if (str_len > 0) {
1876 info[str_len] = 0;
1877 LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n",
1878 get_severity_string(severity), severity, info);
1879 } else { /* nothing found, try details */
1880 str_len =
1881 find_element(noh->data, len_data,
1882 NOKIA_EI_ALARM_DETAIL, info,
1883 sizeof(info));
1884 if (str_len > 0) {
1885 uint16_t code;
1886 info[str_len] = 0;
1887 code = (info[0] << 8) + info[1];
1888 LOGP(DNM, LOGL_INFO,
1889 "ALARM Severity %s (%d), code 0x%X : %s\n",
1890 get_severity_string(severity), severity,
1891 code, info + 2);
1892 }
1893 }
1894 /* send ACK */
1895 abis_nm_ack(bts, ref);
1896 break;
1897 }
1898
1899 abis_nm_queue_send_next(bts);
1900
1901 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001902}
1903
1904/* TODO: put in a separate file ? */
1905
1906int abis_nokia_rcvmsg(struct msgb *msg)
1907{
Harald Weltebda367c2011-07-28 00:03:49 +02001908 struct abis_om_hdr *oh = msgb_l2(msg);
1909 int rc = 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001910
Harald Weltebda367c2011-07-28 00:03:49 +02001911 /* Various consistency checks */
1912 if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
1913 LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
1914 oh->placement);
1915 if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
1916 return -EINVAL;
1917 }
1918 if (oh->sequence != 0) {
1919 LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
1920 oh->sequence);
1921 return -EINVAL;
1922 }
1923 msg->l3h = (unsigned char *)oh + sizeof(*oh);
Dieter Spaar16646022011-07-28 00:01:50 +02001924
Harald Weltebda367c2011-07-28 00:03:49 +02001925 switch (oh->mdisc) {
1926 case ABIS_OM_MDISC_FOM:
1927 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n");
1928 rc = abis_nm_rcvmsg_fom(msg);
1929 break;
1930 case ABIS_OM_MDISC_MANUF:
1931 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n");
1932 break;
1933 case ABIS_OM_MDISC_MMI:
1934 case ABIS_OM_MDISC_TRAU:
1935 LOGP(DNM, LOGL_ERROR,
1936 "unimplemented ABIS OML message discriminator 0x%x\n",
1937 oh->mdisc);
1938 break;
1939 default:
1940 LOGP(DNM, LOGL_ERROR,
1941 "unknown ABIS OML message discriminator 0x%x\n",
1942 oh->mdisc);
1943 return -EINVAL;
1944 }
Dieter Spaar16646022011-07-28 00:01:50 +02001945
Harald Weltebda367c2011-07-28 00:03:49 +02001946 msgb_free(msg);
1947 return rc;
Dieter Spaar16646022011-07-28 00:01:50 +02001948}
1949
1950static int bts_model_nokia_site_start(struct gsm_network *net);
1951
1952static struct gsm_bts_model model_nokia_site = {
Harald Weltebda367c2011-07-28 00:03:49 +02001953 .type = GSM_BTS_TYPE_NOKIA_SITE,
1954 .name = "nokia_site",
1955 .start = bts_model_nokia_site_start,
1956 .oml_rcvmsg = &abis_nokia_rcvmsg
Dieter Spaar16646022011-07-28 00:01:50 +02001957};
1958
1959static struct gsm_network *my_net;
1960
1961static int bts_model_nokia_site_start(struct gsm_network *net)
1962{
Harald Weltebda367c2011-07-28 00:03:49 +02001963 model_nokia_site.features.data = &model_nokia_site._features_data[0];
1964 model_nokia_site.features.data_len =
1965 sizeof(model_nokia_site._features_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001966
Harald Weltebda367c2011-07-28 00:03:49 +02001967 gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HOPPING);
1968 gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HSCSD);
Dieter Spaar16646022011-07-28 00:01:50 +02001969
Harald Weltebda367c2011-07-28 00:03:49 +02001970 osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL);
1971 osmo_signal_register_handler(SS_GLOBAL, gbl_sig_cb, NULL);
1972 osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
Dieter Spaar16646022011-07-28 00:01:50 +02001973
Harald Weltebda367c2011-07-28 00:03:49 +02001974 my_net = net;
1975
1976 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001977}
1978
1979int bts_model_nokia_site_init(void)
1980{
Harald Weltebda367c2011-07-28 00:03:49 +02001981 return gsm_bts_model_register(&model_nokia_site);
Dieter Spaar16646022011-07-28 00:01:50 +02001982}