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