blob: 6cafaae1c45aae5b9df664786f7dd7399c6fc4e0 [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
Harald Weltecde57942011-07-28 00:13:46 +020084/*
Dieter Spaar16646022011-07-28 00:01:50 +020085
86 Tell LAPD to start start the SAP (send SABM requests) for all signalling
Harald Weltecde57942011-07-28 00:13:46 +020087 timeslots in this line
88
89 Attention: this has to be adapted for mISDN
Dieter Spaar16646022011-07-28 00:01:50 +020090*/
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/*
Harald Weltecde57942011-07-28 00:13:46 +0200932 build the configuration for each TRX
Dieter Spaar16646022011-07-28 00:01:50 +0200933*/
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
Harald Weltecde57942011-07-28 00:13:46 +0200980 /*
Harald Weltebda367c2011-07-28 00:03:49 +0200981 Attention: all TRX except the first one seem to get the TSC
982 from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION,
Harald Weltecde57942011-07-28 00:13:46 +0200983 GSM 04.08 CHANNEL DESCRIPTION).
984 There was a bug in rsl_chan_activate_lchan() setting this parameter.
Harald Weltebda367c2011-07-28 00:03:49 +0200985 */
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
Harald Weltecde57942011-07-28 00:13:46 +02001015 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (can be used in GPRS release 2).
1016 0xFF = spare TS
Harald Weltebda367c2011-07-28 00:03:49 +02001017 */
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/*
Dieter Spaar16646022011-07-28 00:01:50 +02001221 build the configuration data
Dieter Spaar16646022011-07-28 00:01:50 +02001222*/
1223
Harald Weltebda367c2011-07-28 00:03:49 +02001224static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config,
1225 int need_hopping)
Dieter Spaar16646022011-07-28 00:01:50 +02001226{
Harald Weltebda367c2011-07-28 00:03:49 +02001227 /* is it an InSite BTS ? */
1228 if (bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */
1229 if (n_trx != 1) {
1230 fprintf(stderr, "InSite has only one TRX\n");
1231 return 0;
1232 }
1233 if (need_hopping != 0) {
1234 fprintf(stderr, "InSite does not support hopping\n");
1235 return 0;
1236 }
1237 memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite));
1238 set_real_time(&fu_config[26]);
1239 return sizeof(bts_config_insite);
1240 }
Dieter Spaar16646022011-07-28 00:01:50 +02001241
Harald Weltebda367c2011-07-28 00:03:49 +02001242 int len = 0;
1243 int i;
1244
1245 memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1));
1246
1247 /* set sector configuration */
1248 fu_config[len + 12 - 1] = 1 + n_trx; /* len */
1249 for (i = 0; i < n_trx; i++)
1250 fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF);
1251
1252 len += (sizeof(bts_config_1) + (n_trx - 1));
1253
1254 memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2));
1255 /* set hopping mode (Baseband and RF hopping work for the MetroSite) */
1256 if (need_hopping)
1257 fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */
1258 len += sizeof(bts_config_2);
1259
1260 /* set extended cell radius for each TRX */
1261 for (i = 0; i < n_trx; i++) {
1262 memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3));
1263 fu_config[len + 3] = ((i + 1) & 0xFF);
1264 len += sizeof(bts_config_3);
1265 }
1266
1267 memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4));
1268 set_real_time(&fu_config[len + 3]);
1269 len += sizeof(bts_config_4);
1270
1271 return len;
Dieter Spaar16646022011-07-28 00:01:50 +02001272}
1273
1274/* TODO: put in a separate file ? */
1275
1276static struct msgb *nm_msgb_alloc(void)
1277{
Harald Weltebda367c2011-07-28 00:03:49 +02001278 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
Dieter Spaar16646022011-07-28 00:01:50 +02001279}
1280
1281/* TODO: put in a separate file ? */
1282
1283struct abis_om_nokia_hdr {
Harald Weltebda367c2011-07-28 00:03:49 +02001284 uint8_t msg_type;
1285 uint8_t spare;
1286 uint16_t reference;
1287 uint8_t data[0];
Dieter Spaar16646022011-07-28 00:01:50 +02001288} __attribute__ ((packed));
1289
1290#define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr))
1291
Harald Weltebda367c2011-07-28 00:03:49 +02001292static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref,
1293 uint8_t * data, int len_data)
Dieter Spaar16646022011-07-28 00:01:50 +02001294{
Harald Weltebda367c2011-07-28 00:03:49 +02001295 struct abis_om_hdr *oh;
1296 struct abis_om_nokia_hdr *noh;
1297 struct msgb *msg = nm_msgb_alloc();
Dieter Spaar16646022011-07-28 00:01:50 +02001298
Harald Weltebda367c2011-07-28 00:03:49 +02001299 oh = (struct abis_om_hdr *)msgb_put(msg,
1300 ABIS_OM_NOKIA_HDR_SIZE + len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001301
Harald Weltebda367c2011-07-28 00:03:49 +02001302 oh->mdisc = ABIS_OM_MDISC_FOM;
1303 oh->placement = ABIS_OM_PLACEMENT_ONLY;
1304 oh->sequence = 0;
1305 oh->length = sizeof(struct abis_om_nokia_hdr) + len_data;
1306
1307 noh = (struct abis_om_nokia_hdr *)oh->data;
1308
1309 noh->msg_type = msg_type;
1310 noh->spare = 0;
1311 noh->reference = htons(ref);
1312 memcpy(noh->data, data, len_data);
1313
1314 DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type));
1315
1316 return abis_nm_sendmsg(bts, msg);
Dieter Spaar16646022011-07-28 00:01:50 +02001317}
1318
1319/* TODO: put in a separate file ? */
1320
1321static uint8_t download_req[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001322 0x5F, 0x25, 0x0B,
1323 /* ID = 0x25 (File identity) */
1324 /* length = 11 */
1325 /* [3] */
1326 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
1327 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001328
Harald Weltebda367c2011-07-28 00:03:49 +02001329 0x5F, 0x78, 0x03,
1330 /* ID = 0x78 (File version) */
1331 /* length = 3 */
1332 /* [17] */
1333 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001334
Harald Weltebda367c2011-07-28 00:03:49 +02001335 0x5F, 0x81, 0x0A, 0x01,
1336 /* ID = 0x8A (SW load mode) */
1337 /* length = 1 */
1338 /* [24] */
1339 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001340
Harald Weltebda367c2011-07-28 00:03:49 +02001341 0x5F, 0x81, 0x06, 0x01,
1342 /* ID = 0x86 (Acknowledgement period) */
1343 /* length = 1 */
1344 /* [29] */
1345 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001346};
1347
1348static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref)
1349{
Harald Weltebda367c2011-07-28 00:03:49 +02001350 uint8_t *data = download_req;
1351 int len_data = sizeof(download_req);
1352
1353 return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data,
1354 len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001355}
1356
1357/* TODO: put in a separate file ? */
1358
1359static uint8_t ack[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001360 0x5F, 0x23, 0x01,
1361 /* ID = 0x23 (Ack-Nack) */
1362 /* length = 1 */
1363 /* [3] */
1364 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001365};
1366
1367static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref)
1368{
Harald Weltebda367c2011-07-28 00:03:49 +02001369 uint8_t *data = ack;
1370 int len_data = sizeof(ack);
1371
1372 return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001373}
1374
1375/* TODO: put in a separate file ? */
1376
1377static uint8_t reset[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001378 0x5F, 0x40, 0x04,
1379 /* ID = 0x40 (Object identity) */
1380 /* length = 4 */
1381 /* [3] */
1382 0x00, 0x01, 0xFF, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +02001383};
1384
1385static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref)
1386{
Harald Weltebda367c2011-07-28 00:03:49 +02001387 uint8_t *data = reset;
1388 int len_data = sizeof(reset);
1389
1390 return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001391}
1392
1393/* TODO: put in a separate file ? */
1394
Harald Weltebda367c2011-07-28 00:03:49 +02001395static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type,
1396 uint16_t ref, uint8_t * data, int len)
Dieter Spaar16646022011-07-28 00:01:50 +02001397{
Harald Weltebda367c2011-07-28 00:03:49 +02001398 int len_remain, len_to_send, max_send;
1399 int seq = 0;
1400 int ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001401
Harald Weltebda367c2011-07-28 00:03:49 +02001402 len_remain = len;
1403
1404 while (len_remain) {
1405 struct abis_om_hdr *oh;
1406 struct abis_om_nokia_hdr *noh;
1407 struct msgb *msg = nm_msgb_alloc();
1408
1409 if (seq == 0)
1410 max_send = 256 - sizeof(struct abis_om_nokia_hdr);
1411 else
1412 max_send = 256;
1413
1414 if (len_remain > max_send) {
1415 len_to_send = max_send;
1416
1417 if (seq == 0) {
1418 /* first segment */
1419 oh = (struct abis_om_hdr *)msgb_put(msg,
1420 ABIS_OM_NOKIA_HDR_SIZE
1421 +
1422 len_to_send);
1423
1424 oh->mdisc = ABIS_OM_MDISC_FOM;
1425 oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */
1426 oh->sequence = seq;
1427 oh->length = 0; /* 256 bytes */
1428
1429 noh = (struct abis_om_nokia_hdr *)oh->data;
1430
1431 noh->msg_type = msg_type;
1432 noh->spare = 0;
1433 noh->reference = htons(ref);
1434 memcpy(noh->data, data, len_to_send);
1435 } else {
1436 /* segment in between */
1437 oh = (struct abis_om_hdr *)msgb_put(msg,
1438 sizeof
1439 (struct
1440 abis_om_hdr)
1441 +
1442 len_to_send);
1443
1444 oh->mdisc = ABIS_OM_MDISC_FOM;
1445 oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */
1446 oh->sequence = seq;
1447 oh->length = 0; /* 256 bytes */
1448
1449 memcpy(oh->data, data, len_to_send);
1450 }
1451 } else {
1452
1453 len_to_send = len_remain;
1454
1455 /* check if message fits in a single segment */
1456
1457 if (seq == 0)
1458 return abis_nm_send(bts, msg_type, ref, data,
1459 len_to_send);
1460
1461 /* last segment */
1462
1463 oh = (struct abis_om_hdr *)msgb_put(msg,
1464 sizeof(struct
1465 abis_om_hdr)
1466 + len_to_send);
1467
1468 oh->mdisc = ABIS_OM_MDISC_FOM;
1469 oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */
1470 oh->sequence = seq;
1471 oh->length = len_to_send;
1472
1473 memcpy(oh->data, data, len_to_send);
1474 }
1475
1476 DEBUGPC(DNM, "Sending multi-segment %d\n", seq);
1477
1478 ret = abis_nm_sendmsg(bts, msg);
1479 if (ret < 0)
1480 return ret;
1481
1482 abis_nm_queue_send_next(bts);
1483
1484 /* next segment */
1485 len_remain -= len_to_send;
1486 data += len_to_send;
1487 seq++;
1488 }
1489 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001490}
1491
1492/* TODO: put in a separate file ? */
1493
1494static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type)
1495{
Harald Weltebda367c2011-07-28 00:03:49 +02001496 struct gsm_bts_trx *trx;
1497 uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */
1498 int len = 0;
1499 int idx = 0;
1500 int ret;
1501 int hopping = 0;
1502 int need_hopping = 0;
1503
1504 memset(config, 0, sizeof(config));
1505
1506 llist_for_each_entry(trx, &bts->trx_list, list) {
1507#if 0 /* debugging */
1508 printf("TRX\n");
1509 printf(" arfcn: %d\n", trx->arfcn);
1510 printf(" bsic: %d\n", trx->bts->bsic);
1511 uint8_t ca[20];
1512 memset(ca, 0xFF, sizeof(ca));
1513 ret = generate_cell_chan_list(ca, trx->bts);
1514 printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca)));
1515 int i;
1516 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
1517 struct gsm_bts_trx_ts *ts = &trx->ts[i];
1518
1519 printf(" pchan %d: %d\n", i, ts->pchan);
1520 }
Dieter Spaar16646022011-07-28 00:01:50 +02001521#endif
Harald Weltebda367c2011-07-28 00:03:49 +02001522 ret = make_fu_config(trx, idx + 1, config + len, &hopping);
1523 need_hopping |= hopping;
1524 len += ret;
1525
1526 idx++;
1527 }
1528
1529 ret = make_bts_config(bts_type, idx, config + len, need_hopping);
1530 len += ret;
1531
1532#if 0 /* debugging */
1533 dump_elements(config, len);
1534#endif
1535
1536 return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config,
1537 len);
Dieter Spaar16646022011-07-28 00:01:50 +02001538}
1539
1540#define GET_NEXT_BYTE if(idx >= len) return 0; \
Harald Weltebda367c2011-07-28 00:03:49 +02001541 ub = data[idx++];
Dieter Spaar16646022011-07-28 00:01:50 +02001542
Harald Weltebda367c2011-07-28 00:03:49 +02001543static int find_element(uint8_t * data, int len, uint16_t id, uint8_t * value,
1544 int max_value)
1545{
1546 uint8_t ub;
1547 int idx = 0;
1548 int found = 0;
1549 int constructed;
1550 uint16_t id_value;
1551
1552 for (;;) {
1553
1554 GET_NEXT_BYTE;
1555
1556 /* encoding bit, construced means that other elements are contained */
1557 constructed = ((ub & 0x20) ? 1 : 0);
1558
1559 if ((ub & 0x1F) == 0x1F) {
1560 /* fixed pattern, ID follows */
1561 GET_NEXT_BYTE; /* ID */
1562 id_value = ub & 0x7F;
1563 if (ub & 0x80) {
1564 /* extension bit */
1565 GET_NEXT_BYTE; /* ID low part */
1566 id_value = (id_value << 7) | (ub & 0x7F);
1567 }
1568 if (id_value == id)
1569 found = 1;
1570 } else {
1571 id_value = (ub & 0x3F);
1572 if (id_value == id)
1573 found = 1;
1574 }
1575
1576 GET_NEXT_BYTE; /* length */
1577
1578 if (found) {
1579 /* get data */
1580 uint8_t n = ub;
1581 uint8_t i;
1582 for (i = 0; i < n; i++) {
1583 GET_NEXT_BYTE;
1584 if (max_value <= 0)
1585 return -1; /* buffer too small */
1586 *value = ub;
1587 value++;
1588 max_value--;
1589 }
1590 return n; /* length */
1591 } else {
1592 /* skip data */
1593 uint8_t n = ub;
1594 uint8_t i;
1595 for (i = 0; i < n; i++) {
1596 GET_NEXT_BYTE;
1597 }
1598 }
1599 }
1600 return 0; /* not found */
Dieter Spaar16646022011-07-28 00:01:50 +02001601}
1602
Harald Weltebda367c2011-07-28 00:03:49 +02001603static int dump_elements(uint8_t * data, int len)
1604{
1605 uint8_t ub;
1606 int idx = 0;
1607 int constructed;
1608 uint16_t id_value;
1609 static char indent[100] = ""; /* TODO: move static to BTS context */
Dieter Spaar16646022011-07-28 00:01:50 +02001610
Harald Weltebda367c2011-07-28 00:03:49 +02001611 for (;;) {
1612
1613 GET_NEXT_BYTE;
1614
1615 /* encoding bit, construced means that other elements are contained */
1616 constructed = ((ub & 0x20) ? 1 : 0);
1617
1618 if ((ub & 0x1F) == 0x1F) {
1619 /* fixed pattern, ID follows */
1620 GET_NEXT_BYTE; /* ID */
1621 id_value = ub & 0x7F;
1622 if (ub & 0x80) {
1623 /* extension bit */
1624 GET_NEXT_BYTE; /* ID low part */
1625 id_value = (id_value << 7) | (ub & 0x7F);
1626 }
1627
1628 } else {
1629 id_value = (ub & 0x3F);
1630 }
1631
1632 GET_NEXT_BYTE; /* length */
1633
1634 printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value,
1635 get_element_name_string(id_value),
1636 constructed ? "** constructed **" : "");
1637 printf("%s length = %d\n", indent, ub);
1638 printf("%s %s\n", indent, osmo_hexdump(data + idx, ub));
1639
1640 if (constructed) {
1641 int indent_len = strlen(indent);
1642 strcat(indent, " ");
1643
1644 dump_elements(data + idx, ub);
1645
1646 indent[indent_len] = 0;
1647 }
1648 /* skip data */
1649 uint8_t n = ub;
1650 uint8_t i;
1651 for (i = 0; i < n; i++) {
1652 GET_NEXT_BYTE;
1653 }
1654 }
1655 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001656}
1657
1658/* TODO: put in a separate file ? */
1659
1660/* taken from abis_nm.c */
1661
1662static void abis_nm_queue_send_next(struct gsm_bts *bts)
1663{
Harald Weltebda367c2011-07-28 00:03:49 +02001664 int wait = 0;
1665 struct msgb *msg;
1666 /* the queue is empty */
1667 while (!llist_empty(&bts->abis_queue)) {
1668 msg = msgb_dequeue(&bts->abis_queue);
1669 wait = OBSC_NM_W_ACK_CB(msg);
1670 _abis_nm_sendmsg(msg, 0);
Dieter Spaar16646022011-07-28 00:01:50 +02001671
Harald Weltebda367c2011-07-28 00:03:49 +02001672 if (wait)
1673 break;
1674 }
Dieter Spaar16646022011-07-28 00:01:50 +02001675
Harald Weltebda367c2011-07-28 00:03:49 +02001676 bts->abis_nm_pend = wait;
Dieter Spaar16646022011-07-28 00:01:50 +02001677}
1678
1679/* TODO: put in a separate file ? */
1680
1681/* timer for restarting OML after BTS reset */
1682
1683static void reset_timer_cb(void *_bts)
1684{
Harald Weltebda367c2011-07-28 00:03:49 +02001685 struct gsm_bts *bts = _bts;
1686 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1687 struct e1inp_line *line;
1688
1689 wait_reset = 0;
1690
1691 /* OML link */
1692 line = e1inp_line_get(e1_link->e1_nr);
1693 if (!line) {
1694 LOGP(DINP, LOGL_ERROR, "BTS %u OML link referring to "
1695 "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
1696 return;
1697 }
1698
1699 start_sabm_in_line(line, 0, -1); /* stop all first */
1700 start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */
Dieter Spaar16646022011-07-28 00:01:50 +02001701}
1702
1703/* TODO: put in a separate file ? */
1704
1705/*
1706 This is how the configuration is done:
Dieter Spaar16646022011-07-28 00:01:50 +02001707 - start OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001708 - reset BTS
Dieter Spaar16646022011-07-28 00:01:50 +02001709 - receive ACK, wait some time and restart OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001710 - receive OMU STARTED message, send START DOWNLOAD REQ
Dieter Spaar16646022011-07-28 00:01:50 +02001711 - receive CNF REQ message, send CONF DATA
Dieter Spaar16646022011-07-28 00:01:50 +02001712 - receive ACK, start RSL link(s)
Dieter Spaar16646022011-07-28 00:01:50 +02001713 ACK some other messages received from the BTS.
Harald Weltecde57942011-07-28 00:13:46 +02001714
Dieter Spaar16646022011-07-28 00:01:50 +02001715 Probably its also possible to configure the BTS without a reset, this
1716 has not been tested yet.
1717*/
1718
1719static int abis_nm_rcvmsg_fom(struct msgb *mb)
1720{
Harald Weltebda367c2011-07-28 00:03:49 +02001721 struct gsm_bts *bts = mb->trx->bts;
1722 struct abis_om_hdr *oh = msgb_l2(mb);
1723 struct abis_om_nokia_hdr *noh = msgb_l3(mb);
1724 uint8_t mt = noh->msg_type;
1725 int ret = 0;
1726 uint16_t ref = ntohs(noh->reference);
Harald Weltebda367c2011-07-28 00:03:49 +02001727 uint8_t info[256];
1728 uint8_t ack = 0xFF;
1729 uint8_t severity = 0xFF;
1730 int str_len;
1731 int len_data;
Dieter Spaar16646022011-07-28 00:01:50 +02001732
Harald Weltebda367c2011-07-28 00:03:49 +02001733 if (wait_reset) {
1734 LOGP(DNM, LOGL_INFO,
1735 "Ignore message while waiting for reset\n");
1736 return ret;
1737 }
Dieter Spaar16646022011-07-28 00:01:50 +02001738
Harald Weltebda367c2011-07-28 00:03:49 +02001739 if (oh->length < sizeof(struct abis_om_nokia_hdr)) {
1740 LOGP(DNM, LOGL_ERROR, "Message too short\n");
1741 return -EINVAL;
1742 }
1743
1744 len_data = oh->length - sizeof(struct abis_om_nokia_hdr);
1745 LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt));
1746#if 0 /* debugging */
1747 dump_elements(noh->data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001748#endif
Dieter Spaar16646022011-07-28 00:01:50 +02001749
Harald Weltebda367c2011-07-28 00:03:49 +02001750 switch (mt) {
1751 case NOKIA_MSG_OMU_STARTED:
Harald Welte9d2f3772011-07-28 00:19:06 +02001752 if (find_element(noh->data, len_data,
1753 NOKIA_EI_BTS_TYPE, &bts->nokia.bts_type,
1754 sizeof(uint8_t)) == sizeof(uint8_t))
1755 LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n",
1756 bts->nokia.bts_type,
1757 get_bts_type_string(bts->nokia.bts_type));
Harald Weltebda367c2011-07-28 00:03:49 +02001758 else
1759 LOGP(DNM, LOGL_ERROR, "BTS type not found\n");
1760 /* send START_DOWNLOAD_REQ */
1761 abis_nm_download_req(bts, ref);
1762 break;
1763 case NOKIA_MSG_MF_REQ:
1764 break;
1765 case NOKIA_MSG_CONF_REQ:
1766 /* send ACK */
1767 abis_nm_ack(bts, ref);
1768 abis_nm_queue_send_next(bts);
1769 /* send CONF_DATA */
Harald Welte9d2f3772011-07-28 00:19:06 +02001770 abis_nm_send_config(bts, bts->nokia.bts_type);
1771 bts->nokia.configured = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001772 break;
1773 case NOKIA_MSG_ACK:
1774 if (find_element
1775 (noh->data, len_data, NOKIA_EI_ACK, &ack,
1776 sizeof(uint8_t)) == sizeof(uint8_t)) {
1777 LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack);
1778 if (ack != 1) {
1779 LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n",
1780 ack);
1781 /* TODO: properly handle failures (NACK) */
1782 }
1783 } else
1784 LOGP(DNM, LOGL_ERROR, "ACK not found\n");
Dieter Spaar16646022011-07-28 00:01:50 +02001785
Harald Weltebda367c2011-07-28 00:03:49 +02001786 /* TODO: the assumption for the following is that no NACK was received */
1787
1788 /* ACK for reset message ? */
1789 if (do_reset != 0) {
1790 do_reset = 0;
1791
1792 /*
1793 TODO: For the InSite processing the received data is
1794 blocked in the driver during reset.
1795 Otherwise the LAPD module might assert because the InSite
1796 sends garbage on the E1 line during reset.
1797 This is done by looking at "wait_reset" in the driver
1798 (function handle_ts1_read()) and ignoring the received data.
1799 It seems to be necessary for the MetroSite too.
1800 */
1801 wait_reset = 1;
1802
1803 reset_timer.cb = &reset_timer_cb;
1804 reset_timer.data = bts;
1805 osmo_timer_schedule(&reset_timer, RESET_INTERVAL);
1806
1807 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1808 struct e1inp_line *line;
1809 /* OML link */
1810 line = e1inp_line_get(e1_link->e1_nr);
1811 if (!line) {
1812 LOGP(DINP, LOGL_ERROR,
1813 "BTS %u OML link referring to "
1814 "non-existing E1 line %u\n", bts->nr,
1815 e1_link->e1_nr);
1816 return -ENOMEM;
1817 }
1818
1819 start_sabm_in_line(line, 0, -1); /* stop all first */
1820 }
1821
1822 /* ACK for CONF DATA message ? */
Harald Welte9d2f3772011-07-28 00:19:06 +02001823 if (bts->nokia.configured != 0) {
Harald Weltebda367c2011-07-28 00:03:49 +02001824 /* start TRX (RSL link) */
1825
1826 struct gsm_e1_subslot *e1_link = &mb->trx->rsl_e1_link;
1827 struct e1inp_line *line;
1828
Harald Welte9d2f3772011-07-28 00:19:06 +02001829 bts->nokia.configured = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001830
1831 /* RSL Link */
1832 line = e1inp_line_get(e1_link->e1_nr);
1833 if (!line) {
1834 LOGP(DINP, LOGL_ERROR,
1835 "TRX (%u/%u) RSL link referring "
1836 "to non-existing E1 line %u\n",
1837 mb->trx->bts->nr, mb->trx->nr,
1838 e1_link->e1_nr);
1839 return -ENOMEM;
1840 }
1841 /* start TRX */
1842 start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */
1843 }
1844 break;
1845 case NOKIA_MSG_STATE_CHANGED:
1846 /* send ACK */
1847 abis_nm_ack(bts, ref);
1848 break;
1849 case NOKIA_MSG_CONF_COMPLETE:
1850 /* send ACK */
1851 abis_nm_ack(bts, ref);
1852 break;
1853 case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */
1854 /* send ACK (do we have to send an ACK ?) */
1855 abis_nm_ack(bts, ref);
1856 break;
1857 case NOKIA_MSG_ALARM:
1858 find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity,
1859 sizeof(severity));
1860 /* TODO: there might be alarms with both elements set */
1861 str_len =
1862 find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info,
1863 sizeof(info));
1864 if (str_len > 0) {
1865 info[str_len] = 0;
1866 LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n",
1867 get_severity_string(severity), severity, info);
1868 } else { /* nothing found, try details */
1869 str_len =
1870 find_element(noh->data, len_data,
1871 NOKIA_EI_ALARM_DETAIL, info,
1872 sizeof(info));
1873 if (str_len > 0) {
1874 uint16_t code;
1875 info[str_len] = 0;
1876 code = (info[0] << 8) + info[1];
1877 LOGP(DNM, LOGL_INFO,
1878 "ALARM Severity %s (%d), code 0x%X : %s\n",
1879 get_severity_string(severity), severity,
1880 code, info + 2);
1881 }
1882 }
1883 /* send ACK */
1884 abis_nm_ack(bts, ref);
1885 break;
1886 }
1887
1888 abis_nm_queue_send_next(bts);
1889
1890 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001891}
1892
1893/* TODO: put in a separate file ? */
1894
1895int abis_nokia_rcvmsg(struct msgb *msg)
1896{
Harald Weltebda367c2011-07-28 00:03:49 +02001897 struct abis_om_hdr *oh = msgb_l2(msg);
1898 int rc = 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001899
Harald Weltebda367c2011-07-28 00:03:49 +02001900 /* Various consistency checks */
1901 if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
1902 LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
1903 oh->placement);
1904 if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
1905 return -EINVAL;
1906 }
1907 if (oh->sequence != 0) {
1908 LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
1909 oh->sequence);
1910 return -EINVAL;
1911 }
1912 msg->l3h = (unsigned char *)oh + sizeof(*oh);
Dieter Spaar16646022011-07-28 00:01:50 +02001913
Harald Weltebda367c2011-07-28 00:03:49 +02001914 switch (oh->mdisc) {
1915 case ABIS_OM_MDISC_FOM:
1916 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n");
1917 rc = abis_nm_rcvmsg_fom(msg);
1918 break;
1919 case ABIS_OM_MDISC_MANUF:
1920 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n");
1921 break;
1922 case ABIS_OM_MDISC_MMI:
1923 case ABIS_OM_MDISC_TRAU:
1924 LOGP(DNM, LOGL_ERROR,
1925 "unimplemented ABIS OML message discriminator 0x%x\n",
1926 oh->mdisc);
1927 break;
1928 default:
1929 LOGP(DNM, LOGL_ERROR,
1930 "unknown ABIS OML message discriminator 0x%x\n",
1931 oh->mdisc);
1932 return -EINVAL;
1933 }
Dieter Spaar16646022011-07-28 00:01:50 +02001934
Harald Weltebda367c2011-07-28 00:03:49 +02001935 msgb_free(msg);
1936 return rc;
Dieter Spaar16646022011-07-28 00:01:50 +02001937}
1938
1939static int bts_model_nokia_site_start(struct gsm_network *net);
1940
1941static struct gsm_bts_model model_nokia_site = {
Harald Weltebda367c2011-07-28 00:03:49 +02001942 .type = GSM_BTS_TYPE_NOKIA_SITE,
1943 .name = "nokia_site",
1944 .start = bts_model_nokia_site_start,
1945 .oml_rcvmsg = &abis_nokia_rcvmsg
Dieter Spaar16646022011-07-28 00:01:50 +02001946};
1947
1948static struct gsm_network *my_net;
1949
1950static int bts_model_nokia_site_start(struct gsm_network *net)
1951{
Harald Weltebda367c2011-07-28 00:03:49 +02001952 model_nokia_site.features.data = &model_nokia_site._features_data[0];
1953 model_nokia_site.features.data_len =
1954 sizeof(model_nokia_site._features_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001955
Harald Weltebda367c2011-07-28 00:03:49 +02001956 gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HOPPING);
1957 gsm_btsmodel_set_feature(&model_nokia_site, BTS_FEAT_HSCSD);
Dieter Spaar16646022011-07-28 00:01:50 +02001958
Harald Weltebda367c2011-07-28 00:03:49 +02001959 osmo_signal_register_handler(SS_INPUT, inp_sig_cb, NULL);
1960 osmo_signal_register_handler(SS_GLOBAL, gbl_sig_cb, NULL);
1961 osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
Dieter Spaar16646022011-07-28 00:01:50 +02001962
Harald Weltebda367c2011-07-28 00:03:49 +02001963 my_net = net;
1964
1965 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001966}
1967
1968int bts_model_nokia_site_init(void)
1969{
Harald Weltebda367c2011-07-28 00:03:49 +02001970 return gsm_bts_model_register(&model_nokia_site);
Dieter Spaar16646022011-07-28 00:01:50 +02001971}