blob: 4a24c3931f44ace297f7163ac42db6c811b50224 [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
Neels Hofmeyrc0164792017-09-04 15:15:32 +020033#include <osmocom/bsc/debug.h>
34#include <osmocom/bsc/gsm_data.h>
35#include <osmocom/bsc/abis_nm.h>
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020036#include <osmocom/abis/e1_input.h>
Neels Hofmeyrc0164792017-09-04 15:15:32 +020037#include <osmocom/bsc/signal.h>
Dieter Spaar16646022011-07-28 00:01:50 +020038
39#include <osmocom/core/timer.h>
40
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020041#include <osmocom/abis/lapd.h>
Dieter Spaar16646022011-07-28 00:01:50 +020042
43/* TODO: put in a separate file ? */
44
Dieter Spaar16646022011-07-28 00:01:50 +020045extern int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg);
46/* was static in system_information.c */
Harald Weltebda367c2011-07-28 00:03:49 +020047extern int generate_cell_chan_list(uint8_t * chan_list, struct gsm_bts *bts);
Dieter Spaar16646022011-07-28 00:01:50 +020048
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +020049static void nokia_abis_nm_queue_send_next(struct gsm_bts *bts);
Dieter Spaar16646022011-07-28 00:01:50 +020050static void reset_timer_cb(void *_bts);
51static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref);
Holger Hans Peter Freythera5050b12012-09-11 11:55:03 +020052static int dump_elements(uint8_t * data, int len) __attribute__((unused));
Dieter Spaar16646022011-07-28 00:01:50 +020053
54static void bootstrap_om_bts(struct gsm_bts *bts)
55{
Harald Weltebda367c2011-07-28 00:03:49 +020056 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for BTS %u\n", bts->nr);
57
Neels Hofmeyr91aa68f2018-05-09 17:46:22 +020058 gsm_bts_mark_all_ts_uninitialized(bts);
59
Sylvain Munautc9519462011-10-17 14:04:55 +020060 if (!bts->nokia.skip_reset) {
61 if (!bts->nokia.did_reset)
62 abis_nm_reset(bts, 1);
63 } else
64 bts->nokia.did_reset = 1;
Dieter Spaar16646022011-07-28 00:01:50 +020065}
66
67static void bootstrap_om_trx(struct gsm_bts_trx *trx)
68{
Harald Weltebda367c2011-07-28 00:03:49 +020069 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
70 trx->bts->nr, trx->nr);
Neels Hofmeyr91aa68f2018-05-09 17:46:22 +020071
72 gsm_trx_mark_all_ts_uninitialized(trx);
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
Andreas Eversbergc57e6ed2011-09-26 11:44:22 +020092static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi)
Dieter Spaar16646022011-07-28 00:01:50 +020093{
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
Andreas.Eversbergbb5c5942011-11-02 22:22:24 +0100112 if (start) {
113 ts->lapd->profile.t200_sec = 1;
114 ts->lapd->profile.t200_usec = 0;
Harald Welteb4d913d2011-08-26 19:14:55 +0200115 lapd_sap_start(ts->lapd, link->tei,
Harald Weltebda367c2011-07-28 00:03:49 +0200116 link->sapi);
Andreas.Eversbergbb5c5942011-11-02 22:22:24 +0100117 } else
Harald Welteb4d913d2011-08-26 19:14:55 +0200118 lapd_sap_stop(ts->lapd, link->tei,
Harald Weltebda367c2011-07-28 00:03:49 +0200119 link->sapi);
120 }
121 }
Dieter Spaar16646022011-07-28 00:01:50 +0200122}
123
124/* Callback function to be called every time we receive a signal from INPUT */
125static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200126 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200127{
Harald Weltebda367c2011-07-28 00:03:49 +0200128 struct gsm_bts *bts;
Dieter Spaar16646022011-07-28 00:01:50 +0200129
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200130 if (subsys != SS_L_GLOBAL)
Harald Weltebda367c2011-07-28 00:03:49 +0200131 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200132
Harald Weltebda367c2011-07-28 00:03:49 +0200133 switch (signal) {
134 case S_GLOBAL_BTS_CLOSE_OM:
135 bts = signal_data;
136 if (bts->type == GSM_BTS_TYPE_NOKIA_SITE)
137 shutdown_om(signal_data);
138 break;
139 }
Dieter Spaar16646022011-07-28 00:01:50 +0200140
Harald Weltebda367c2011-07-28 00:03:49 +0200141 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200142}
143
144/* Callback function to be called every time we receive a signal from INPUT */
145static int inp_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200146 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200147{
Harald Weltebda367c2011-07-28 00:03:49 +0200148 struct input_signal_data *isd = signal_data;
Dieter Spaar16646022011-07-28 00:01:50 +0200149
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200150 if (subsys != SS_L_INPUT)
Harald Weltebda367c2011-07-28 00:03:49 +0200151 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200152
Harald Weltebda367c2011-07-28 00:03:49 +0200153 switch (signal) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200154 case S_L_INP_LINE_INIT:
Harald Weltebda367c2011-07-28 00:03:49 +0200155 start_sabm_in_line(isd->line, 1, SAPI_OML); /* start only OML */
156 break;
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200157 case S_L_INP_TEI_DN:
Harald Weltebda367c2011-07-28 00:03:49 +0200158 break;
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200159 case S_L_INP_TEI_UP:
Harald Weltebda367c2011-07-28 00:03:49 +0200160 switch (isd->link_type) {
161 case E1INP_SIGN_OML:
162 if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
163 break;
Dieter Spaar16646022011-07-28 00:01:50 +0200164
Harald Weltebda367c2011-07-28 00:03:49 +0200165 if (isd->tei == isd->trx->bts->oml_tei)
166 bootstrap_om_bts(isd->trx->bts);
167 else
168 bootstrap_om_trx(isd->trx);
169 break;
170 }
171 break;
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200172 case S_L_INP_TEI_UNKNOWN:
Pablo Neira Ayuso2962c202011-08-10 00:48:10 +0200173 /* We are receiving LAPD frames with one TEI that we do not
174 * seem to know, likely that we (the BSC) stopped working
175 * and lost our local states. However, the BTS is already
176 * configured, we try to take over the RSL links. */
177 start_sabm_in_line(isd->line, 1, SAPI_RSL);
178 break;
Harald Weltebda367c2011-07-28 00:03:49 +0200179 }
180
181 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200182}
183
184static void nm_statechg_evt(unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200185 struct nm_statechg_signal_data *nsd)
Dieter Spaar16646022011-07-28 00:01:50 +0200186{
Harald Weltebda367c2011-07-28 00:03:49 +0200187 if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
188 return;
Dieter Spaar16646022011-07-28 00:01:50 +0200189}
190
191static int nm_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200192 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200193{
Harald Weltebda367c2011-07-28 00:03:49 +0200194 if (subsys != SS_NM)
195 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200196
Harald Weltebda367c2011-07-28 00:03:49 +0200197 switch (signal) {
198 case S_NM_STATECHG_OPER:
199 case S_NM_STATECHG_ADM:
200 nm_statechg_evt(signal, signal_data);
201 break;
202 default:
203 break;
204 }
Dieter Spaar16646022011-07-28 00:01:50 +0200205
Harald Weltebda367c2011-07-28 00:03:49 +0200206 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200207}
208
209/* TODO: put in a separate file ? */
210
Harald Welte44d26112011-07-28 00:43:13 +0200211static const struct value_string nokia_msgt_name[] = {
212 { 0x80, "NOKIA_BTS_CONF_DATA" },
213 { 0x81, "NOKIA_BTS_ACK" },
214 { 0x82, "NOKIA_BTS_OMU_STARTED" },
215 { 0x83, "NOKIA_BTS_START_DOWNLOAD_REQ" },
216 { 0x84, "NOKIA_BTS_MF_REQ" },
217 { 0x85, "NOKIA_BTS_AF_REQ" },
218 { 0x86, "NOKIA_BTS_RESET_REQ" },
219 { 0x87, "NOKIA_reserved" },
220 { 0x88, "NOKIA_BTS_CONF_REQ" },
221 { 0x89, "NOKIA_BTS_TEST_REQ" },
222 { 0x8A, "NOKIA_BTS_TEST_REPORT" },
223 { 0x8B, "NOKIA_reserved" },
224 { 0x8C, "NOKIA_reserved" },
225 { 0x8D, "NOKIA_reserved" },
226 { 0x8E, "NOKIA_BTS_CONF_COMPL" },
227 { 0x8F, "NOKIA_reserved" },
228 { 0x90, "NOKIA_BTS_STM_TEST_REQ" },
229 { 0x91, "NOKIA_BTS_STM_TEST_REPORT" },
230 { 0x92, "NOKIA_BTS_TRANSMISSION_COMMAND" },
231 { 0x93, "NOKIA_BTS_TRANSMISSION_ANSWER" },
232 { 0x94, "NOKIA_BTS_HW_DB_UPLOAD_REQ" },
233 { 0x95, "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ" },
234 { 0x96, "NOKIA_BTS_HW_DB_SAVE_REQ" },
235 { 0x97, "NOKIA_BTS_FLASH_ERASURE_REQ" },
236 { 0x98, "NOKIA_BTS_HW_DB_DOWNLOAD_REQ" },
237 { 0x99, "NOKIA_BTS_PWR_SUPPLY_CONTROL" },
238 { 0x9A, "NOKIA_BTS_ATTRIBUTE_REQ" },
239 { 0x9B, "NOKIA_BTS_ATTRIBUTE_REPORT" },
240 { 0x9C, "NOKIA_BTS_HW_REQ" },
241 { 0x9D, "NOKIA_BTS_HW_REPORT" },
242 { 0x9E, "NOKIA_BTS_RTE_TEST_REQ" },
243 { 0x9F, "NOKIA_BTS_RTE_TEST_REPORT" },
244 { 0xA0, "NOKIA_BTS_HW_DB_VERIFICATION_REQ" },
245 { 0xA1, "NOKIA_BTS_CLOCK_REQ" },
246 { 0xA2, "NOKIA_AC_CIRCUIT_REQ_NACK" },
247 { 0xA3, "NOKIA_AC_INTERRUPTED" },
248 { 0xA4, "NOKIA_BTS_NEW_TRE_INFO" },
249 { 0xA5, "NOKIA_AC_BSC_CIRCUITS_ALLOCATED" },
250 { 0xA6, "NOKIA_BTS_TRE_POLL_LIST" },
251 { 0xA7, "NOKIA_AC_CIRCUIT_REQ" },
252 { 0xA8, "NOKIA_BTS_BLOCK_CTRL_REQ" },
253 { 0xA9, "NOKIA_BTS_GSM_TIME_REQ" },
254 { 0xAA, "NOKIA_BTS_GSM_TIME" },
255 { 0xAB, "NOKIA_BTS_OUTPUT_CONTROL" },
256 { 0xAC, "NOKIA_BTS_STATE_CHANGED" },
257 { 0xAD, "NOKIA_BTS_SW_SAVE_REQ" },
258 { 0xAE, "NOKIA_BTS_ALARM" },
259 { 0xAF, "NOKIA_BTS_CHA_ADM_STATE" },
260 { 0xB0, "NOKIA_AC_POOL_SIZE_REPORT" },
261 { 0xB1, "NOKIA_AC_POOL_SIZE_INQUIRY" },
262 { 0xB2, "NOKIA_BTS_COMMISS_TEST_COMPLETED" },
263 { 0xB3, "NOKIA_BTS_COMMISS_TEST_REQ" },
264 { 0xB4, "NOKIA_BTS_TRANSP_BTS_TO_BSC" },
265 { 0xB5, "NOKIA_BTS_TRANSP_BSC_TO_BTS" },
266 { 0xB6, "NOKIA_BTS_LCS_COMMAND" },
267 { 0xB7, "NOKIA_BTS_LCS_ANSWER" },
268 { 0xB8, "NOKIA_BTS_LMU_FN_OFFSET_COMMAND" },
269 { 0xB9, "NOKIA_BTS_LMU_FN_OFFSET_ANSWER" },
270 { 0, NULL }
271};
272
273static const char *get_msg_type_name_string(uint8_t msg_type)
Dieter Spaar16646022011-07-28 00:01:50 +0200274{
Harald Welte44d26112011-07-28 00:43:13 +0200275 return get_value_string(nokia_msgt_name, msg_type);
Dieter Spaar16646022011-07-28 00:01:50 +0200276}
277
Harald Welte44d26112011-07-28 00:43:13 +0200278static const struct value_string nokia_element_name[] = {
279 { 0x01, "Ny1" },
280 { 0x02, "T3105_F" },
281 { 0x03, "Interference band limits" },
282 { 0x04, "Interference report timer in secs" },
283 { 0x05, "Channel configuration per TS" },
284 { 0x06, "BSIC" },
285 { 0x07, "RACH report timer in secs" },
286 { 0x08, "Hardware database status" },
287 { 0x09, "BTS RX level" },
288 { 0x0A, "ARFN" },
289 { 0x0B, "STM antenna attenuation" },
290 { 0x0C, "Cell allocation bitmap" },
291 { 0x0D, "Radio definition per TS" },
292 { 0x0E, "Frame number" },
293 { 0x0F, "Antenna diversity" },
294 { 0x10, "T3105_D" },
295 { 0x11, "File format" },
296 { 0x12, "Last File" },
297 { 0x13, "BTS type" },
298 { 0x14, "Erasure mode" },
299 { 0x15, "Hopping mode" },
300 { 0x16, "Floating TRX" },
301 { 0x17, "Power supplies" },
302 { 0x18, "Reset type" },
303 { 0x19, "Averaging period" },
304 { 0x1A, "RBER2" },
305 { 0x1B, "LAC" },
306 { 0x1C, "CI" },
307 { 0x1D, "Failure parameters" },
308 { 0x1E, "(RF max power reduction)" },
309 { 0x1F, "Measured RX_SENS" },
310 { 0x20, "Extended cell radius" },
311 { 0x21, "reserved" },
312 { 0x22, "Success-Failure" },
313 { 0x23, "Ack-Nack" },
314 { 0x24, "OMU test results" },
315 { 0x25, "File identity" },
316 { 0x26, "Generation and version code" },
317 { 0x27, "SW description" },
318 { 0x28, "BCCH LEV" },
319 { 0x29, "Test type" },
320 { 0x2A, "Subscriber number" },
321 { 0x2B, "reserved" },
322 { 0x2C, "HSN" },
323 { 0x2D, "reserved" },
324 { 0x2E, "MS RXLEV" },
325 { 0x2F, "MS TXLEV" },
326 { 0x30, "RXQUAL" },
327 { 0x31, "RX SENS" },
328 { 0x32, "Alarm block" },
329 { 0x33, "Neighbouring BCCH levels" },
330 { 0x34, "STM report type" },
331 { 0x35, "MA" },
332 { 0x36, "MAIO" },
333 { 0x37, "H_FLAG" },
334 { 0x38, "TCH_ARFN" },
335 { 0x39, "Clock output" },
336 { 0x3A, "Transmitted power" },
337 { 0x3B, "Clock sync" },
338 { 0x3C, "TMS protocol discriminator" },
339 { 0x3D, "TMS protocol data" },
340 { 0x3E, "FER" },
341 { 0x3F, "SWR result" },
342 { 0x40, "Object identity" },
343 { 0x41, "STM RX Antenna Test" },
344 { 0x42, "reserved" },
345 { 0x43, "reserved" },
346 { 0x44, "Object current state" },
347 { 0x45, "reserved" },
348 { 0x46, "FU channel configuration" },
349 { 0x47, "reserved" },
350 { 0x48, "ARFN of a CU" },
351 { 0x49, "FU radio definition" },
352 { 0x4A, "reserved" },
353 { 0x4B, "Severity" },
354 { 0x4C, "Diversity selection" },
355 { 0x4D, "RX antenna test" },
356 { 0x4E, "RX antenna supervision period" },
357 { 0x4F, "RX antenna state" },
358 { 0x50, "Sector configuration" },
359 { 0x51, "Additional info" },
360 { 0x52, "SWR parameters" },
361 { 0x53, "HW inquiry mode" },
362 { 0x54, "reserved" },
363 { 0x55, "Availability status" },
364 { 0x56, "reserved" },
365 { 0x57, "EAC inputs" },
366 { 0x58, "EAC outputs" },
367 { 0x59, "reserved" },
368 { 0x5A, "Position" },
369 { 0x5B, "HW unit identity" },
370 { 0x5C, "RF test signal attenuation" },
371 { 0x5D, "Operational state" },
372 { 0x5E, "Logical object identity" },
373 { 0x5F, "reserved" },
374 { 0x60, "BS_TXPWR_OM" },
375 { 0x61, "Loop_Duration" },
376 { 0x62, "LNA_Path_Selection" },
377 { 0x63, "Serial number" },
378 { 0x64, "HW version" },
379 { 0x65, "Obj. identity and obj. state" },
380 { 0x66, "reserved" },
381 { 0x67, "EAC input definition" },
382 { 0x68, "EAC id and text" },
383 { 0x69, "HW unit status" },
384 { 0x6A, "SW release version" },
385 { 0x6B, "FW version" },
386 { 0x6C, "Bit_Error_Ratio" },
387 { 0x6D, "RXLEV_with_Attenuation" },
388 { 0x6E, "RXLEV_without_Attenuation" },
389 { 0x6F, "reserved" },
390 { 0x70, "CU_Results" },
391 { 0x71, "reserved" },
392 { 0x72, "LNA_Path_Results" },
393 { 0x73, "RTE Results" },
394 { 0x74, "Real Time" },
395 { 0x75, "RX diversity selection" },
396 { 0x76, "EAC input config" },
397 { 0x77, "Feature support" },
398 { 0x78, "File version" },
399 { 0x79, "Outputs" },
400 { 0x7A, "FU parameters" },
401 { 0x7B, "Diagnostic info" },
402 { 0x7C, "FU BSIC" },
403 { 0x7D, "TRX Configuration" },
404 { 0x7E, "Download status" },
405 { 0x7F, "RX difference limit" },
406 { 0x80, "TRX HW capability" },
407 { 0x81, "Common HW config" },
408 { 0x82, "Autoconfiguration pool size" },
409 { 0x83, "TRE diagnostic info" },
410 { 0x84, "TRE object identity" },
411 { 0x85, "New TRE Info" },
412 { 0x86, "Acknowledgement period" },
413 { 0x87, "Synchronization mode" },
414 { 0x88, "reserved" },
415 { 0x89, "Block Control Data" },
416 { 0x8A, "SW load mode" },
417 { 0x8B, "Recommended recovery action" },
418 { 0x8C, "BSC BCF id" },
419 { 0x8D, "Q1 baud rate" },
420 { 0x8E, "Allocation status" },
421 { 0x8F, "Functional entity number" },
422 { 0x90, "Transmission delay" },
423 { 0x91, "Loop Duration ms" },
424 { 0x92, "Logical channel" },
425 { 0x93, "Q1 address" },
426 { 0x94, "Alarm detail" },
427 { 0x95, "Cabinet type" },
428 { 0x96, "HW unit existence" },
429 { 0x97, "RF power parameters" },
430 { 0x98, "Message scenario" },
431 { 0x99, "HW unit max amount" },
432 { 0x9A, "Master TRX" },
433 { 0x9B, "Transparent data" },
434 { 0x9C, "BSC topology info" },
435 { 0x9D, "Air i/f modulation" },
436 { 0x9E, "LCS Q1 command data" },
437 { 0x9F, "Frame number offset" },
438 { 0xA0, "Abis TSL" },
439 { 0xA1, "Dynamic pool info" },
440 { 0xA2, "LCS LLP data" },
441 { 0xA3, "LCS Q1 answer data" },
442 { 0xA4, "DFCA FU Radio Definition" },
443 { 0xA5, "Antenna hopping" },
444 { 0xA6, "Field record sequence number" },
445 { 0xA7, "Timeslot offslot" },
446 { 0xA8, "EPCR capability" },
447 { 0xA9, "Connectsite optional element" },
448 { 0xAA, "TSC" },
449 { 0xAB, "Special TX Power Setting" },
450 { 0xAC, "Optional sync settings" },
451 { 0xFA, "Abis If parameters" },
452 { 0, NULL }
453};
454
455static const char *get_element_name_string(uint16_t element)
Dieter Spaar16646022011-07-28 00:01:50 +0200456{
Harald Welte44d26112011-07-28 00:43:13 +0200457 return get_value_string(nokia_element_name, element);
Dieter Spaar16646022011-07-28 00:01:50 +0200458}
459
Harald Welte3c3003f2011-07-28 00:28:20 +0200460static const struct value_string nokia_bts_types[] = {
461 { 0x0a, "MetroSite GSM 900" },
462 { 0x0b, "MetroSite GSM 1800" },
463 { 0x0c, "MetroSite GSM 1900 (PCS)" },
464 { 0x0d, "MetroSite GSM 900 & 1800" },
465 { 0x0e, "InSite GSM 900" },
466 { 0x0f, "InSite GSM 1800" },
467 { 0x10, "InSite GSM 1900" },
468 { 0x11, "UltraSite GSM 900" },
469 { 0x12, "UltraSite GSM 1800" },
470 { 0x13, "UltraSite GSM/US-TDMA 1900" },
471 { 0x14, "UltraSite GSM 900 & 1800" },
472 { 0x16, "UltraSite GSM/US-TDMA 850" },
473 { 0x18, "MetroSite GSM/US-TDMA 850" },
474 { 0x19, "UltraSite GSM 800/1900" },
475 { 0, NULL }
476};
477
478static const char *get_bts_type_string(uint8_t type)
Dieter Spaar16646022011-07-28 00:01:50 +0200479{
Harald Welte3c3003f2011-07-28 00:28:20 +0200480 return get_value_string(nokia_bts_types, type);
Dieter Spaar16646022011-07-28 00:01:50 +0200481}
482
Harald Welte3c3003f2011-07-28 00:28:20 +0200483static const struct value_string nokia_severity[] = {
484 { 0, "indeterminate" },
485 { 1, "critical" },
486 { 2, "major" },
487 { 3, "minor" },
488 { 4, "warning" },
489 { 0, NULL }
490};
491
492static const char *get_severity_string(uint8_t severity)
Dieter Spaar16646022011-07-28 00:01:50 +0200493{
Harald Welte3c3003f2011-07-28 00:28:20 +0200494 return get_value_string(nokia_severity, severity);
Dieter Spaar16646022011-07-28 00:01:50 +0200495}
496
497/* TODO: put in a separate file ? */
498
499/* some message IDs */
500
501#define NOKIA_MSG_CONF_DATA 128
502#define NOKIA_MSG_ACK 129
503#define NOKIA_MSG_OMU_STARTED 130
504#define NOKIA_MSG_START_DOWNLOAD_REQ 131
505#define NOKIA_MSG_MF_REQ 132
506#define NOKIA_MSG_RESET_REQ 134
507#define NOKIA_MSG_CONF_REQ 136
508#define NOKIA_MSG_CONF_COMPLETE 142
509#define NOKIA_MSG_BLOCK_CTRL_REQ 168
510#define NOKIA_MSG_STATE_CHANGED 172
511#define NOKIA_MSG_ALARM 174
512
513/* some element IDs */
514
515#define NOKIA_EI_BTS_TYPE 0x13
516#define NOKIA_EI_ACK 0x23
517#define NOKIA_EI_ADD_INFO 0x51
518#define NOKIA_EI_SEVERITY 0x4B
519#define NOKIA_EI_ALARM_DETAIL 0x94
520
521#define OM_ALLOC_SIZE 1024
522#define OM_HEADROOM_SIZE 128
523
Harald Weltebda367c2011-07-28 00:03:49 +0200524static uint8_t fu_config_template[] = {
525 0x7F, 0x7A, 0x39,
526 /* ID = 0x7A (FU parameters) ## constructed ## */
527 /* length = 57 */
528 /* [3] */
Dieter Spaar16646022011-07-28 00:01:50 +0200529
Harald Weltebda367c2011-07-28 00:03:49 +0200530 0x5F, 0x40, 0x04,
531 /* ID = 0x40 (Object identity) */
532 /* length = 4 */
533 /* [6] */
534 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200535
Harald Weltebda367c2011-07-28 00:03:49 +0200536 0x41, 0x02,
537 /* ID = 0x01 (Ny1) */
538 /* length = 2 */
539 /* [12] */
540 0x00, 0x05,
Dieter Spaar16646022011-07-28 00:01:50 +0200541
Harald Weltebda367c2011-07-28 00:03:49 +0200542 0x42, 0x02,
543 /* ID = 0x02 (T3105_F) */
544 /* length = 2 */
545 /* [16] */
Harald Welte67161f22012-06-03 13:01:47 +0200546 0x00, 0x28, /* FIXME: use net->T3105 */
Dieter Spaar16646022011-07-28 00:01:50 +0200547
Harald Weltebda367c2011-07-28 00:03:49 +0200548 0x50, 0x02,
549 /* ID = 0x10 (T3105_D) */
550 /* length = 2 */
551 /* [20] */
Harald Welte67161f22012-06-03 13:01:47 +0200552 0x00, 0x28, /* FIXME: use net->T3105 */
Dieter Spaar16646022011-07-28 00:01:50 +0200553
Harald Weltebda367c2011-07-28 00:03:49 +0200554 0x43, 0x05,
555 /* ID = 0x03 (Interference band limits) */
556 /* length = 5 */
557 /* [24] */
558 0x0F, 0x1B, 0x27, 0x33, 0x3F,
Dieter Spaar16646022011-07-28 00:01:50 +0200559
Harald Weltebda367c2011-07-28 00:03:49 +0200560 0x44, 0x02,
561 /* ID = 0x04 (Interference report timer in secs) */
562 /* length = 2 */
563 /* [31] */
564 0x00, 0x10,
Dieter Spaar16646022011-07-28 00:01:50 +0200565
Harald Weltebda367c2011-07-28 00:03:49 +0200566 0x47, 0x01,
567 /* ID = 0x07 (RACH report timer in secs) */
568 /* length = 1 */
569 /* [35] */
570 0x1E,
Dieter Spaar16646022011-07-28 00:01:50 +0200571
Harald Weltebda367c2011-07-28 00:03:49 +0200572 0x4C, 0x10,
573 /* ID = 0x0C (Cell allocation bitmap) ####### */
574 /* length = 16 */
575 /* [38] */
576 0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
577 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200578
Harald Weltebda367c2011-07-28 00:03:49 +0200579 0x59, 0x01,
580 /* ID = 0x19 (Averaging period) */
581 /* length = 1 */
582 /* [56] */
583 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +0200584
Harald Weltebda367c2011-07-28 00:03:49 +0200585 0x5E, 0x01,
586 /* ID = 0x1E ((RF max power reduction)) */
587 /* length = 1 */
588 /* [59] */
589 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200590
Harald Weltebda367c2011-07-28 00:03:49 +0200591 0x7F, 0x46, 0x11,
592 /* ID = 0x46 (FU channel configuration) ## constructed ## */
593 /* length = 17 */
594 /* [63] */
Dieter Spaar16646022011-07-28 00:01:50 +0200595
Harald Weltebda367c2011-07-28 00:03:49 +0200596 0x5F, 0x40, 0x04,
597 /* ID = 0x40 (Object identity) */
598 /* length = 4 */
599 /* [66] */
600 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200601
Harald Weltebda367c2011-07-28 00:03:49 +0200602 0x45, 0x08,
603 /* ID = 0x05 (Channel configuration per TS) */
604 /* length = 8 */
605 /* [72] */
606 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
Dieter Spaar16646022011-07-28 00:01:50 +0200607
Harald Weltebda367c2011-07-28 00:03:49 +0200608 0x7F, 0x65, 0x0B,
609 /* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */
610 /* length = 11 */
611 /* [83] */
Dieter Spaar16646022011-07-28 00:01:50 +0200612
Harald Weltebda367c2011-07-28 00:03:49 +0200613 0x5F, 0x40, 0x04,
614 /* ID = 0x40 (Object identity) */
615 /* length = 4 */
616 /* [86] */
617 0x00, 0x04, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200618
Harald Weltebda367c2011-07-28 00:03:49 +0200619 0x5F, 0x44, 0x01,
620 /* ID = 0x44 (Object current state) */
621 /* length = 1 */
622 /* [93] */
623 0x03,
Dieter Spaar16646022011-07-28 00:01:50 +0200624
Harald Weltebda367c2011-07-28 00:03:49 +0200625 0x7F, 0x7C, 0x0A,
626 /* ID = 0x7C (FU BSIC) ## constructed ## */
627 /* length = 10 */
628 /* [97] */
Dieter Spaar16646022011-07-28 00:01:50 +0200629
Harald Weltebda367c2011-07-28 00:03:49 +0200630 0x5F, 0x40, 0x04,
631 /* ID = 0x40 (Object identity) */
632 /* length = 4 */
633 /* [100] */
634 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200635
Harald Weltebda367c2011-07-28 00:03:49 +0200636 0x46, 0x01,
637 /* ID = 0x06 (BSIC) */
638 /* length = 1 */
639 /* [106] */
640 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200641
Harald Weltebda367c2011-07-28 00:03:49 +0200642 0x7F, 0x48, 0x0B,
643 /* ID = 0x48 (ARFN of a CU) ## constructed ## */
644 /* length = 11 */
645 /* [110] */
Dieter Spaar16646022011-07-28 00:01:50 +0200646
Harald Weltebda367c2011-07-28 00:03:49 +0200647 0x5F, 0x40, 0x04,
648 /* ID = 0x40 (Object identity) */
649 /* length = 4 */
650 /* [113] */
651 0x00, 0x08, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200652
Harald Weltebda367c2011-07-28 00:03:49 +0200653 0x4A, 0x02,
654 /* ID = 0x0A (ARFN) ####### */
655 /* length = 2 */
656 /* [119] */
657 0x03, 0x62,
Dieter Spaar16646022011-07-28 00:01:50 +0200658
Harald Weltebda367c2011-07-28 00:03:49 +0200659 0x7F, 0x49, 0x59,
660 /* ID = 0x49 (FU radio definition) ## constructed ## */
661 /* length = 89 */
662 /* [124] */
Dieter Spaar16646022011-07-28 00:01:50 +0200663
Harald Weltebda367c2011-07-28 00:03:49 +0200664 0x5F, 0x40, 0x04,
665 /* ID = 0x40 (Object identity) */
666 /* length = 4 */
667 /* [127] */
668 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200669
Harald Weltebda367c2011-07-28 00:03:49 +0200670 0x4D, 0x50,
671 /* ID = 0x0D (Radio definition per TS) ####### */
672 /* length = 80 */
673 /* [133] */
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MA */
675 0x03, 0x62, /* HSN, MAIO or ARFCN if no hopping */
676 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
677 0x03, 0x62,
678 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
679 0x03, 0x62,
680 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
681 0x03, 0x62,
682 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
683 0x03, 0x62,
684 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
685 0x03, 0x62,
686 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
687 0x03, 0x62,
688 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
689 0x03, 0x62,
Dieter Spaar16646022011-07-28 00:01:50 +0200690};
691
692/* TODO: put in a separate file ? */
693
694/*
Harald Weltecde57942011-07-28 00:13:46 +0200695 build the configuration for each TRX
Dieter Spaar16646022011-07-28 00:01:50 +0200696*/
697
Harald Weltebda367c2011-07-28 00:03:49 +0200698static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id,
699 uint8_t * fu_config, int *hopping)
Dieter Spaar16646022011-07-28 00:01:50 +0200700{
Harald Weltebda367c2011-07-28 00:03:49 +0200701 int i;
Dieter Spaar16646022011-07-28 00:01:50 +0200702
Harald Weltebda367c2011-07-28 00:03:49 +0200703 *hopping = 0;
704
705 memcpy(fu_config, fu_config_template, sizeof(fu_config_template));
706
707 /* set ID */
708
709 fu_config[6 + 2] = id;
710 fu_config[66 + 2] = id;
711 fu_config[86 + 2] = id;
712 fu_config[100 + 2] = id;
713 fu_config[113 + 2] = id;
714 fu_config[127 + 2] = id;
715
716 /* set ARFCN */
717
718 uint16_t arfcn = trx->arfcn;
719
720 fu_config[119] = arfcn >> 8;
721 fu_config[119 + 1] = arfcn & 0xFF;
722
723 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
724 struct gsm_bts_trx_ts *ts = &trx->ts[i];
725
726 if (ts->hopping.enabled) {
727 /* reverse order */
728 int j;
729 for (j = 0; j < ts->hopping.ma_len; j++)
730 fu_config[133 + (i * 10) + (7 - j)] =
731 ts->hopping.ma_data[j];
732 fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn;
733 fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio;
734 *hopping = 1;
735 } else {
736 fu_config[133 + 8 + (i * 10)] = arfcn >> 8;
737 fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF;
738 }
739 }
740
741 /* set BSIC */
742
Harald Weltecde57942011-07-28 00:13:46 +0200743 /*
Harald Weltebda367c2011-07-28 00:03:49 +0200744 Attention: all TRX except the first one seem to get the TSC
745 from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION,
Harald Weltecde57942011-07-28 00:13:46 +0200746 GSM 04.08 CHANNEL DESCRIPTION).
747 There was a bug in rsl_chan_activate_lchan() setting this parameter.
Harald Weltebda367c2011-07-28 00:03:49 +0200748 */
749
750 uint8_t bsic = trx->bts->bsic;
751
752 fu_config[106] = bsic;
753
754 /* set CA */
755
756 if (generate_cell_chan_list(&fu_config[38], trx->bts) != 0) {
757 fprintf(stderr, "generate_cell_chan_list failed\n");
758 return 0;
759 }
760
761 /* set channel configuration */
762
763 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
764 struct gsm_bts_trx_ts *ts = &trx->ts[i];
765 uint8_t chan_config;
766
767 /*
768 0 = FCCH + SCH + BCCH + CCCH
769 1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4
770 2 = BCCH + CCCH (This combination is not used in any BTS)
771 3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH
772 4 = SDCCH/8 + SACCH/8
773 5 = SDCCH/8 with SDCCH2 used as CBCH
774 6 = TCH/F + FACCH/F + SACCH/F
775 7 = E-RACH (Talk family)
776 9 = Dual rate (capability for TCH/F and TCH/H)
777 10 = reserved for BTS internal use
Harald Weltecde57942011-07-28 00:13:46 +0200778 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (can be used in GPRS release 2).
779 0xFF = spare TS
Harald Weltebda367c2011-07-28 00:03:49 +0200780 */
781
782 if (ts->pchan == GSM_PCHAN_NONE)
783 chan_config = 0xFF;
784 else if (ts->pchan == GSM_PCHAN_CCCH)
785 chan_config = 0;
786 else if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4)
787 chan_config = 1;
788 else if (ts->pchan == GSM_PCHAN_TCH_F)
789 chan_config = 6; /* 9 should work too */
790 else if (ts->pchan == GSM_PCHAN_TCH_H)
791 chan_config = 9;
792 else if (ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C)
793 chan_config = 4;
794 else if (ts->pchan == GSM_PCHAN_PDCH)
795 chan_config = 11;
796 else {
797 fprintf(stderr,
798 "unsupported channel config %d for timeslot %d\n",
799 ts->pchan, i);
800 return 0;
801 }
802
803 fu_config[72 + i] = chan_config;
804 }
805 return sizeof(fu_config_template);
Dieter Spaar16646022011-07-28 00:01:50 +0200806}
807
808/* TODO: put in a separate file ? */
809
Harald Weltebda367c2011-07-28 00:03:49 +0200810static uint8_t bts_config_1[] = {
811 0x4E, 0x02,
812 /* ID = 0x0E (Frame number) */
813 /* length = 2 */
814 /* [2] */
815 0xFF, 0xFF,
816
817 0x5F, 0x4E, 0x02,
818 /* ID = 0x4E (RX antenna supervision period) */
819 /* length = 2 */
820 /* [7] */
821 0xFF, 0xFF,
822
823 0x5F, 0x50, 0x02,
824 /* ID = 0x50 (Sector configuration) */
825 /* length = 2 */
826 /* [12] */
827 0x01, 0x01,
828};
829
830static uint8_t bts_config_2[] = {
831 0x55, 0x02,
832 /* ID = 0x15 (Hopping mode) */
833 /* length = 2 */
834 /* [2] */
835 0x01, 0x00,
836
837 0x5F, 0x75, 0x02,
838 /* ID = 0x75 (RX diversity selection) */
839 /* length = 2 */
840 /* [7] */
841 0x01, 0x01,
842};
843
844static uint8_t bts_config_3[] = {
845 0x5F, 0x20, 0x02,
846 /* ID = 0x20 (Extended cell radius) */
847 /* length = 2 */
848 /* [3] */
849 0x01, 0x00,
850};
851
852static uint8_t bts_config_4[] = {
853 0x5F, 0x74, 0x09,
854 /* ID = 0x74 (Real Time) */
855 /* length = 9 */
856 /* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
857 0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00,
858 0x00,
859
860 0x5F, 0x76, 0x03,
861 /* ID = 0x76 (EAC input config) */
862 /* length = 3 */
863 /* [15] */
864 0x01, 0x01, 0x00,
865
866 0x5F, 0x76, 0x03,
867 /* ID = 0x76 (EAC input config) */
868 /* length = 3 */
869 /* [21] */
870 0x02, 0x01, 0x00,
871
872 0x5F, 0x76, 0x03,
873 /* ID = 0x76 (EAC input config) */
874 /* length = 3 */
875 /* [27] */
876 0x03, 0x01, 0x00,
877
878 0x5F, 0x76, 0x03,
879 /* ID = 0x76 (EAC input config) */
880 /* length = 3 */
881 /* [33] */
882 0x04, 0x01, 0x00,
883
884 0x5F, 0x76, 0x03,
885 /* ID = 0x76 (EAC input config) */
886 /* length = 3 */
887 /* [39] */
888 0x05, 0x01, 0x00,
889
890 0x5F, 0x76, 0x03,
891 /* ID = 0x76 (EAC input config) */
892 /* length = 3 */
893 /* [45] */
894 0x06, 0x01, 0x00,
895
896 0x5F, 0x76, 0x03,
897 /* ID = 0x76 (EAC input config) */
898 /* length = 3 */
899 /* [51] */
900 0x07, 0x01, 0x00,
901
902 0x5F, 0x76, 0x03,
903 /* ID = 0x76 (EAC input config) */
904 /* length = 3 */
905 /* [57] */
906 0x08, 0x01, 0x00,
907
908 0x5F, 0x76, 0x03,
909 /* ID = 0x76 (EAC input config) */
910 /* length = 3 */
911 /* [63] */
912 0x09, 0x01, 0x00,
913
914 0x5F, 0x76, 0x03,
915 /* ID = 0x76 (EAC input config) */
916 /* length = 3 */
917 /* [69] */
918 0x0A, 0x01, 0x00,
919};
920
921static uint8_t bts_config_insite[] = {
922 0x4E, 0x02,
923 /* ID = 0x0E (Frame number) */
924 /* length = 2 */
925 /* [2] */
926 0xFF, 0xFF,
927
928 0x5F, 0x4E, 0x02,
929 /* ID = 0x4E (RX antenna supervision period) */
930 /* length = 2 */
931 /* [7] */
932 0xFF, 0xFF,
933
934 0x5F, 0x50, 0x02,
935 /* ID = 0x50 (Sector configuration) */
936 /* length = 2 */
937 /* [12] */
938 0x01, 0x01,
939
940 0x55, 0x02,
941 /* ID = 0x15 (Hopping mode) */
942 /* length = 2 */
943 /* [16] */
944 0x01, 0x00,
945
946 0x5F, 0x20, 0x02,
947 /* ID = 0x20 (Extended cell radius) */
948 /* length = 2 */
949 /* [21] */
950 0x01, 0x00,
951
952 0x5F, 0x74, 0x09,
953 /* ID = 0x74 (Real Time) */
954 /* length = 9 */
955 /* [26] */
956 0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00,
957 0x00,
958};
959
960void set_real_time(uint8_t * real_time)
Dieter Spaar16646022011-07-28 00:01:50 +0200961{
Harald Weltebda367c2011-07-28 00:03:49 +0200962 time_t t;
963 struct tm *tm;
Dieter Spaar16646022011-07-28 00:01:50 +0200964
Harald Weltebda367c2011-07-28 00:03:49 +0200965 t = time(NULL);
966 tm = localtime(&t);
Dieter Spaar16646022011-07-28 00:01:50 +0200967
Harald Weltebda367c2011-07-28 00:03:49 +0200968 /* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
Dieter Spaar16646022011-07-28 00:01:50 +0200969
Harald Weltebda367c2011-07-28 00:03:49 +0200970 real_time[0] = (1900 + tm->tm_year) >> 8;
971 real_time[1] = (1900 + tm->tm_year) & 0xFF;
972 real_time[2] = tm->tm_mon + 1;
973 real_time[3] = tm->tm_mday;
974 real_time[4] = tm->tm_hour;
975 real_time[5] = tm->tm_min;
976 real_time[6] = tm->tm_sec;
977 real_time[7] = 0;
978 real_time[8] = 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200979}
980
981/* TODO: put in a separate file ? */
982
983/*
Dieter Spaar16646022011-07-28 00:01:50 +0200984 build the configuration data
Dieter Spaar16646022011-07-28 00:01:50 +0200985*/
986
Harald Weltebda367c2011-07-28 00:03:49 +0200987static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config,
988 int need_hopping)
Dieter Spaar16646022011-07-28 00:01:50 +0200989{
Harald Weltebda367c2011-07-28 00:03:49 +0200990 /* is it an InSite BTS ? */
991 if (bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */
992 if (n_trx != 1) {
993 fprintf(stderr, "InSite has only one TRX\n");
994 return 0;
995 }
996 if (need_hopping != 0) {
997 fprintf(stderr, "InSite does not support hopping\n");
998 return 0;
999 }
1000 memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite));
1001 set_real_time(&fu_config[26]);
1002 return sizeof(bts_config_insite);
1003 }
Dieter Spaar16646022011-07-28 00:01:50 +02001004
Harald Weltebda367c2011-07-28 00:03:49 +02001005 int len = 0;
1006 int i;
1007
1008 memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1));
1009
1010 /* set sector configuration */
1011 fu_config[len + 12 - 1] = 1 + n_trx; /* len */
1012 for (i = 0; i < n_trx; i++)
1013 fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF);
1014
1015 len += (sizeof(bts_config_1) + (n_trx - 1));
1016
1017 memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2));
1018 /* set hopping mode (Baseband and RF hopping work for the MetroSite) */
1019 if (need_hopping)
1020 fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */
1021 len += sizeof(bts_config_2);
1022
1023 /* set extended cell radius for each TRX */
1024 for (i = 0; i < n_trx; i++) {
1025 memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3));
1026 fu_config[len + 3] = ((i + 1) & 0xFF);
1027 len += sizeof(bts_config_3);
1028 }
1029
1030 memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4));
1031 set_real_time(&fu_config[len + 3]);
1032 len += sizeof(bts_config_4);
1033
1034 return len;
Dieter Spaar16646022011-07-28 00:01:50 +02001035}
1036
1037/* TODO: put in a separate file ? */
1038
1039static struct msgb *nm_msgb_alloc(void)
1040{
Harald Weltebda367c2011-07-28 00:03:49 +02001041 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
Dieter Spaar16646022011-07-28 00:01:50 +02001042}
1043
1044/* TODO: put in a separate file ? */
1045
1046struct abis_om_nokia_hdr {
Harald Weltebda367c2011-07-28 00:03:49 +02001047 uint8_t msg_type;
1048 uint8_t spare;
1049 uint16_t reference;
1050 uint8_t data[0];
Dieter Spaar16646022011-07-28 00:01:50 +02001051} __attribute__ ((packed));
1052
1053#define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr))
1054
Harald Weltebda367c2011-07-28 00:03:49 +02001055static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref,
1056 uint8_t * data, int len_data)
Dieter Spaar16646022011-07-28 00:01:50 +02001057{
Harald Weltebda367c2011-07-28 00:03:49 +02001058 struct abis_om_hdr *oh;
1059 struct abis_om_nokia_hdr *noh;
1060 struct msgb *msg = nm_msgb_alloc();
Dieter Spaar16646022011-07-28 00:01:50 +02001061
Harald Weltebda367c2011-07-28 00:03:49 +02001062 oh = (struct abis_om_hdr *)msgb_put(msg,
1063 ABIS_OM_NOKIA_HDR_SIZE + len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001064
Harald Weltebda367c2011-07-28 00:03:49 +02001065 oh->mdisc = ABIS_OM_MDISC_FOM;
1066 oh->placement = ABIS_OM_PLACEMENT_ONLY;
1067 oh->sequence = 0;
1068 oh->length = sizeof(struct abis_om_nokia_hdr) + len_data;
1069
1070 noh = (struct abis_om_nokia_hdr *)oh->data;
1071
1072 noh->msg_type = msg_type;
1073 noh->spare = 0;
1074 noh->reference = htons(ref);
1075 memcpy(noh->data, data, len_data);
1076
1077 DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type));
1078
1079 return abis_nm_sendmsg(bts, msg);
Dieter Spaar16646022011-07-28 00:01:50 +02001080}
1081
1082/* TODO: put in a separate file ? */
1083
1084static uint8_t download_req[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001085 0x5F, 0x25, 0x0B,
1086 /* ID = 0x25 (File identity) */
1087 /* length = 11 */
1088 /* [3] */
1089 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
1090 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001091
Harald Weltebda367c2011-07-28 00:03:49 +02001092 0x5F, 0x78, 0x03,
1093 /* ID = 0x78 (File version) */
1094 /* length = 3 */
1095 /* [17] */
1096 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001097
Harald Weltebda367c2011-07-28 00:03:49 +02001098 0x5F, 0x81, 0x0A, 0x01,
1099 /* ID = 0x8A (SW load mode) */
1100 /* length = 1 */
1101 /* [24] */
1102 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001103
Harald Weltebda367c2011-07-28 00:03:49 +02001104 0x5F, 0x81, 0x06, 0x01,
1105 /* ID = 0x86 (Acknowledgement period) */
1106 /* length = 1 */
1107 /* [29] */
1108 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001109};
1110
1111static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref)
1112{
Harald Weltebda367c2011-07-28 00:03:49 +02001113 uint8_t *data = download_req;
1114 int len_data = sizeof(download_req);
1115
1116 return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data,
1117 len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001118}
1119
1120/* TODO: put in a separate file ? */
1121
1122static uint8_t ack[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001123 0x5F, 0x23, 0x01,
1124 /* ID = 0x23 (Ack-Nack) */
1125 /* length = 1 */
1126 /* [3] */
1127 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001128};
1129
1130static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref)
1131{
Harald Weltebda367c2011-07-28 00:03:49 +02001132 uint8_t *data = ack;
1133 int len_data = sizeof(ack);
1134
1135 return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001136}
1137
1138/* TODO: put in a separate file ? */
1139
1140static uint8_t reset[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001141 0x5F, 0x40, 0x04,
1142 /* ID = 0x40 (Object identity) */
1143 /* length = 4 */
1144 /* [3] */
1145 0x00, 0x01, 0xFF, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +02001146};
1147
1148static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref)
1149{
Harald Weltebda367c2011-07-28 00:03:49 +02001150 uint8_t *data = reset;
1151 int len_data = sizeof(reset);
Sipos Csaba56e17662015-02-07 13:27:36 +01001152 LOGP(DLINP, LOGL_INFO, "Nokia BTS reset timer: %d\n", bts->nokia.bts_reset_timer_cnf);
Harald Weltebda367c2011-07-28 00:03:49 +02001153 return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001154}
1155
1156/* TODO: put in a separate file ? */
1157
Harald Weltebda367c2011-07-28 00:03:49 +02001158static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type,
1159 uint16_t ref, uint8_t * data, int len)
Dieter Spaar16646022011-07-28 00:01:50 +02001160{
Harald Weltebda367c2011-07-28 00:03:49 +02001161 int len_remain, len_to_send, max_send;
1162 int seq = 0;
1163 int ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001164
Harald Weltebda367c2011-07-28 00:03:49 +02001165 len_remain = len;
1166
1167 while (len_remain) {
1168 struct abis_om_hdr *oh;
1169 struct abis_om_nokia_hdr *noh;
1170 struct msgb *msg = nm_msgb_alloc();
1171
1172 if (seq == 0)
1173 max_send = 256 - sizeof(struct abis_om_nokia_hdr);
1174 else
1175 max_send = 256;
1176
1177 if (len_remain > max_send) {
1178 len_to_send = max_send;
1179
1180 if (seq == 0) {
1181 /* first segment */
1182 oh = (struct abis_om_hdr *)msgb_put(msg,
1183 ABIS_OM_NOKIA_HDR_SIZE
1184 +
1185 len_to_send);
1186
1187 oh->mdisc = ABIS_OM_MDISC_FOM;
1188 oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */
1189 oh->sequence = seq;
1190 oh->length = 0; /* 256 bytes */
1191
1192 noh = (struct abis_om_nokia_hdr *)oh->data;
1193
1194 noh->msg_type = msg_type;
1195 noh->spare = 0;
1196 noh->reference = htons(ref);
1197 memcpy(noh->data, data, len_to_send);
1198 } else {
1199 /* segment in between */
1200 oh = (struct abis_om_hdr *)msgb_put(msg,
1201 sizeof
1202 (struct
1203 abis_om_hdr)
1204 +
1205 len_to_send);
1206
1207 oh->mdisc = ABIS_OM_MDISC_FOM;
1208 oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */
1209 oh->sequence = seq;
1210 oh->length = 0; /* 256 bytes */
1211
1212 memcpy(oh->data, data, len_to_send);
1213 }
1214 } else {
1215
1216 len_to_send = len_remain;
1217
1218 /* check if message fits in a single segment */
1219
1220 if (seq == 0)
1221 return abis_nm_send(bts, msg_type, ref, data,
1222 len_to_send);
1223
1224 /* last segment */
1225
1226 oh = (struct abis_om_hdr *)msgb_put(msg,
1227 sizeof(struct
1228 abis_om_hdr)
1229 + len_to_send);
1230
1231 oh->mdisc = ABIS_OM_MDISC_FOM;
1232 oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */
1233 oh->sequence = seq;
1234 oh->length = len_to_send;
1235
1236 memcpy(oh->data, data, len_to_send);
1237 }
1238
1239 DEBUGPC(DNM, "Sending multi-segment %d\n", seq);
1240
1241 ret = abis_nm_sendmsg(bts, msg);
1242 if (ret < 0)
1243 return ret;
1244
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001245 nokia_abis_nm_queue_send_next(bts);
Harald Weltebda367c2011-07-28 00:03:49 +02001246
1247 /* next segment */
1248 len_remain -= len_to_send;
1249 data += len_to_send;
1250 seq++;
1251 }
Pau Espin Pedrol39fb1fb2018-03-26 18:09:19 +02001252
1253 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001254}
1255
1256/* TODO: put in a separate file ? */
1257
1258static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type)
1259{
Harald Weltebda367c2011-07-28 00:03:49 +02001260 struct gsm_bts_trx *trx;
1261 uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */
1262 int len = 0;
1263 int idx = 0;
1264 int ret;
1265 int hopping = 0;
1266 int need_hopping = 0;
1267
1268 memset(config, 0, sizeof(config));
1269
1270 llist_for_each_entry(trx, &bts->trx_list, list) {
1271#if 0 /* debugging */
1272 printf("TRX\n");
1273 printf(" arfcn: %d\n", trx->arfcn);
1274 printf(" bsic: %d\n", trx->bts->bsic);
1275 uint8_t ca[20];
1276 memset(ca, 0xFF, sizeof(ca));
1277 ret = generate_cell_chan_list(ca, trx->bts);
1278 printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca)));
1279 int i;
1280 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
1281 struct gsm_bts_trx_ts *ts = &trx->ts[i];
1282
1283 printf(" pchan %d: %d\n", i, ts->pchan);
1284 }
Dieter Spaar16646022011-07-28 00:01:50 +02001285#endif
Harald Weltebda367c2011-07-28 00:03:49 +02001286 ret = make_fu_config(trx, idx + 1, config + len, &hopping);
1287 need_hopping |= hopping;
1288 len += ret;
1289
1290 idx++;
1291 }
1292
1293 ret = make_bts_config(bts_type, idx, config + len, need_hopping);
1294 len += ret;
1295
1296#if 0 /* debugging */
1297 dump_elements(config, len);
1298#endif
1299
1300 return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config,
1301 len);
Dieter Spaar16646022011-07-28 00:01:50 +02001302}
1303
1304#define GET_NEXT_BYTE if(idx >= len) return 0; \
Harald Weltebda367c2011-07-28 00:03:49 +02001305 ub = data[idx++];
Dieter Spaar16646022011-07-28 00:01:50 +02001306
Harald Weltebda367c2011-07-28 00:03:49 +02001307static int find_element(uint8_t * data, int len, uint16_t id, uint8_t * value,
1308 int max_value)
1309{
1310 uint8_t ub;
1311 int idx = 0;
1312 int found = 0;
Holger Hans Peter Freythera5050b12012-09-11 11:55:03 +02001313 int constructed __attribute__((unused));
Harald Weltebda367c2011-07-28 00:03:49 +02001314 uint16_t id_value;
1315
1316 for (;;) {
1317
1318 GET_NEXT_BYTE;
1319
1320 /* encoding bit, construced means that other elements are contained */
1321 constructed = ((ub & 0x20) ? 1 : 0);
1322
1323 if ((ub & 0x1F) == 0x1F) {
1324 /* fixed pattern, ID follows */
1325 GET_NEXT_BYTE; /* ID */
1326 id_value = ub & 0x7F;
1327 if (ub & 0x80) {
1328 /* extension bit */
1329 GET_NEXT_BYTE; /* ID low part */
1330 id_value = (id_value << 7) | (ub & 0x7F);
1331 }
1332 if (id_value == id)
1333 found = 1;
1334 } else {
1335 id_value = (ub & 0x3F);
1336 if (id_value == id)
1337 found = 1;
1338 }
1339
1340 GET_NEXT_BYTE; /* length */
1341
1342 if (found) {
1343 /* get data */
1344 uint8_t n = ub;
1345 uint8_t i;
1346 for (i = 0; i < n; i++) {
1347 GET_NEXT_BYTE;
1348 if (max_value <= 0)
1349 return -1; /* buffer too small */
1350 *value = ub;
1351 value++;
1352 max_value--;
1353 }
1354 return n; /* length */
1355 } else {
1356 /* skip data */
1357 uint8_t n = ub;
1358 uint8_t i;
1359 for (i = 0; i < n; i++) {
1360 GET_NEXT_BYTE;
1361 }
1362 }
1363 }
1364 return 0; /* not found */
Dieter Spaar16646022011-07-28 00:01:50 +02001365}
1366
Harald Weltebda367c2011-07-28 00:03:49 +02001367static int dump_elements(uint8_t * data, int len)
1368{
1369 uint8_t ub;
1370 int idx = 0;
1371 int constructed;
1372 uint16_t id_value;
1373 static char indent[100] = ""; /* TODO: move static to BTS context */
Dieter Spaar16646022011-07-28 00:01:50 +02001374
Harald Weltebda367c2011-07-28 00:03:49 +02001375 for (;;) {
1376
1377 GET_NEXT_BYTE;
1378
1379 /* encoding bit, construced means that other elements are contained */
1380 constructed = ((ub & 0x20) ? 1 : 0);
1381
1382 if ((ub & 0x1F) == 0x1F) {
1383 /* fixed pattern, ID follows */
1384 GET_NEXT_BYTE; /* ID */
1385 id_value = ub & 0x7F;
1386 if (ub & 0x80) {
1387 /* extension bit */
1388 GET_NEXT_BYTE; /* ID low part */
1389 id_value = (id_value << 7) | (ub & 0x7F);
1390 }
1391
1392 } else {
1393 id_value = (ub & 0x3F);
1394 }
1395
1396 GET_NEXT_BYTE; /* length */
1397
1398 printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value,
1399 get_element_name_string(id_value),
1400 constructed ? "** constructed **" : "");
1401 printf("%s length = %d\n", indent, ub);
1402 printf("%s %s\n", indent, osmo_hexdump(data + idx, ub));
1403
1404 if (constructed) {
1405 int indent_len = strlen(indent);
1406 strcat(indent, " ");
1407
1408 dump_elements(data + idx, ub);
1409
1410 indent[indent_len] = 0;
1411 }
1412 /* skip data */
1413 uint8_t n = ub;
1414 uint8_t i;
1415 for (i = 0; i < n; i++) {
1416 GET_NEXT_BYTE;
1417 }
1418 }
1419 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001420}
1421
1422/* TODO: put in a separate file ? */
1423
1424/* taken from abis_nm.c */
1425
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001426static void nokia_abis_nm_queue_send_next(struct gsm_bts *bts)
Dieter Spaar16646022011-07-28 00:01:50 +02001427{
Harald Weltebda367c2011-07-28 00:03:49 +02001428 int wait = 0;
1429 struct msgb *msg;
1430 /* the queue is empty */
1431 while (!llist_empty(&bts->abis_queue)) {
1432 msg = msgb_dequeue(&bts->abis_queue);
1433 wait = OBSC_NM_W_ACK_CB(msg);
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001434 abis_sendmsg(msg);
Dieter Spaar16646022011-07-28 00:01:50 +02001435
Harald Weltebda367c2011-07-28 00:03:49 +02001436 if (wait)
1437 break;
1438 }
Dieter Spaar16646022011-07-28 00:01:50 +02001439
Harald Weltebda367c2011-07-28 00:03:49 +02001440 bts->abis_nm_pend = wait;
Dieter Spaar16646022011-07-28 00:01:50 +02001441}
1442
1443/* TODO: put in a separate file ? */
1444
1445/* timer for restarting OML after BTS reset */
1446
1447static void reset_timer_cb(void *_bts)
1448{
Harald Weltebda367c2011-07-28 00:03:49 +02001449 struct gsm_bts *bts = _bts;
1450 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1451 struct e1inp_line *line;
1452
Harald Weltec8755af2011-07-28 00:22:17 +02001453 bts->nokia.wait_reset = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001454
1455 /* OML link */
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001456 line = e1inp_line_find(e1_link->e1_nr);
Harald Weltebda367c2011-07-28 00:03:49 +02001457 if (!line) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001458 LOGP(DLINP, LOGL_ERROR, "BTS %u OML link referring to "
Harald Weltebda367c2011-07-28 00:03:49 +02001459 "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
1460 return;
1461 }
1462
1463 start_sabm_in_line(line, 0, -1); /* stop all first */
1464 start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */
Dieter Spaar16646022011-07-28 00:01:50 +02001465}
1466
1467/* TODO: put in a separate file ? */
1468
1469/*
1470 This is how the configuration is done:
Dieter Spaar16646022011-07-28 00:01:50 +02001471 - start OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001472 - reset BTS
Dieter Spaar16646022011-07-28 00:01:50 +02001473 - receive ACK, wait some time and restart OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001474 - receive OMU STARTED message, send START DOWNLOAD REQ
Dieter Spaar16646022011-07-28 00:01:50 +02001475 - receive CNF REQ message, send CONF DATA
Dieter Spaar16646022011-07-28 00:01:50 +02001476 - receive ACK, start RSL link(s)
Dieter Spaar16646022011-07-28 00:01:50 +02001477 ACK some other messages received from the BTS.
Harald Weltecde57942011-07-28 00:13:46 +02001478
Dieter Spaar16646022011-07-28 00:01:50 +02001479 Probably its also possible to configure the BTS without a reset, this
1480 has not been tested yet.
1481*/
1482
1483static int abis_nm_rcvmsg_fom(struct msgb *mb)
1484{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001485 struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)mb->dst;
1486 struct gsm_bts *bts = sign_link->trx->bts;
Harald Weltebda367c2011-07-28 00:03:49 +02001487 struct abis_om_hdr *oh = msgb_l2(mb);
1488 struct abis_om_nokia_hdr *noh = msgb_l3(mb);
1489 uint8_t mt = noh->msg_type;
1490 int ret = 0;
1491 uint16_t ref = ntohs(noh->reference);
Harald Weltebda367c2011-07-28 00:03:49 +02001492 uint8_t info[256];
1493 uint8_t ack = 0xFF;
1494 uint8_t severity = 0xFF;
1495 int str_len;
1496 int len_data;
Dieter Spaar16646022011-07-28 00:01:50 +02001497
Harald Weltec8755af2011-07-28 00:22:17 +02001498 if (bts->nokia.wait_reset) {
Harald Weltebda367c2011-07-28 00:03:49 +02001499 LOGP(DNM, LOGL_INFO,
1500 "Ignore message while waiting for reset\n");
1501 return ret;
1502 }
Dieter Spaar16646022011-07-28 00:01:50 +02001503
Harald Weltebda367c2011-07-28 00:03:49 +02001504 if (oh->length < sizeof(struct abis_om_nokia_hdr)) {
1505 LOGP(DNM, LOGL_ERROR, "Message too short\n");
1506 return -EINVAL;
1507 }
1508
1509 len_data = oh->length - sizeof(struct abis_om_nokia_hdr);
1510 LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt));
1511#if 0 /* debugging */
1512 dump_elements(noh->data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001513#endif
Dieter Spaar16646022011-07-28 00:01:50 +02001514
Harald Weltebda367c2011-07-28 00:03:49 +02001515 switch (mt) {
1516 case NOKIA_MSG_OMU_STARTED:
Harald Welte9d2f3772011-07-28 00:19:06 +02001517 if (find_element(noh->data, len_data,
1518 NOKIA_EI_BTS_TYPE, &bts->nokia.bts_type,
1519 sizeof(uint8_t)) == sizeof(uint8_t))
1520 LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n",
1521 bts->nokia.bts_type,
1522 get_bts_type_string(bts->nokia.bts_type));
Harald Weltebda367c2011-07-28 00:03:49 +02001523 else
1524 LOGP(DNM, LOGL_ERROR, "BTS type not found\n");
1525 /* send START_DOWNLOAD_REQ */
1526 abis_nm_download_req(bts, ref);
1527 break;
1528 case NOKIA_MSG_MF_REQ:
1529 break;
1530 case NOKIA_MSG_CONF_REQ:
1531 /* send ACK */
1532 abis_nm_ack(bts, ref);
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001533 nokia_abis_nm_queue_send_next(bts);
Harald Weltebda367c2011-07-28 00:03:49 +02001534 /* send CONF_DATA */
Harald Welte9d2f3772011-07-28 00:19:06 +02001535 abis_nm_send_config(bts, bts->nokia.bts_type);
1536 bts->nokia.configured = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001537 break;
1538 case NOKIA_MSG_ACK:
1539 if (find_element
1540 (noh->data, len_data, NOKIA_EI_ACK, &ack,
1541 sizeof(uint8_t)) == sizeof(uint8_t)) {
1542 LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack);
1543 if (ack != 1) {
1544 LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n",
1545 ack);
1546 /* TODO: properly handle failures (NACK) */
1547 }
1548 } else
1549 LOGP(DNM, LOGL_ERROR, "ACK not found\n");
Dieter Spaar16646022011-07-28 00:01:50 +02001550
Harald Weltebda367c2011-07-28 00:03:49 +02001551 /* TODO: the assumption for the following is that no NACK was received */
1552
1553 /* ACK for reset message ? */
Sylvain Munautc9519462011-10-17 14:04:55 +02001554 if (!bts->nokia.did_reset) {
1555 bts->nokia.did_reset = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001556
1557 /*
1558 TODO: For the InSite processing the received data is
1559 blocked in the driver during reset.
1560 Otherwise the LAPD module might assert because the InSite
1561 sends garbage on the E1 line during reset.
1562 This is done by looking at "wait_reset" in the driver
1563 (function handle_ts1_read()) and ignoring the received data.
1564 It seems to be necessary for the MetroSite too.
1565 */
Harald Weltec8755af2011-07-28 00:22:17 +02001566 bts->nokia.wait_reset = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001567
Pablo Neira Ayuso51215762017-05-08 20:57:52 +02001568 osmo_timer_setup(&bts->nokia.reset_timer,
1569 reset_timer_cb, bts);
Sipos Csaba56e17662015-02-07 13:27:36 +01001570 osmo_timer_schedule(&bts->nokia.reset_timer, bts->nokia.bts_reset_timer_cnf, 0);
Harald Weltebda367c2011-07-28 00:03:49 +02001571
1572 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1573 struct e1inp_line *line;
1574 /* OML link */
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001575 line = e1inp_line_find(e1_link->e1_nr);
Harald Weltebda367c2011-07-28 00:03:49 +02001576 if (!line) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001577 LOGP(DLINP, LOGL_ERROR,
Harald Weltebda367c2011-07-28 00:03:49 +02001578 "BTS %u OML link referring to "
1579 "non-existing E1 line %u\n", bts->nr,
1580 e1_link->e1_nr);
1581 return -ENOMEM;
1582 }
1583
1584 start_sabm_in_line(line, 0, -1); /* stop all first */
1585 }
1586
1587 /* ACK for CONF DATA message ? */
Harald Welte9d2f3772011-07-28 00:19:06 +02001588 if (bts->nokia.configured != 0) {
Harald Weltebda367c2011-07-28 00:03:49 +02001589 /* start TRX (RSL link) */
1590
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001591 struct gsm_e1_subslot *e1_link =
1592 &sign_link->trx->rsl_e1_link;
Harald Weltebda367c2011-07-28 00:03:49 +02001593 struct e1inp_line *line;
1594
Harald Welte9d2f3772011-07-28 00:19:06 +02001595 bts->nokia.configured = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001596
1597 /* RSL Link */
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001598 line = e1inp_line_find(e1_link->e1_nr);
Harald Weltebda367c2011-07-28 00:03:49 +02001599 if (!line) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001600 LOGP(DLINP, LOGL_ERROR,
Harald Weltebda367c2011-07-28 00:03:49 +02001601 "TRX (%u/%u) RSL link referring "
1602 "to non-existing E1 line %u\n",
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001603 sign_link->trx->bts->nr, sign_link->trx->nr,
Harald Weltebda367c2011-07-28 00:03:49 +02001604 e1_link->e1_nr);
1605 return -ENOMEM;
1606 }
1607 /* start TRX */
1608 start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */
1609 }
1610 break;
1611 case NOKIA_MSG_STATE_CHANGED:
1612 /* send ACK */
1613 abis_nm_ack(bts, ref);
1614 break;
1615 case NOKIA_MSG_CONF_COMPLETE:
1616 /* send ACK */
1617 abis_nm_ack(bts, ref);
1618 break;
1619 case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */
1620 /* send ACK (do we have to send an ACK ?) */
1621 abis_nm_ack(bts, ref);
1622 break;
1623 case NOKIA_MSG_ALARM:
1624 find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity,
1625 sizeof(severity));
1626 /* TODO: there might be alarms with both elements set */
1627 str_len =
1628 find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info,
1629 sizeof(info));
1630 if (str_len > 0) {
1631 info[str_len] = 0;
1632 LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n",
1633 get_severity_string(severity), severity, info);
1634 } else { /* nothing found, try details */
1635 str_len =
1636 find_element(noh->data, len_data,
1637 NOKIA_EI_ALARM_DETAIL, info,
1638 sizeof(info));
1639 if (str_len > 0) {
1640 uint16_t code;
1641 info[str_len] = 0;
1642 code = (info[0] << 8) + info[1];
1643 LOGP(DNM, LOGL_INFO,
1644 "ALARM Severity %s (%d), code 0x%X : %s\n",
1645 get_severity_string(severity), severity,
1646 code, info + 2);
1647 }
1648 }
1649 /* send ACK */
1650 abis_nm_ack(bts, ref);
1651 break;
1652 }
1653
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001654 nokia_abis_nm_queue_send_next(bts);
Harald Weltebda367c2011-07-28 00:03:49 +02001655
1656 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001657}
1658
1659/* TODO: put in a separate file ? */
1660
1661int abis_nokia_rcvmsg(struct msgb *msg)
1662{
Harald Weltebda367c2011-07-28 00:03:49 +02001663 struct abis_om_hdr *oh = msgb_l2(msg);
1664 int rc = 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001665
Harald Weltebda367c2011-07-28 00:03:49 +02001666 /* Various consistency checks */
1667 if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
1668 LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
1669 oh->placement);
1670 if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
1671 return -EINVAL;
1672 }
1673 if (oh->sequence != 0) {
1674 LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
1675 oh->sequence);
1676 return -EINVAL;
1677 }
1678 msg->l3h = (unsigned char *)oh + sizeof(*oh);
Dieter Spaar16646022011-07-28 00:01:50 +02001679
Harald Weltebda367c2011-07-28 00:03:49 +02001680 switch (oh->mdisc) {
1681 case ABIS_OM_MDISC_FOM:
1682 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n");
1683 rc = abis_nm_rcvmsg_fom(msg);
1684 break;
1685 case ABIS_OM_MDISC_MANUF:
1686 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n");
1687 break;
1688 case ABIS_OM_MDISC_MMI:
1689 case ABIS_OM_MDISC_TRAU:
1690 LOGP(DNM, LOGL_ERROR,
1691 "unimplemented ABIS OML message discriminator 0x%x\n",
1692 oh->mdisc);
1693 break;
1694 default:
1695 LOGP(DNM, LOGL_ERROR,
1696 "unknown ABIS OML message discriminator 0x%x\n",
1697 oh->mdisc);
1698 return -EINVAL;
1699 }
Dieter Spaar16646022011-07-28 00:01:50 +02001700
Harald Weltebda367c2011-07-28 00:03:49 +02001701 msgb_free(msg);
1702 return rc;
Dieter Spaar16646022011-07-28 00:01:50 +02001703}
1704
1705static int bts_model_nokia_site_start(struct gsm_network *net);
1706
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001707static void bts_model_nokia_site_e1line_bind_ops(struct e1inp_line *line)
1708{
1709 e1inp_line_bind_ops(line, &bts_isdn_e1inp_line_ops);
1710}
1711
Dieter Spaar16646022011-07-28 00:01:50 +02001712static struct gsm_bts_model model_nokia_site = {
Harald Weltebda367c2011-07-28 00:03:49 +02001713 .type = GSM_BTS_TYPE_NOKIA_SITE,
1714 .name = "nokia_site",
1715 .start = bts_model_nokia_site_start,
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001716 .oml_rcvmsg = &abis_nokia_rcvmsg,
1717 .e1line_bind_ops = &bts_model_nokia_site_e1line_bind_ops,
Dieter Spaar16646022011-07-28 00:01:50 +02001718};
1719
1720static struct gsm_network *my_net;
1721
1722static int bts_model_nokia_site_start(struct gsm_network *net)
1723{
Harald Weltebda367c2011-07-28 00:03:49 +02001724 model_nokia_site.features.data = &model_nokia_site._features_data[0];
1725 model_nokia_site.features.data_len =
1726 sizeof(model_nokia_site._features_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001727
Philipp Maier8c498fc2018-02-21 13:24:36 +01001728 osmo_bts_set_feature(&model_nokia_site.features, BTS_FEAT_HOPPING);
1729 osmo_bts_set_feature(&model_nokia_site.features, BTS_FEAT_HSCSD);
1730 osmo_bts_set_feature(&model_nokia_site.features, BTS_FEAT_MULTI_TSC);
Dieter Spaar16646022011-07-28 00:01:50 +02001731
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001732 osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL);
1733 osmo_signal_register_handler(SS_L_GLOBAL, gbl_sig_cb, NULL);
Harald Weltebda367c2011-07-28 00:03:49 +02001734 osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
Dieter Spaar16646022011-07-28 00:01:50 +02001735
Harald Weltebda367c2011-07-28 00:03:49 +02001736 my_net = net;
1737
1738 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001739}
1740
1741int bts_model_nokia_site_init(void)
1742{
Harald Weltebda367c2011-07-28 00:03:49 +02001743 return gsm_bts_model_register(&model_nokia_site);
Dieter Spaar16646022011-07-28 00:01:50 +02001744}