blob: 67281bbf1e6bef87c52e19e70d920b80726165d6 [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
Sylvain Munautc9519462011-10-17 14:04:55 +020058 if (!bts->nokia.skip_reset) {
59 if (!bts->nokia.did_reset)
60 abis_nm_reset(bts, 1);
61 } else
62 bts->nokia.did_reset = 1;
Dieter Spaar16646022011-07-28 00:01:50 +020063}
64
65static void bootstrap_om_trx(struct gsm_bts_trx *trx)
66{
Harald Weltebda367c2011-07-28 00:03:49 +020067 LOGP(DNM, LOGL_NOTICE, "bootstrapping OML for TRX %u/%u\n",
68 trx->bts->nr, trx->nr);
Dieter Spaar16646022011-07-28 00:01:50 +020069}
70
71static int shutdown_om(struct gsm_bts *bts)
72{
Harald Weltebda367c2011-07-28 00:03:49 +020073 /* TODO !? */
74 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +020075}
76
77#define SAPI_OML 62
78#define SAPI_RSL 0
79
Harald Weltecde57942011-07-28 00:13:46 +020080/*
Dieter Spaar16646022011-07-28 00:01:50 +020081
82 Tell LAPD to start start the SAP (send SABM requests) for all signalling
Harald Weltecde57942011-07-28 00:13:46 +020083 timeslots in this line
84
85 Attention: this has to be adapted for mISDN
Dieter Spaar16646022011-07-28 00:01:50 +020086*/
Harald Weltebda367c2011-07-28 00:03:49 +020087
Andreas Eversbergc57e6ed2011-09-26 11:44:22 +020088static void start_sabm_in_line(struct e1inp_line *line, int start, int sapi)
Dieter Spaar16646022011-07-28 00:01:50 +020089{
Harald Weltebda367c2011-07-28 00:03:49 +020090 struct e1inp_sign_link *link;
91 int i;
Dieter Spaar16646022011-07-28 00:01:50 +020092
Harald Weltebda367c2011-07-28 00:03:49 +020093 for (i = 0; i < ARRAY_SIZE(line->ts); i++) {
94 struct e1inp_ts *ts = &line->ts[i];
Dieter Spaar16646022011-07-28 00:01:50 +020095
Harald Weltebda367c2011-07-28 00:03:49 +020096 if (ts->type != E1INP_TS_TYPE_SIGN)
97 continue;
Dieter Spaar16646022011-07-28 00:01:50 +020098
Harald Weltebda367c2011-07-28 00:03:49 +020099 llist_for_each_entry(link, &ts->sign.sign_links, list) {
100 if (sapi != -1 && link->sapi != sapi)
101 continue;
102
103#if 0 /* debugging */
104 printf("sap start/stop (%d): %d tei=%d sapi=%d\n",
105 start, i + 1, link->tei, link->sapi);
Dieter Spaar16646022011-07-28 00:01:50 +0200106#endif
Harald Weltebda367c2011-07-28 00:03:49 +0200107
Andreas.Eversbergbb5c5942011-11-02 22:22:24 +0100108 if (start) {
109 ts->lapd->profile.t200_sec = 1;
110 ts->lapd->profile.t200_usec = 0;
Harald Welteb4d913d2011-08-26 19:14:55 +0200111 lapd_sap_start(ts->lapd, link->tei,
Harald Weltebda367c2011-07-28 00:03:49 +0200112 link->sapi);
Andreas.Eversbergbb5c5942011-11-02 22:22:24 +0100113 } else
Harald Welteb4d913d2011-08-26 19:14:55 +0200114 lapd_sap_stop(ts->lapd, link->tei,
Harald Weltebda367c2011-07-28 00:03:49 +0200115 link->sapi);
116 }
117 }
Dieter Spaar16646022011-07-28 00:01:50 +0200118}
119
120/* Callback function to be called every time we receive a signal from INPUT */
121static int gbl_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200122 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200123{
Harald Weltebda367c2011-07-28 00:03:49 +0200124 struct gsm_bts *bts;
Dieter Spaar16646022011-07-28 00:01:50 +0200125
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200126 if (subsys != SS_L_GLOBAL)
Harald Weltebda367c2011-07-28 00:03:49 +0200127 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200128
Harald Weltebda367c2011-07-28 00:03:49 +0200129 switch (signal) {
130 case S_GLOBAL_BTS_CLOSE_OM:
131 bts = signal_data;
132 if (bts->type == GSM_BTS_TYPE_NOKIA_SITE)
133 shutdown_om(signal_data);
134 break;
135 }
Dieter Spaar16646022011-07-28 00:01:50 +0200136
Harald Weltebda367c2011-07-28 00:03:49 +0200137 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200138}
139
140/* Callback function to be called every time we receive a signal from INPUT */
141static int inp_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200142 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200143{
Harald Weltebda367c2011-07-28 00:03:49 +0200144 struct input_signal_data *isd = signal_data;
Dieter Spaar16646022011-07-28 00:01:50 +0200145
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200146 if (subsys != SS_L_INPUT)
Harald Weltebda367c2011-07-28 00:03:49 +0200147 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200148
Harald Weltebda367c2011-07-28 00:03:49 +0200149 switch (signal) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200150 case S_L_INP_LINE_INIT:
Harald Weltebda367c2011-07-28 00:03:49 +0200151 start_sabm_in_line(isd->line, 1, SAPI_OML); /* start only OML */
152 break;
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200153 case S_L_INP_TEI_DN:
Harald Weltebda367c2011-07-28 00:03:49 +0200154 break;
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200155 case S_L_INP_TEI_UP:
Harald Weltebda367c2011-07-28 00:03:49 +0200156 switch (isd->link_type) {
157 case E1INP_SIGN_OML:
158 if (isd->trx->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
159 break;
Dieter Spaar16646022011-07-28 00:01:50 +0200160
Harald Weltebda367c2011-07-28 00:03:49 +0200161 if (isd->tei == isd->trx->bts->oml_tei)
162 bootstrap_om_bts(isd->trx->bts);
163 else
164 bootstrap_om_trx(isd->trx);
165 break;
166 }
167 break;
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +0200168 case S_L_INP_TEI_UNKNOWN:
Pablo Neira Ayuso2962c202011-08-10 00:48:10 +0200169 /* We are receiving LAPD frames with one TEI that we do not
170 * seem to know, likely that we (the BSC) stopped working
171 * and lost our local states. However, the BTS is already
172 * configured, we try to take over the RSL links. */
173 start_sabm_in_line(isd->line, 1, SAPI_RSL);
174 break;
Harald Weltebda367c2011-07-28 00:03:49 +0200175 }
176
177 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200178}
179
180static void nm_statechg_evt(unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200181 struct nm_statechg_signal_data *nsd)
Dieter Spaar16646022011-07-28 00:01:50 +0200182{
Harald Weltebda367c2011-07-28 00:03:49 +0200183 if (nsd->bts->type != GSM_BTS_TYPE_NOKIA_SITE)
184 return;
Dieter Spaar16646022011-07-28 00:01:50 +0200185}
186
187static int nm_sig_cb(unsigned int subsys, unsigned int signal,
Harald Weltebda367c2011-07-28 00:03:49 +0200188 void *handler_data, void *signal_data)
Dieter Spaar16646022011-07-28 00:01:50 +0200189{
Harald Weltebda367c2011-07-28 00:03:49 +0200190 if (subsys != SS_NM)
191 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200192
Harald Weltebda367c2011-07-28 00:03:49 +0200193 switch (signal) {
194 case S_NM_STATECHG_OPER:
195 case S_NM_STATECHG_ADM:
196 nm_statechg_evt(signal, signal_data);
197 break;
198 default:
199 break;
200 }
Dieter Spaar16646022011-07-28 00:01:50 +0200201
Harald Weltebda367c2011-07-28 00:03:49 +0200202 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200203}
204
205/* TODO: put in a separate file ? */
206
Harald Welte44d26112011-07-28 00:43:13 +0200207static const struct value_string nokia_msgt_name[] = {
208 { 0x80, "NOKIA_BTS_CONF_DATA" },
209 { 0x81, "NOKIA_BTS_ACK" },
210 { 0x82, "NOKIA_BTS_OMU_STARTED" },
211 { 0x83, "NOKIA_BTS_START_DOWNLOAD_REQ" },
212 { 0x84, "NOKIA_BTS_MF_REQ" },
213 { 0x85, "NOKIA_BTS_AF_REQ" },
214 { 0x86, "NOKIA_BTS_RESET_REQ" },
215 { 0x87, "NOKIA_reserved" },
216 { 0x88, "NOKIA_BTS_CONF_REQ" },
217 { 0x89, "NOKIA_BTS_TEST_REQ" },
218 { 0x8A, "NOKIA_BTS_TEST_REPORT" },
219 { 0x8B, "NOKIA_reserved" },
220 { 0x8C, "NOKIA_reserved" },
221 { 0x8D, "NOKIA_reserved" },
222 { 0x8E, "NOKIA_BTS_CONF_COMPL" },
223 { 0x8F, "NOKIA_reserved" },
224 { 0x90, "NOKIA_BTS_STM_TEST_REQ" },
225 { 0x91, "NOKIA_BTS_STM_TEST_REPORT" },
226 { 0x92, "NOKIA_BTS_TRANSMISSION_COMMAND" },
227 { 0x93, "NOKIA_BTS_TRANSMISSION_ANSWER" },
228 { 0x94, "NOKIA_BTS_HW_DB_UPLOAD_REQ" },
229 { 0x95, "NOKIA_BTS_START_HW_DB_DOWNLOAD_REQ" },
230 { 0x96, "NOKIA_BTS_HW_DB_SAVE_REQ" },
231 { 0x97, "NOKIA_BTS_FLASH_ERASURE_REQ" },
232 { 0x98, "NOKIA_BTS_HW_DB_DOWNLOAD_REQ" },
233 { 0x99, "NOKIA_BTS_PWR_SUPPLY_CONTROL" },
234 { 0x9A, "NOKIA_BTS_ATTRIBUTE_REQ" },
235 { 0x9B, "NOKIA_BTS_ATTRIBUTE_REPORT" },
236 { 0x9C, "NOKIA_BTS_HW_REQ" },
237 { 0x9D, "NOKIA_BTS_HW_REPORT" },
238 { 0x9E, "NOKIA_BTS_RTE_TEST_REQ" },
239 { 0x9F, "NOKIA_BTS_RTE_TEST_REPORT" },
240 { 0xA0, "NOKIA_BTS_HW_DB_VERIFICATION_REQ" },
241 { 0xA1, "NOKIA_BTS_CLOCK_REQ" },
242 { 0xA2, "NOKIA_AC_CIRCUIT_REQ_NACK" },
243 { 0xA3, "NOKIA_AC_INTERRUPTED" },
244 { 0xA4, "NOKIA_BTS_NEW_TRE_INFO" },
245 { 0xA5, "NOKIA_AC_BSC_CIRCUITS_ALLOCATED" },
246 { 0xA6, "NOKIA_BTS_TRE_POLL_LIST" },
247 { 0xA7, "NOKIA_AC_CIRCUIT_REQ" },
248 { 0xA8, "NOKIA_BTS_BLOCK_CTRL_REQ" },
249 { 0xA9, "NOKIA_BTS_GSM_TIME_REQ" },
250 { 0xAA, "NOKIA_BTS_GSM_TIME" },
251 { 0xAB, "NOKIA_BTS_OUTPUT_CONTROL" },
252 { 0xAC, "NOKIA_BTS_STATE_CHANGED" },
253 { 0xAD, "NOKIA_BTS_SW_SAVE_REQ" },
254 { 0xAE, "NOKIA_BTS_ALARM" },
255 { 0xAF, "NOKIA_BTS_CHA_ADM_STATE" },
256 { 0xB0, "NOKIA_AC_POOL_SIZE_REPORT" },
257 { 0xB1, "NOKIA_AC_POOL_SIZE_INQUIRY" },
258 { 0xB2, "NOKIA_BTS_COMMISS_TEST_COMPLETED" },
259 { 0xB3, "NOKIA_BTS_COMMISS_TEST_REQ" },
260 { 0xB4, "NOKIA_BTS_TRANSP_BTS_TO_BSC" },
261 { 0xB5, "NOKIA_BTS_TRANSP_BSC_TO_BTS" },
262 { 0xB6, "NOKIA_BTS_LCS_COMMAND" },
263 { 0xB7, "NOKIA_BTS_LCS_ANSWER" },
264 { 0xB8, "NOKIA_BTS_LMU_FN_OFFSET_COMMAND" },
265 { 0xB9, "NOKIA_BTS_LMU_FN_OFFSET_ANSWER" },
266 { 0, NULL }
267};
268
269static const char *get_msg_type_name_string(uint8_t msg_type)
Dieter Spaar16646022011-07-28 00:01:50 +0200270{
Harald Welte44d26112011-07-28 00:43:13 +0200271 return get_value_string(nokia_msgt_name, msg_type);
Dieter Spaar16646022011-07-28 00:01:50 +0200272}
273
Harald Welte44d26112011-07-28 00:43:13 +0200274static const struct value_string nokia_element_name[] = {
275 { 0x01, "Ny1" },
276 { 0x02, "T3105_F" },
277 { 0x03, "Interference band limits" },
278 { 0x04, "Interference report timer in secs" },
279 { 0x05, "Channel configuration per TS" },
280 { 0x06, "BSIC" },
281 { 0x07, "RACH report timer in secs" },
282 { 0x08, "Hardware database status" },
283 { 0x09, "BTS RX level" },
284 { 0x0A, "ARFN" },
285 { 0x0B, "STM antenna attenuation" },
286 { 0x0C, "Cell allocation bitmap" },
287 { 0x0D, "Radio definition per TS" },
288 { 0x0E, "Frame number" },
289 { 0x0F, "Antenna diversity" },
290 { 0x10, "T3105_D" },
291 { 0x11, "File format" },
292 { 0x12, "Last File" },
293 { 0x13, "BTS type" },
294 { 0x14, "Erasure mode" },
295 { 0x15, "Hopping mode" },
296 { 0x16, "Floating TRX" },
297 { 0x17, "Power supplies" },
298 { 0x18, "Reset type" },
299 { 0x19, "Averaging period" },
300 { 0x1A, "RBER2" },
301 { 0x1B, "LAC" },
302 { 0x1C, "CI" },
303 { 0x1D, "Failure parameters" },
304 { 0x1E, "(RF max power reduction)" },
305 { 0x1F, "Measured RX_SENS" },
306 { 0x20, "Extended cell radius" },
307 { 0x21, "reserved" },
308 { 0x22, "Success-Failure" },
309 { 0x23, "Ack-Nack" },
310 { 0x24, "OMU test results" },
311 { 0x25, "File identity" },
312 { 0x26, "Generation and version code" },
313 { 0x27, "SW description" },
314 { 0x28, "BCCH LEV" },
315 { 0x29, "Test type" },
316 { 0x2A, "Subscriber number" },
317 { 0x2B, "reserved" },
318 { 0x2C, "HSN" },
319 { 0x2D, "reserved" },
320 { 0x2E, "MS RXLEV" },
321 { 0x2F, "MS TXLEV" },
322 { 0x30, "RXQUAL" },
323 { 0x31, "RX SENS" },
324 { 0x32, "Alarm block" },
325 { 0x33, "Neighbouring BCCH levels" },
326 { 0x34, "STM report type" },
327 { 0x35, "MA" },
328 { 0x36, "MAIO" },
329 { 0x37, "H_FLAG" },
330 { 0x38, "TCH_ARFN" },
331 { 0x39, "Clock output" },
332 { 0x3A, "Transmitted power" },
333 { 0x3B, "Clock sync" },
334 { 0x3C, "TMS protocol discriminator" },
335 { 0x3D, "TMS protocol data" },
336 { 0x3E, "FER" },
337 { 0x3F, "SWR result" },
338 { 0x40, "Object identity" },
339 { 0x41, "STM RX Antenna Test" },
340 { 0x42, "reserved" },
341 { 0x43, "reserved" },
342 { 0x44, "Object current state" },
343 { 0x45, "reserved" },
344 { 0x46, "FU channel configuration" },
345 { 0x47, "reserved" },
346 { 0x48, "ARFN of a CU" },
347 { 0x49, "FU radio definition" },
348 { 0x4A, "reserved" },
349 { 0x4B, "Severity" },
350 { 0x4C, "Diversity selection" },
351 { 0x4D, "RX antenna test" },
352 { 0x4E, "RX antenna supervision period" },
353 { 0x4F, "RX antenna state" },
354 { 0x50, "Sector configuration" },
355 { 0x51, "Additional info" },
356 { 0x52, "SWR parameters" },
357 { 0x53, "HW inquiry mode" },
358 { 0x54, "reserved" },
359 { 0x55, "Availability status" },
360 { 0x56, "reserved" },
361 { 0x57, "EAC inputs" },
362 { 0x58, "EAC outputs" },
363 { 0x59, "reserved" },
364 { 0x5A, "Position" },
365 { 0x5B, "HW unit identity" },
366 { 0x5C, "RF test signal attenuation" },
367 { 0x5D, "Operational state" },
368 { 0x5E, "Logical object identity" },
369 { 0x5F, "reserved" },
370 { 0x60, "BS_TXPWR_OM" },
371 { 0x61, "Loop_Duration" },
372 { 0x62, "LNA_Path_Selection" },
373 { 0x63, "Serial number" },
374 { 0x64, "HW version" },
375 { 0x65, "Obj. identity and obj. state" },
376 { 0x66, "reserved" },
377 { 0x67, "EAC input definition" },
378 { 0x68, "EAC id and text" },
379 { 0x69, "HW unit status" },
380 { 0x6A, "SW release version" },
381 { 0x6B, "FW version" },
382 { 0x6C, "Bit_Error_Ratio" },
383 { 0x6D, "RXLEV_with_Attenuation" },
384 { 0x6E, "RXLEV_without_Attenuation" },
385 { 0x6F, "reserved" },
386 { 0x70, "CU_Results" },
387 { 0x71, "reserved" },
388 { 0x72, "LNA_Path_Results" },
389 { 0x73, "RTE Results" },
390 { 0x74, "Real Time" },
391 { 0x75, "RX diversity selection" },
392 { 0x76, "EAC input config" },
393 { 0x77, "Feature support" },
394 { 0x78, "File version" },
395 { 0x79, "Outputs" },
396 { 0x7A, "FU parameters" },
397 { 0x7B, "Diagnostic info" },
398 { 0x7C, "FU BSIC" },
399 { 0x7D, "TRX Configuration" },
400 { 0x7E, "Download status" },
401 { 0x7F, "RX difference limit" },
402 { 0x80, "TRX HW capability" },
403 { 0x81, "Common HW config" },
404 { 0x82, "Autoconfiguration pool size" },
405 { 0x83, "TRE diagnostic info" },
406 { 0x84, "TRE object identity" },
407 { 0x85, "New TRE Info" },
408 { 0x86, "Acknowledgement period" },
409 { 0x87, "Synchronization mode" },
410 { 0x88, "reserved" },
411 { 0x89, "Block Control Data" },
412 { 0x8A, "SW load mode" },
413 { 0x8B, "Recommended recovery action" },
414 { 0x8C, "BSC BCF id" },
415 { 0x8D, "Q1 baud rate" },
416 { 0x8E, "Allocation status" },
417 { 0x8F, "Functional entity number" },
418 { 0x90, "Transmission delay" },
419 { 0x91, "Loop Duration ms" },
420 { 0x92, "Logical channel" },
421 { 0x93, "Q1 address" },
422 { 0x94, "Alarm detail" },
423 { 0x95, "Cabinet type" },
424 { 0x96, "HW unit existence" },
425 { 0x97, "RF power parameters" },
426 { 0x98, "Message scenario" },
427 { 0x99, "HW unit max amount" },
428 { 0x9A, "Master TRX" },
429 { 0x9B, "Transparent data" },
430 { 0x9C, "BSC topology info" },
431 { 0x9D, "Air i/f modulation" },
432 { 0x9E, "LCS Q1 command data" },
433 { 0x9F, "Frame number offset" },
434 { 0xA0, "Abis TSL" },
435 { 0xA1, "Dynamic pool info" },
436 { 0xA2, "LCS LLP data" },
437 { 0xA3, "LCS Q1 answer data" },
438 { 0xA4, "DFCA FU Radio Definition" },
439 { 0xA5, "Antenna hopping" },
440 { 0xA6, "Field record sequence number" },
441 { 0xA7, "Timeslot offslot" },
442 { 0xA8, "EPCR capability" },
443 { 0xA9, "Connectsite optional element" },
444 { 0xAA, "TSC" },
445 { 0xAB, "Special TX Power Setting" },
446 { 0xAC, "Optional sync settings" },
447 { 0xFA, "Abis If parameters" },
448 { 0, NULL }
449};
450
451static const char *get_element_name_string(uint16_t element)
Dieter Spaar16646022011-07-28 00:01:50 +0200452{
Harald Welte44d26112011-07-28 00:43:13 +0200453 return get_value_string(nokia_element_name, element);
Dieter Spaar16646022011-07-28 00:01:50 +0200454}
455
Harald Welte3c3003f2011-07-28 00:28:20 +0200456static const struct value_string nokia_bts_types[] = {
457 { 0x0a, "MetroSite GSM 900" },
458 { 0x0b, "MetroSite GSM 1800" },
459 { 0x0c, "MetroSite GSM 1900 (PCS)" },
460 { 0x0d, "MetroSite GSM 900 & 1800" },
461 { 0x0e, "InSite GSM 900" },
462 { 0x0f, "InSite GSM 1800" },
463 { 0x10, "InSite GSM 1900" },
464 { 0x11, "UltraSite GSM 900" },
465 { 0x12, "UltraSite GSM 1800" },
466 { 0x13, "UltraSite GSM/US-TDMA 1900" },
467 { 0x14, "UltraSite GSM 900 & 1800" },
468 { 0x16, "UltraSite GSM/US-TDMA 850" },
469 { 0x18, "MetroSite GSM/US-TDMA 850" },
470 { 0x19, "UltraSite GSM 800/1900" },
471 { 0, NULL }
472};
473
474static const char *get_bts_type_string(uint8_t type)
Dieter Spaar16646022011-07-28 00:01:50 +0200475{
Harald Welte3c3003f2011-07-28 00:28:20 +0200476 return get_value_string(nokia_bts_types, type);
Dieter Spaar16646022011-07-28 00:01:50 +0200477}
478
Harald Welte3c3003f2011-07-28 00:28:20 +0200479static const struct value_string nokia_severity[] = {
480 { 0, "indeterminate" },
481 { 1, "critical" },
482 { 2, "major" },
483 { 3, "minor" },
484 { 4, "warning" },
485 { 0, NULL }
486};
487
488static const char *get_severity_string(uint8_t severity)
Dieter Spaar16646022011-07-28 00:01:50 +0200489{
Harald Welte3c3003f2011-07-28 00:28:20 +0200490 return get_value_string(nokia_severity, severity);
Dieter Spaar16646022011-07-28 00:01:50 +0200491}
492
493/* TODO: put in a separate file ? */
494
495/* some message IDs */
496
497#define NOKIA_MSG_CONF_DATA 128
498#define NOKIA_MSG_ACK 129
499#define NOKIA_MSG_OMU_STARTED 130
500#define NOKIA_MSG_START_DOWNLOAD_REQ 131
501#define NOKIA_MSG_MF_REQ 132
502#define NOKIA_MSG_RESET_REQ 134
503#define NOKIA_MSG_CONF_REQ 136
504#define NOKIA_MSG_CONF_COMPLETE 142
505#define NOKIA_MSG_BLOCK_CTRL_REQ 168
506#define NOKIA_MSG_STATE_CHANGED 172
507#define NOKIA_MSG_ALARM 174
508
509/* some element IDs */
510
511#define NOKIA_EI_BTS_TYPE 0x13
512#define NOKIA_EI_ACK 0x23
513#define NOKIA_EI_ADD_INFO 0x51
514#define NOKIA_EI_SEVERITY 0x4B
515#define NOKIA_EI_ALARM_DETAIL 0x94
516
517#define OM_ALLOC_SIZE 1024
518#define OM_HEADROOM_SIZE 128
519
Harald Weltebda367c2011-07-28 00:03:49 +0200520static uint8_t fu_config_template[] = {
521 0x7F, 0x7A, 0x39,
522 /* ID = 0x7A (FU parameters) ## constructed ## */
523 /* length = 57 */
524 /* [3] */
Dieter Spaar16646022011-07-28 00:01:50 +0200525
Harald Weltebda367c2011-07-28 00:03:49 +0200526 0x5F, 0x40, 0x04,
527 /* ID = 0x40 (Object identity) */
528 /* length = 4 */
529 /* [6] */
530 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200531
Harald Weltebda367c2011-07-28 00:03:49 +0200532 0x41, 0x02,
533 /* ID = 0x01 (Ny1) */
534 /* length = 2 */
535 /* [12] */
536 0x00, 0x05,
Dieter Spaar16646022011-07-28 00:01:50 +0200537
Harald Weltebda367c2011-07-28 00:03:49 +0200538 0x42, 0x02,
539 /* ID = 0x02 (T3105_F) */
540 /* length = 2 */
541 /* [16] */
Harald Welte67161f22012-06-03 13:01:47 +0200542 0x00, 0x28, /* FIXME: use net->T3105 */
Dieter Spaar16646022011-07-28 00:01:50 +0200543
Harald Weltebda367c2011-07-28 00:03:49 +0200544 0x50, 0x02,
545 /* ID = 0x10 (T3105_D) */
546 /* length = 2 */
547 /* [20] */
Harald Welte67161f22012-06-03 13:01:47 +0200548 0x00, 0x28, /* FIXME: use net->T3105 */
Dieter Spaar16646022011-07-28 00:01:50 +0200549
Harald Weltebda367c2011-07-28 00:03:49 +0200550 0x43, 0x05,
551 /* ID = 0x03 (Interference band limits) */
552 /* length = 5 */
553 /* [24] */
554 0x0F, 0x1B, 0x27, 0x33, 0x3F,
Dieter Spaar16646022011-07-28 00:01:50 +0200555
Harald Weltebda367c2011-07-28 00:03:49 +0200556 0x44, 0x02,
557 /* ID = 0x04 (Interference report timer in secs) */
558 /* length = 2 */
559 /* [31] */
560 0x00, 0x10,
Dieter Spaar16646022011-07-28 00:01:50 +0200561
Harald Weltebda367c2011-07-28 00:03:49 +0200562 0x47, 0x01,
563 /* ID = 0x07 (RACH report timer in secs) */
564 /* length = 1 */
565 /* [35] */
566 0x1E,
Dieter Spaar16646022011-07-28 00:01:50 +0200567
Harald Weltebda367c2011-07-28 00:03:49 +0200568 0x4C, 0x10,
569 /* ID = 0x0C (Cell allocation bitmap) ####### */
570 /* length = 16 */
571 /* [38] */
572 0x8F, 0xB1, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
573 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200574
Harald Weltebda367c2011-07-28 00:03:49 +0200575 0x59, 0x01,
576 /* ID = 0x19 (Averaging period) */
577 /* length = 1 */
578 /* [56] */
579 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +0200580
Harald Weltebda367c2011-07-28 00:03:49 +0200581 0x5E, 0x01,
582 /* ID = 0x1E ((RF max power reduction)) */
583 /* length = 1 */
584 /* [59] */
585 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200586
Harald Weltebda367c2011-07-28 00:03:49 +0200587 0x7F, 0x46, 0x11,
588 /* ID = 0x46 (FU channel configuration) ## constructed ## */
589 /* length = 17 */
590 /* [63] */
Dieter Spaar16646022011-07-28 00:01:50 +0200591
Harald Weltebda367c2011-07-28 00:03:49 +0200592 0x5F, 0x40, 0x04,
593 /* ID = 0x40 (Object identity) */
594 /* length = 4 */
595 /* [66] */
596 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200597
Harald Weltebda367c2011-07-28 00:03:49 +0200598 0x45, 0x08,
599 /* ID = 0x05 (Channel configuration per TS) */
600 /* length = 8 */
601 /* [72] */
602 0x01, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09, 0x09,
Dieter Spaar16646022011-07-28 00:01:50 +0200603
Harald Weltebda367c2011-07-28 00:03:49 +0200604 0x7F, 0x65, 0x0B,
605 /* ID = 0x65 (Obj. identity and obj. state) ## constructed ## */
606 /* length = 11 */
607 /* [83] */
Dieter Spaar16646022011-07-28 00:01:50 +0200608
Harald Weltebda367c2011-07-28 00:03:49 +0200609 0x5F, 0x40, 0x04,
610 /* ID = 0x40 (Object identity) */
611 /* length = 4 */
612 /* [86] */
613 0x00, 0x04, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200614
Harald Weltebda367c2011-07-28 00:03:49 +0200615 0x5F, 0x44, 0x01,
616 /* ID = 0x44 (Object current state) */
617 /* length = 1 */
618 /* [93] */
619 0x03,
Dieter Spaar16646022011-07-28 00:01:50 +0200620
Harald Weltebda367c2011-07-28 00:03:49 +0200621 0x7F, 0x7C, 0x0A,
622 /* ID = 0x7C (FU BSIC) ## constructed ## */
623 /* length = 10 */
624 /* [97] */
Dieter Spaar16646022011-07-28 00:01:50 +0200625
Harald Weltebda367c2011-07-28 00:03:49 +0200626 0x5F, 0x40, 0x04,
627 /* ID = 0x40 (Object identity) */
628 /* length = 4 */
629 /* [100] */
630 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200631
Harald Weltebda367c2011-07-28 00:03:49 +0200632 0x46, 0x01,
633 /* ID = 0x06 (BSIC) */
634 /* length = 1 */
635 /* [106] */
636 0x00,
Dieter Spaar16646022011-07-28 00:01:50 +0200637
Harald Weltebda367c2011-07-28 00:03:49 +0200638 0x7F, 0x48, 0x0B,
639 /* ID = 0x48 (ARFN of a CU) ## constructed ## */
640 /* length = 11 */
641 /* [110] */
Dieter Spaar16646022011-07-28 00:01:50 +0200642
Harald Weltebda367c2011-07-28 00:03:49 +0200643 0x5F, 0x40, 0x04,
644 /* ID = 0x40 (Object identity) */
645 /* length = 4 */
646 /* [113] */
647 0x00, 0x08, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200648
Harald Weltebda367c2011-07-28 00:03:49 +0200649 0x4A, 0x02,
650 /* ID = 0x0A (ARFN) ####### */
651 /* length = 2 */
652 /* [119] */
653 0x03, 0x62,
Dieter Spaar16646022011-07-28 00:01:50 +0200654
Harald Weltebda367c2011-07-28 00:03:49 +0200655 0x7F, 0x49, 0x59,
656 /* ID = 0x49 (FU radio definition) ## constructed ## */
657 /* length = 89 */
658 /* [124] */
Dieter Spaar16646022011-07-28 00:01:50 +0200659
Harald Weltebda367c2011-07-28 00:03:49 +0200660 0x5F, 0x40, 0x04,
661 /* ID = 0x40 (Object identity) */
662 /* length = 4 */
663 /* [127] */
664 0x00, 0x07, 0x01, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +0200665
Harald Weltebda367c2011-07-28 00:03:49 +0200666 0x4D, 0x50,
667 /* ID = 0x0D (Radio definition per TS) ####### */
668 /* length = 80 */
669 /* [133] */
670 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, /* MA */
671 0x03, 0x62, /* HSN, MAIO or ARFCN if no hopping */
672 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
673 0x03, 0x62,
674 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
675 0x03, 0x62,
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,
Dieter Spaar16646022011-07-28 00:01:50 +0200686};
687
688/* TODO: put in a separate file ? */
689
690/*
Harald Weltecde57942011-07-28 00:13:46 +0200691 build the configuration for each TRX
Dieter Spaar16646022011-07-28 00:01:50 +0200692*/
693
Harald Weltebda367c2011-07-28 00:03:49 +0200694static int make_fu_config(struct gsm_bts_trx *trx, uint8_t id,
695 uint8_t * fu_config, int *hopping)
Dieter Spaar16646022011-07-28 00:01:50 +0200696{
Harald Weltebda367c2011-07-28 00:03:49 +0200697 int i;
Dieter Spaar16646022011-07-28 00:01:50 +0200698
Harald Weltebda367c2011-07-28 00:03:49 +0200699 *hopping = 0;
700
701 memcpy(fu_config, fu_config_template, sizeof(fu_config_template));
702
703 /* set ID */
704
705 fu_config[6 + 2] = id;
706 fu_config[66 + 2] = id;
707 fu_config[86 + 2] = id;
708 fu_config[100 + 2] = id;
709 fu_config[113 + 2] = id;
710 fu_config[127 + 2] = id;
711
712 /* set ARFCN */
713
714 uint16_t arfcn = trx->arfcn;
715
716 fu_config[119] = arfcn >> 8;
717 fu_config[119 + 1] = arfcn & 0xFF;
718
719 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
720 struct gsm_bts_trx_ts *ts = &trx->ts[i];
721
722 if (ts->hopping.enabled) {
723 /* reverse order */
724 int j;
725 for (j = 0; j < ts->hopping.ma_len; j++)
726 fu_config[133 + (i * 10) + (7 - j)] =
727 ts->hopping.ma_data[j];
728 fu_config[133 + 8 + (i * 10)] = ts->hopping.hsn;
729 fu_config[133 + 8 + 1 + (i * 10)] = ts->hopping.maio;
730 *hopping = 1;
731 } else {
732 fu_config[133 + 8 + (i * 10)] = arfcn >> 8;
733 fu_config[133 + 8 + 1 + (i * 10)] = arfcn & 0xFF;
734 }
735 }
736
737 /* set BSIC */
738
Harald Weltecde57942011-07-28 00:13:46 +0200739 /*
Harald Weltebda367c2011-07-28 00:03:49 +0200740 Attention: all TRX except the first one seem to get the TSC
741 from the CHANNEL ACTIVATION command (in CHANNEL IDENTIFICATION,
Harald Weltecde57942011-07-28 00:13:46 +0200742 GSM 04.08 CHANNEL DESCRIPTION).
743 There was a bug in rsl_chan_activate_lchan() setting this parameter.
Harald Weltebda367c2011-07-28 00:03:49 +0200744 */
745
746 uint8_t bsic = trx->bts->bsic;
747
748 fu_config[106] = bsic;
749
750 /* set CA */
751
752 if (generate_cell_chan_list(&fu_config[38], trx->bts) != 0) {
753 fprintf(stderr, "generate_cell_chan_list failed\n");
754 return 0;
755 }
756
757 /* set channel configuration */
758
759 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
760 struct gsm_bts_trx_ts *ts = &trx->ts[i];
761 uint8_t chan_config;
762
763 /*
764 0 = FCCH + SCH + BCCH + CCCH
765 1 = FCCH + SCH + BCCH + CCCH + SDCCH/4 + SACCH/4
766 2 = BCCH + CCCH (This combination is not used in any BTS)
767 3 = FCCH + SCH + BCCH + CCCH + SDCCH/4 with SDCCH2 used as CBCH
768 4 = SDCCH/8 + SACCH/8
769 5 = SDCCH/8 with SDCCH2 used as CBCH
770 6 = TCH/F + FACCH/F + SACCH/F
771 7 = E-RACH (Talk family)
772 9 = Dual rate (capability for TCH/F and TCH/H)
773 10 = reserved for BTS internal use
Harald Weltecde57942011-07-28 00:13:46 +0200774 11 = PBCCH + PCCCH + PDTCH + PACCH + PTCCH (can be used in GPRS release 2).
775 0xFF = spare TS
Harald Weltebda367c2011-07-28 00:03:49 +0200776 */
777
778 if (ts->pchan == GSM_PCHAN_NONE)
779 chan_config = 0xFF;
780 else if (ts->pchan == GSM_PCHAN_CCCH)
781 chan_config = 0;
782 else if (ts->pchan == GSM_PCHAN_CCCH_SDCCH4)
783 chan_config = 1;
784 else if (ts->pchan == GSM_PCHAN_TCH_F)
785 chan_config = 6; /* 9 should work too */
786 else if (ts->pchan == GSM_PCHAN_TCH_H)
787 chan_config = 9;
788 else if (ts->pchan == GSM_PCHAN_SDCCH8_SACCH8C)
789 chan_config = 4;
790 else if (ts->pchan == GSM_PCHAN_PDCH)
791 chan_config = 11;
792 else {
793 fprintf(stderr,
794 "unsupported channel config %d for timeslot %d\n",
795 ts->pchan, i);
796 return 0;
797 }
798
799 fu_config[72 + i] = chan_config;
800 }
801 return sizeof(fu_config_template);
Dieter Spaar16646022011-07-28 00:01:50 +0200802}
803
804/* TODO: put in a separate file ? */
805
Harald Weltebda367c2011-07-28 00:03:49 +0200806static uint8_t bts_config_1[] = {
807 0x4E, 0x02,
808 /* ID = 0x0E (Frame number) */
809 /* length = 2 */
810 /* [2] */
811 0xFF, 0xFF,
812
813 0x5F, 0x4E, 0x02,
814 /* ID = 0x4E (RX antenna supervision period) */
815 /* length = 2 */
816 /* [7] */
817 0xFF, 0xFF,
818
819 0x5F, 0x50, 0x02,
820 /* ID = 0x50 (Sector configuration) */
821 /* length = 2 */
822 /* [12] */
823 0x01, 0x01,
824};
825
826static uint8_t bts_config_2[] = {
827 0x55, 0x02,
828 /* ID = 0x15 (Hopping mode) */
829 /* length = 2 */
830 /* [2] */
831 0x01, 0x00,
832
833 0x5F, 0x75, 0x02,
834 /* ID = 0x75 (RX diversity selection) */
835 /* length = 2 */
836 /* [7] */
837 0x01, 0x01,
838};
839
840static uint8_t bts_config_3[] = {
841 0x5F, 0x20, 0x02,
842 /* ID = 0x20 (Extended cell radius) */
843 /* length = 2 */
844 /* [3] */
845 0x01, 0x00,
846};
847
848static uint8_t bts_config_4[] = {
849 0x5F, 0x74, 0x09,
850 /* ID = 0x74 (Real Time) */
851 /* length = 9 */
852 /* [3] year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
853 0x07, 0xDB, 0x06, 0x02, 0x0B, 0x20, 0x0C, 0x00,
854 0x00,
855
856 0x5F, 0x76, 0x03,
857 /* ID = 0x76 (EAC input config) */
858 /* length = 3 */
859 /* [15] */
860 0x01, 0x01, 0x00,
861
862 0x5F, 0x76, 0x03,
863 /* ID = 0x76 (EAC input config) */
864 /* length = 3 */
865 /* [21] */
866 0x02, 0x01, 0x00,
867
868 0x5F, 0x76, 0x03,
869 /* ID = 0x76 (EAC input config) */
870 /* length = 3 */
871 /* [27] */
872 0x03, 0x01, 0x00,
873
874 0x5F, 0x76, 0x03,
875 /* ID = 0x76 (EAC input config) */
876 /* length = 3 */
877 /* [33] */
878 0x04, 0x01, 0x00,
879
880 0x5F, 0x76, 0x03,
881 /* ID = 0x76 (EAC input config) */
882 /* length = 3 */
883 /* [39] */
884 0x05, 0x01, 0x00,
885
886 0x5F, 0x76, 0x03,
887 /* ID = 0x76 (EAC input config) */
888 /* length = 3 */
889 /* [45] */
890 0x06, 0x01, 0x00,
891
892 0x5F, 0x76, 0x03,
893 /* ID = 0x76 (EAC input config) */
894 /* length = 3 */
895 /* [51] */
896 0x07, 0x01, 0x00,
897
898 0x5F, 0x76, 0x03,
899 /* ID = 0x76 (EAC input config) */
900 /* length = 3 */
901 /* [57] */
902 0x08, 0x01, 0x00,
903
904 0x5F, 0x76, 0x03,
905 /* ID = 0x76 (EAC input config) */
906 /* length = 3 */
907 /* [63] */
908 0x09, 0x01, 0x00,
909
910 0x5F, 0x76, 0x03,
911 /* ID = 0x76 (EAC input config) */
912 /* length = 3 */
913 /* [69] */
914 0x0A, 0x01, 0x00,
915};
916
917static uint8_t bts_config_insite[] = {
918 0x4E, 0x02,
919 /* ID = 0x0E (Frame number) */
920 /* length = 2 */
921 /* [2] */
922 0xFF, 0xFF,
923
924 0x5F, 0x4E, 0x02,
925 /* ID = 0x4E (RX antenna supervision period) */
926 /* length = 2 */
927 /* [7] */
928 0xFF, 0xFF,
929
930 0x5F, 0x50, 0x02,
931 /* ID = 0x50 (Sector configuration) */
932 /* length = 2 */
933 /* [12] */
934 0x01, 0x01,
935
936 0x55, 0x02,
937 /* ID = 0x15 (Hopping mode) */
938 /* length = 2 */
939 /* [16] */
940 0x01, 0x00,
941
942 0x5F, 0x20, 0x02,
943 /* ID = 0x20 (Extended cell radius) */
944 /* length = 2 */
945 /* [21] */
946 0x01, 0x00,
947
948 0x5F, 0x74, 0x09,
949 /* ID = 0x74 (Real Time) */
950 /* length = 9 */
951 /* [26] */
952 0x07, 0xDB, 0x07, 0x0A, 0x0F, 0x09, 0x0B, 0x00,
953 0x00,
954};
955
956void set_real_time(uint8_t * real_time)
Dieter Spaar16646022011-07-28 00:01:50 +0200957{
Harald Weltebda367c2011-07-28 00:03:49 +0200958 time_t t;
959 struct tm *tm;
Dieter Spaar16646022011-07-28 00:01:50 +0200960
Harald Weltebda367c2011-07-28 00:03:49 +0200961 t = time(NULL);
962 tm = localtime(&t);
Dieter Spaar16646022011-07-28 00:01:50 +0200963
Harald Weltebda367c2011-07-28 00:03:49 +0200964 /* year-high, year-low, month, day, hour, minute, second, msec-high, msec-low */
Dieter Spaar16646022011-07-28 00:01:50 +0200965
Harald Weltebda367c2011-07-28 00:03:49 +0200966 real_time[0] = (1900 + tm->tm_year) >> 8;
967 real_time[1] = (1900 + tm->tm_year) & 0xFF;
968 real_time[2] = tm->tm_mon + 1;
969 real_time[3] = tm->tm_mday;
970 real_time[4] = tm->tm_hour;
971 real_time[5] = tm->tm_min;
972 real_time[6] = tm->tm_sec;
973 real_time[7] = 0;
974 real_time[8] = 0;
Dieter Spaar16646022011-07-28 00:01:50 +0200975}
976
977/* TODO: put in a separate file ? */
978
979/*
Dieter Spaar16646022011-07-28 00:01:50 +0200980 build the configuration data
Dieter Spaar16646022011-07-28 00:01:50 +0200981*/
982
Harald Weltebda367c2011-07-28 00:03:49 +0200983static int make_bts_config(uint8_t bts_type, int n_trx, uint8_t * fu_config,
984 int need_hopping)
Dieter Spaar16646022011-07-28 00:01:50 +0200985{
Harald Weltebda367c2011-07-28 00:03:49 +0200986 /* is it an InSite BTS ? */
987 if (bts_type == 0x0E || bts_type == 0x0F || bts_type == 0x10) { /* TODO */
988 if (n_trx != 1) {
989 fprintf(stderr, "InSite has only one TRX\n");
990 return 0;
991 }
992 if (need_hopping != 0) {
993 fprintf(stderr, "InSite does not support hopping\n");
994 return 0;
995 }
996 memcpy(fu_config, bts_config_insite, sizeof(bts_config_insite));
997 set_real_time(&fu_config[26]);
998 return sizeof(bts_config_insite);
999 }
Dieter Spaar16646022011-07-28 00:01:50 +02001000
Harald Weltebda367c2011-07-28 00:03:49 +02001001 int len = 0;
1002 int i;
1003
1004 memcpy(fu_config + len, bts_config_1, sizeof(bts_config_1));
1005
1006 /* set sector configuration */
1007 fu_config[len + 12 - 1] = 1 + n_trx; /* len */
1008 for (i = 0; i < n_trx; i++)
1009 fu_config[len + 12 + 1 + i] = ((i + 1) & 0xFF);
1010
1011 len += (sizeof(bts_config_1) + (n_trx - 1));
1012
1013 memcpy(fu_config + len, bts_config_2, sizeof(bts_config_2));
1014 /* set hopping mode (Baseband and RF hopping work for the MetroSite) */
1015 if (need_hopping)
1016 fu_config[len + 2 + 1] = 1; /* 0: no hopping, 1: Baseband hopping, 2: RF hopping */
1017 len += sizeof(bts_config_2);
1018
1019 /* set extended cell radius for each TRX */
1020 for (i = 0; i < n_trx; i++) {
1021 memcpy(fu_config + len, bts_config_3, sizeof(bts_config_3));
1022 fu_config[len + 3] = ((i + 1) & 0xFF);
1023 len += sizeof(bts_config_3);
1024 }
1025
1026 memcpy(fu_config + len, bts_config_4, sizeof(bts_config_4));
1027 set_real_time(&fu_config[len + 3]);
1028 len += sizeof(bts_config_4);
1029
1030 return len;
Dieter Spaar16646022011-07-28 00:01:50 +02001031}
1032
1033/* TODO: put in a separate file ? */
1034
1035static struct msgb *nm_msgb_alloc(void)
1036{
Harald Weltebda367c2011-07-28 00:03:49 +02001037 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE, "OML");
Dieter Spaar16646022011-07-28 00:01:50 +02001038}
1039
1040/* TODO: put in a separate file ? */
1041
1042struct abis_om_nokia_hdr {
Harald Weltebda367c2011-07-28 00:03:49 +02001043 uint8_t msg_type;
1044 uint8_t spare;
1045 uint16_t reference;
1046 uint8_t data[0];
Dieter Spaar16646022011-07-28 00:01:50 +02001047} __attribute__ ((packed));
1048
1049#define ABIS_OM_NOKIA_HDR_SIZE (sizeof(struct abis_om_hdr) + sizeof(struct abis_om_nokia_hdr))
1050
Harald Weltebda367c2011-07-28 00:03:49 +02001051static int abis_nm_send(struct gsm_bts *bts, uint8_t msg_type, uint16_t ref,
1052 uint8_t * data, int len_data)
Dieter Spaar16646022011-07-28 00:01:50 +02001053{
Harald Weltebda367c2011-07-28 00:03:49 +02001054 struct abis_om_hdr *oh;
1055 struct abis_om_nokia_hdr *noh;
1056 struct msgb *msg = nm_msgb_alloc();
Dieter Spaar16646022011-07-28 00:01:50 +02001057
Harald Weltebda367c2011-07-28 00:03:49 +02001058 oh = (struct abis_om_hdr *)msgb_put(msg,
1059 ABIS_OM_NOKIA_HDR_SIZE + len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001060
Harald Weltebda367c2011-07-28 00:03:49 +02001061 oh->mdisc = ABIS_OM_MDISC_FOM;
1062 oh->placement = ABIS_OM_PLACEMENT_ONLY;
1063 oh->sequence = 0;
1064 oh->length = sizeof(struct abis_om_nokia_hdr) + len_data;
1065
1066 noh = (struct abis_om_nokia_hdr *)oh->data;
1067
1068 noh->msg_type = msg_type;
1069 noh->spare = 0;
1070 noh->reference = htons(ref);
1071 memcpy(noh->data, data, len_data);
1072
1073 DEBUGPC(DNM, "Sending %s\n", get_msg_type_name_string(msg_type));
1074
1075 return abis_nm_sendmsg(bts, msg);
Dieter Spaar16646022011-07-28 00:01:50 +02001076}
1077
1078/* TODO: put in a separate file ? */
1079
1080static uint8_t download_req[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001081 0x5F, 0x25, 0x0B,
1082 /* ID = 0x25 (File identity) */
1083 /* length = 11 */
1084 /* [3] */
1085 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A, 0x2A,
1086 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001087
Harald Weltebda367c2011-07-28 00:03:49 +02001088 0x5F, 0x78, 0x03,
1089 /* ID = 0x78 (File version) */
1090 /* length = 3 */
1091 /* [17] */
1092 0x2A, 0x2A, 0x2A,
Dieter Spaar16646022011-07-28 00:01:50 +02001093
Harald Weltebda367c2011-07-28 00:03:49 +02001094 0x5F, 0x81, 0x0A, 0x01,
1095 /* ID = 0x8A (SW load mode) */
1096 /* length = 1 */
1097 /* [24] */
1098 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001099
Harald Weltebda367c2011-07-28 00:03:49 +02001100 0x5F, 0x81, 0x06, 0x01,
1101 /* ID = 0x86 (Acknowledgement period) */
1102 /* length = 1 */
1103 /* [29] */
1104 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001105};
1106
1107static int abis_nm_download_req(struct gsm_bts *bts, uint16_t ref)
1108{
Harald Weltebda367c2011-07-28 00:03:49 +02001109 uint8_t *data = download_req;
1110 int len_data = sizeof(download_req);
1111
1112 return abis_nm_send(bts, NOKIA_MSG_START_DOWNLOAD_REQ, ref, data,
1113 len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001114}
1115
1116/* TODO: put in a separate file ? */
1117
1118static uint8_t ack[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001119 0x5F, 0x23, 0x01,
1120 /* ID = 0x23 (Ack-Nack) */
1121 /* length = 1 */
1122 /* [3] */
1123 0x01,
Dieter Spaar16646022011-07-28 00:01:50 +02001124};
1125
1126static int abis_nm_ack(struct gsm_bts *bts, uint16_t ref)
1127{
Harald Weltebda367c2011-07-28 00:03:49 +02001128 uint8_t *data = ack;
1129 int len_data = sizeof(ack);
1130
1131 return abis_nm_send(bts, NOKIA_MSG_ACK, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001132}
1133
1134/* TODO: put in a separate file ? */
1135
1136static uint8_t reset[] = {
Harald Weltebda367c2011-07-28 00:03:49 +02001137 0x5F, 0x40, 0x04,
1138 /* ID = 0x40 (Object identity) */
1139 /* length = 4 */
1140 /* [3] */
1141 0x00, 0x01, 0xFF, 0xFF,
Dieter Spaar16646022011-07-28 00:01:50 +02001142};
1143
1144static int abis_nm_reset(struct gsm_bts *bts, uint16_t ref)
1145{
Harald Weltebda367c2011-07-28 00:03:49 +02001146 uint8_t *data = reset;
1147 int len_data = sizeof(reset);
Sipos Csaba56e17662015-02-07 13:27:36 +01001148 LOGP(DLINP, LOGL_INFO, "Nokia BTS reset timer: %d\n", bts->nokia.bts_reset_timer_cnf);
Harald Weltebda367c2011-07-28 00:03:49 +02001149 return abis_nm_send(bts, NOKIA_MSG_RESET_REQ, ref, data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001150}
1151
1152/* TODO: put in a separate file ? */
1153
Harald Weltebda367c2011-07-28 00:03:49 +02001154static int abis_nm_send_multi_segments(struct gsm_bts *bts, uint8_t msg_type,
1155 uint16_t ref, uint8_t * data, int len)
Dieter Spaar16646022011-07-28 00:01:50 +02001156{
Harald Weltebda367c2011-07-28 00:03:49 +02001157 int len_remain, len_to_send, max_send;
1158 int seq = 0;
1159 int ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001160
Harald Weltebda367c2011-07-28 00:03:49 +02001161 len_remain = len;
1162
1163 while (len_remain) {
1164 struct abis_om_hdr *oh;
1165 struct abis_om_nokia_hdr *noh;
1166 struct msgb *msg = nm_msgb_alloc();
1167
1168 if (seq == 0)
1169 max_send = 256 - sizeof(struct abis_om_nokia_hdr);
1170 else
1171 max_send = 256;
1172
1173 if (len_remain > max_send) {
1174 len_to_send = max_send;
1175
1176 if (seq == 0) {
1177 /* first segment */
1178 oh = (struct abis_om_hdr *)msgb_put(msg,
1179 ABIS_OM_NOKIA_HDR_SIZE
1180 +
1181 len_to_send);
1182
1183 oh->mdisc = ABIS_OM_MDISC_FOM;
1184 oh->placement = ABIS_OM_PLACEMENT_FIRST; /* first segment of multi-segment message */
1185 oh->sequence = seq;
1186 oh->length = 0; /* 256 bytes */
1187
1188 noh = (struct abis_om_nokia_hdr *)oh->data;
1189
1190 noh->msg_type = msg_type;
1191 noh->spare = 0;
1192 noh->reference = htons(ref);
1193 memcpy(noh->data, data, len_to_send);
1194 } else {
1195 /* segment in between */
1196 oh = (struct abis_om_hdr *)msgb_put(msg,
1197 sizeof
1198 (struct
1199 abis_om_hdr)
1200 +
1201 len_to_send);
1202
1203 oh->mdisc = ABIS_OM_MDISC_FOM;
1204 oh->placement = ABIS_OM_PLACEMENT_MIDDLE; /* segment of multi-segment message */
1205 oh->sequence = seq;
1206 oh->length = 0; /* 256 bytes */
1207
1208 memcpy(oh->data, data, len_to_send);
1209 }
1210 } else {
1211
1212 len_to_send = len_remain;
1213
1214 /* check if message fits in a single segment */
1215
1216 if (seq == 0)
1217 return abis_nm_send(bts, msg_type, ref, data,
1218 len_to_send);
1219
1220 /* last segment */
1221
1222 oh = (struct abis_om_hdr *)msgb_put(msg,
1223 sizeof(struct
1224 abis_om_hdr)
1225 + len_to_send);
1226
1227 oh->mdisc = ABIS_OM_MDISC_FOM;
1228 oh->placement = ABIS_OM_PLACEMENT_LAST; /* last segment of multi-segment message */
1229 oh->sequence = seq;
1230 oh->length = len_to_send;
1231
1232 memcpy(oh->data, data, len_to_send);
1233 }
1234
1235 DEBUGPC(DNM, "Sending multi-segment %d\n", seq);
1236
1237 ret = abis_nm_sendmsg(bts, msg);
1238 if (ret < 0)
1239 return ret;
1240
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001241 nokia_abis_nm_queue_send_next(bts);
Harald Weltebda367c2011-07-28 00:03:49 +02001242
1243 /* next segment */
1244 len_remain -= len_to_send;
1245 data += len_to_send;
1246 seq++;
1247 }
Pau Espin Pedrol39fb1fb2018-03-26 18:09:19 +02001248
1249 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001250}
1251
1252/* TODO: put in a separate file ? */
1253
1254static int abis_nm_send_config(struct gsm_bts *bts, uint8_t bts_type)
1255{
Harald Weltebda367c2011-07-28 00:03:49 +02001256 struct gsm_bts_trx *trx;
1257 uint8_t config[2048]; /* TODO: might be too small if lots of TRX are used */
1258 int len = 0;
1259 int idx = 0;
1260 int ret;
1261 int hopping = 0;
1262 int need_hopping = 0;
1263
1264 memset(config, 0, sizeof(config));
1265
1266 llist_for_each_entry(trx, &bts->trx_list, list) {
1267#if 0 /* debugging */
1268 printf("TRX\n");
1269 printf(" arfcn: %d\n", trx->arfcn);
1270 printf(" bsic: %d\n", trx->bts->bsic);
1271 uint8_t ca[20];
1272 memset(ca, 0xFF, sizeof(ca));
1273 ret = generate_cell_chan_list(ca, trx->bts);
1274 printf(" ca (%d): %s\n", ret, osmo_hexdump(ca, sizeof(ca)));
1275 int i;
1276 for (i = 0; i < ARRAY_SIZE(trx->ts); i++) {
1277 struct gsm_bts_trx_ts *ts = &trx->ts[i];
1278
1279 printf(" pchan %d: %d\n", i, ts->pchan);
1280 }
Dieter Spaar16646022011-07-28 00:01:50 +02001281#endif
Harald Weltebda367c2011-07-28 00:03:49 +02001282 ret = make_fu_config(trx, idx + 1, config + len, &hopping);
1283 need_hopping |= hopping;
1284 len += ret;
1285
1286 idx++;
1287 }
1288
1289 ret = make_bts_config(bts_type, idx, config + len, need_hopping);
1290 len += ret;
1291
1292#if 0 /* debugging */
1293 dump_elements(config, len);
1294#endif
1295
1296 return abis_nm_send_multi_segments(bts, NOKIA_MSG_CONF_DATA, 1, config,
1297 len);
Dieter Spaar16646022011-07-28 00:01:50 +02001298}
1299
1300#define GET_NEXT_BYTE if(idx >= len) return 0; \
Harald Weltebda367c2011-07-28 00:03:49 +02001301 ub = data[idx++];
Dieter Spaar16646022011-07-28 00:01:50 +02001302
Harald Weltebda367c2011-07-28 00:03:49 +02001303static int find_element(uint8_t * data, int len, uint16_t id, uint8_t * value,
1304 int max_value)
1305{
1306 uint8_t ub;
1307 int idx = 0;
1308 int found = 0;
Holger Hans Peter Freythera5050b12012-09-11 11:55:03 +02001309 int constructed __attribute__((unused));
Harald Weltebda367c2011-07-28 00:03:49 +02001310 uint16_t id_value;
1311
1312 for (;;) {
1313
1314 GET_NEXT_BYTE;
1315
1316 /* encoding bit, construced means that other elements are contained */
1317 constructed = ((ub & 0x20) ? 1 : 0);
1318
1319 if ((ub & 0x1F) == 0x1F) {
1320 /* fixed pattern, ID follows */
1321 GET_NEXT_BYTE; /* ID */
1322 id_value = ub & 0x7F;
1323 if (ub & 0x80) {
1324 /* extension bit */
1325 GET_NEXT_BYTE; /* ID low part */
1326 id_value = (id_value << 7) | (ub & 0x7F);
1327 }
1328 if (id_value == id)
1329 found = 1;
1330 } else {
1331 id_value = (ub & 0x3F);
1332 if (id_value == id)
1333 found = 1;
1334 }
1335
1336 GET_NEXT_BYTE; /* length */
1337
1338 if (found) {
1339 /* get data */
1340 uint8_t n = ub;
1341 uint8_t i;
1342 for (i = 0; i < n; i++) {
1343 GET_NEXT_BYTE;
1344 if (max_value <= 0)
1345 return -1; /* buffer too small */
1346 *value = ub;
1347 value++;
1348 max_value--;
1349 }
1350 return n; /* length */
1351 } else {
1352 /* skip data */
1353 uint8_t n = ub;
1354 uint8_t i;
1355 for (i = 0; i < n; i++) {
1356 GET_NEXT_BYTE;
1357 }
1358 }
1359 }
1360 return 0; /* not found */
Dieter Spaar16646022011-07-28 00:01:50 +02001361}
1362
Harald Weltebda367c2011-07-28 00:03:49 +02001363static int dump_elements(uint8_t * data, int len)
1364{
1365 uint8_t ub;
1366 int idx = 0;
1367 int constructed;
1368 uint16_t id_value;
1369 static char indent[100] = ""; /* TODO: move static to BTS context */
Dieter Spaar16646022011-07-28 00:01:50 +02001370
Harald Weltebda367c2011-07-28 00:03:49 +02001371 for (;;) {
1372
1373 GET_NEXT_BYTE;
1374
1375 /* encoding bit, construced means that other elements are contained */
1376 constructed = ((ub & 0x20) ? 1 : 0);
1377
1378 if ((ub & 0x1F) == 0x1F) {
1379 /* fixed pattern, ID follows */
1380 GET_NEXT_BYTE; /* ID */
1381 id_value = ub & 0x7F;
1382 if (ub & 0x80) {
1383 /* extension bit */
1384 GET_NEXT_BYTE; /* ID low part */
1385 id_value = (id_value << 7) | (ub & 0x7F);
1386 }
1387
1388 } else {
1389 id_value = (ub & 0x3F);
1390 }
1391
1392 GET_NEXT_BYTE; /* length */
1393
1394 printf("%s--ID = 0x%02X (%s) %s\n", indent, id_value,
1395 get_element_name_string(id_value),
1396 constructed ? "** constructed **" : "");
1397 printf("%s length = %d\n", indent, ub);
1398 printf("%s %s\n", indent, osmo_hexdump(data + idx, ub));
1399
1400 if (constructed) {
1401 int indent_len = strlen(indent);
1402 strcat(indent, " ");
1403
1404 dump_elements(data + idx, ub);
1405
1406 indent[indent_len] = 0;
1407 }
1408 /* skip data */
1409 uint8_t n = ub;
1410 uint8_t i;
1411 for (i = 0; i < n; i++) {
1412 GET_NEXT_BYTE;
1413 }
1414 }
1415 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001416}
1417
1418/* TODO: put in a separate file ? */
1419
1420/* taken from abis_nm.c */
1421
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001422static void nokia_abis_nm_queue_send_next(struct gsm_bts *bts)
Dieter Spaar16646022011-07-28 00:01:50 +02001423{
Harald Weltebda367c2011-07-28 00:03:49 +02001424 int wait = 0;
1425 struct msgb *msg;
1426 /* the queue is empty */
1427 while (!llist_empty(&bts->abis_queue)) {
1428 msg = msgb_dequeue(&bts->abis_queue);
1429 wait = OBSC_NM_W_ACK_CB(msg);
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001430 abis_sendmsg(msg);
Dieter Spaar16646022011-07-28 00:01:50 +02001431
Harald Weltebda367c2011-07-28 00:03:49 +02001432 if (wait)
1433 break;
1434 }
Dieter Spaar16646022011-07-28 00:01:50 +02001435
Harald Weltebda367c2011-07-28 00:03:49 +02001436 bts->abis_nm_pend = wait;
Dieter Spaar16646022011-07-28 00:01:50 +02001437}
1438
1439/* TODO: put in a separate file ? */
1440
1441/* timer for restarting OML after BTS reset */
1442
1443static void reset_timer_cb(void *_bts)
1444{
Harald Weltebda367c2011-07-28 00:03:49 +02001445 struct gsm_bts *bts = _bts;
1446 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1447 struct e1inp_line *line;
1448
Harald Weltec8755af2011-07-28 00:22:17 +02001449 bts->nokia.wait_reset = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001450
1451 /* OML link */
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001452 line = e1inp_line_find(e1_link->e1_nr);
Harald Weltebda367c2011-07-28 00:03:49 +02001453 if (!line) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001454 LOGP(DLINP, LOGL_ERROR, "BTS %u OML link referring to "
Harald Weltebda367c2011-07-28 00:03:49 +02001455 "non-existing E1 line %u\n", bts->nr, e1_link->e1_nr);
1456 return;
1457 }
1458
1459 start_sabm_in_line(line, 0, -1); /* stop all first */
1460 start_sabm_in_line(line, 1, SAPI_OML); /* start only OML */
Dieter Spaar16646022011-07-28 00:01:50 +02001461}
1462
1463/* TODO: put in a separate file ? */
1464
1465/*
1466 This is how the configuration is done:
Dieter Spaar16646022011-07-28 00:01:50 +02001467 - start OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001468 - reset BTS
Dieter Spaar16646022011-07-28 00:01:50 +02001469 - receive ACK, wait some time and restart OML link
Dieter Spaar16646022011-07-28 00:01:50 +02001470 - receive OMU STARTED message, send START DOWNLOAD REQ
Dieter Spaar16646022011-07-28 00:01:50 +02001471 - receive CNF REQ message, send CONF DATA
Dieter Spaar16646022011-07-28 00:01:50 +02001472 - receive ACK, start RSL link(s)
Dieter Spaar16646022011-07-28 00:01:50 +02001473 ACK some other messages received from the BTS.
Harald Weltecde57942011-07-28 00:13:46 +02001474
Dieter Spaar16646022011-07-28 00:01:50 +02001475 Probably its also possible to configure the BTS without a reset, this
1476 has not been tested yet.
1477*/
1478
1479static int abis_nm_rcvmsg_fom(struct msgb *mb)
1480{
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001481 struct e1inp_sign_link *sign_link = (struct e1inp_sign_link *)mb->dst;
1482 struct gsm_bts *bts = sign_link->trx->bts;
Harald Weltebda367c2011-07-28 00:03:49 +02001483 struct abis_om_hdr *oh = msgb_l2(mb);
1484 struct abis_om_nokia_hdr *noh = msgb_l3(mb);
1485 uint8_t mt = noh->msg_type;
1486 int ret = 0;
1487 uint16_t ref = ntohs(noh->reference);
Harald Weltebda367c2011-07-28 00:03:49 +02001488 uint8_t info[256];
1489 uint8_t ack = 0xFF;
1490 uint8_t severity = 0xFF;
1491 int str_len;
1492 int len_data;
Dieter Spaar16646022011-07-28 00:01:50 +02001493
Harald Weltec8755af2011-07-28 00:22:17 +02001494 if (bts->nokia.wait_reset) {
Harald Weltebda367c2011-07-28 00:03:49 +02001495 LOGP(DNM, LOGL_INFO,
1496 "Ignore message while waiting for reset\n");
1497 return ret;
1498 }
Dieter Spaar16646022011-07-28 00:01:50 +02001499
Harald Weltebda367c2011-07-28 00:03:49 +02001500 if (oh->length < sizeof(struct abis_om_nokia_hdr)) {
1501 LOGP(DNM, LOGL_ERROR, "Message too short\n");
1502 return -EINVAL;
1503 }
1504
1505 len_data = oh->length - sizeof(struct abis_om_nokia_hdr);
1506 LOGP(DNM, LOGL_INFO, "(0x%02X) %s\n", mt, get_msg_type_name_string(mt));
1507#if 0 /* debugging */
1508 dump_elements(noh->data, len_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001509#endif
Dieter Spaar16646022011-07-28 00:01:50 +02001510
Harald Weltebda367c2011-07-28 00:03:49 +02001511 switch (mt) {
1512 case NOKIA_MSG_OMU_STARTED:
Harald Welte9d2f3772011-07-28 00:19:06 +02001513 if (find_element(noh->data, len_data,
1514 NOKIA_EI_BTS_TYPE, &bts->nokia.bts_type,
1515 sizeof(uint8_t)) == sizeof(uint8_t))
1516 LOGP(DNM, LOGL_INFO, "BTS type = %d (%s)\n",
1517 bts->nokia.bts_type,
1518 get_bts_type_string(bts->nokia.bts_type));
Harald Weltebda367c2011-07-28 00:03:49 +02001519 else
1520 LOGP(DNM, LOGL_ERROR, "BTS type not found\n");
1521 /* send START_DOWNLOAD_REQ */
1522 abis_nm_download_req(bts, ref);
1523 break;
1524 case NOKIA_MSG_MF_REQ:
1525 break;
1526 case NOKIA_MSG_CONF_REQ:
1527 /* send ACK */
1528 abis_nm_ack(bts, ref);
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001529 nokia_abis_nm_queue_send_next(bts);
Harald Weltebda367c2011-07-28 00:03:49 +02001530 /* send CONF_DATA */
Harald Welte9d2f3772011-07-28 00:19:06 +02001531 abis_nm_send_config(bts, bts->nokia.bts_type);
1532 bts->nokia.configured = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001533 break;
1534 case NOKIA_MSG_ACK:
1535 if (find_element
1536 (noh->data, len_data, NOKIA_EI_ACK, &ack,
1537 sizeof(uint8_t)) == sizeof(uint8_t)) {
1538 LOGP(DNM, LOGL_INFO, "ACK = %d\n", ack);
1539 if (ack != 1) {
1540 LOGP(DNM, LOGL_ERROR, "No ACK received (%d)\n",
1541 ack);
1542 /* TODO: properly handle failures (NACK) */
1543 }
1544 } else
1545 LOGP(DNM, LOGL_ERROR, "ACK not found\n");
Dieter Spaar16646022011-07-28 00:01:50 +02001546
Harald Weltebda367c2011-07-28 00:03:49 +02001547 /* TODO: the assumption for the following is that no NACK was received */
1548
1549 /* ACK for reset message ? */
Sylvain Munautc9519462011-10-17 14:04:55 +02001550 if (!bts->nokia.did_reset) {
1551 bts->nokia.did_reset = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001552
1553 /*
1554 TODO: For the InSite processing the received data is
1555 blocked in the driver during reset.
1556 Otherwise the LAPD module might assert because the InSite
1557 sends garbage on the E1 line during reset.
1558 This is done by looking at "wait_reset" in the driver
1559 (function handle_ts1_read()) and ignoring the received data.
1560 It seems to be necessary for the MetroSite too.
1561 */
Harald Weltec8755af2011-07-28 00:22:17 +02001562 bts->nokia.wait_reset = 1;
Harald Weltebda367c2011-07-28 00:03:49 +02001563
Pablo Neira Ayuso51215762017-05-08 20:57:52 +02001564 osmo_timer_setup(&bts->nokia.reset_timer,
1565 reset_timer_cb, bts);
Sipos Csaba56e17662015-02-07 13:27:36 +01001566 osmo_timer_schedule(&bts->nokia.reset_timer, bts->nokia.bts_reset_timer_cnf, 0);
Harald Weltebda367c2011-07-28 00:03:49 +02001567
1568 struct gsm_e1_subslot *e1_link = &bts->oml_e1_link;
1569 struct e1inp_line *line;
1570 /* OML link */
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001571 line = e1inp_line_find(e1_link->e1_nr);
Harald Weltebda367c2011-07-28 00:03:49 +02001572 if (!line) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001573 LOGP(DLINP, LOGL_ERROR,
Harald Weltebda367c2011-07-28 00:03:49 +02001574 "BTS %u OML link referring to "
1575 "non-existing E1 line %u\n", bts->nr,
1576 e1_link->e1_nr);
1577 return -ENOMEM;
1578 }
1579
1580 start_sabm_in_line(line, 0, -1); /* stop all first */
1581 }
1582
1583 /* ACK for CONF DATA message ? */
Harald Welte9d2f3772011-07-28 00:19:06 +02001584 if (bts->nokia.configured != 0) {
Harald Weltebda367c2011-07-28 00:03:49 +02001585 /* start TRX (RSL link) */
1586
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001587 struct gsm_e1_subslot *e1_link =
1588 &sign_link->trx->rsl_e1_link;
Harald Weltebda367c2011-07-28 00:03:49 +02001589 struct e1inp_line *line;
1590
Harald Welte9d2f3772011-07-28 00:19:06 +02001591 bts->nokia.configured = 0;
Harald Weltebda367c2011-07-28 00:03:49 +02001592
1593 /* RSL Link */
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001594 line = e1inp_line_find(e1_link->e1_nr);
Harald Weltebda367c2011-07-28 00:03:49 +02001595 if (!line) {
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001596 LOGP(DLINP, LOGL_ERROR,
Harald Weltebda367c2011-07-28 00:03:49 +02001597 "TRX (%u/%u) RSL link referring "
1598 "to non-existing E1 line %u\n",
Pablo Neira Ayuso7abecfc2011-08-17 22:43:54 +02001599 sign_link->trx->bts->nr, sign_link->trx->nr,
Harald Weltebda367c2011-07-28 00:03:49 +02001600 e1_link->e1_nr);
1601 return -ENOMEM;
1602 }
1603 /* start TRX */
1604 start_sabm_in_line(line, 1, SAPI_RSL); /* start only RSL */
1605 }
1606 break;
1607 case NOKIA_MSG_STATE_CHANGED:
1608 /* send ACK */
1609 abis_nm_ack(bts, ref);
1610 break;
1611 case NOKIA_MSG_CONF_COMPLETE:
1612 /* send ACK */
1613 abis_nm_ack(bts, ref);
1614 break;
1615 case NOKIA_MSG_BLOCK_CTRL_REQ: /* seems to be send when something goes wrong !? */
1616 /* send ACK (do we have to send an ACK ?) */
1617 abis_nm_ack(bts, ref);
1618 break;
1619 case NOKIA_MSG_ALARM:
1620 find_element(noh->data, len_data, NOKIA_EI_SEVERITY, &severity,
1621 sizeof(severity));
1622 /* TODO: there might be alarms with both elements set */
1623 str_len =
1624 find_element(noh->data, len_data, NOKIA_EI_ADD_INFO, info,
1625 sizeof(info));
1626 if (str_len > 0) {
1627 info[str_len] = 0;
1628 LOGP(DNM, LOGL_INFO, "ALARM Severity %s (%d) : %s\n",
1629 get_severity_string(severity), severity, info);
1630 } else { /* nothing found, try details */
1631 str_len =
1632 find_element(noh->data, len_data,
1633 NOKIA_EI_ALARM_DETAIL, info,
1634 sizeof(info));
1635 if (str_len > 0) {
1636 uint16_t code;
1637 info[str_len] = 0;
1638 code = (info[0] << 8) + info[1];
1639 LOGP(DNM, LOGL_INFO,
1640 "ALARM Severity %s (%d), code 0x%X : %s\n",
1641 get_severity_string(severity), severity,
1642 code, info + 2);
1643 }
1644 }
1645 /* send ACK */
1646 abis_nm_ack(bts, ref);
1647 break;
1648 }
1649
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001650 nokia_abis_nm_queue_send_next(bts);
Harald Weltebda367c2011-07-28 00:03:49 +02001651
1652 return ret;
Dieter Spaar16646022011-07-28 00:01:50 +02001653}
1654
1655/* TODO: put in a separate file ? */
1656
1657int abis_nokia_rcvmsg(struct msgb *msg)
1658{
Harald Weltebda367c2011-07-28 00:03:49 +02001659 struct abis_om_hdr *oh = msgb_l2(msg);
1660 int rc = 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001661
Harald Weltebda367c2011-07-28 00:03:49 +02001662 /* Various consistency checks */
1663 if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
1664 LOGP(DNM, LOGL_ERROR, "ABIS OML placement 0x%x not supported\n",
1665 oh->placement);
1666 if (oh->placement != ABIS_OM_PLACEMENT_FIRST)
1667 return -EINVAL;
1668 }
1669 if (oh->sequence != 0) {
1670 LOGP(DNM, LOGL_ERROR, "ABIS OML sequence 0x%x != 0x00\n",
1671 oh->sequence);
1672 return -EINVAL;
1673 }
1674 msg->l3h = (unsigned char *)oh + sizeof(*oh);
Dieter Spaar16646022011-07-28 00:01:50 +02001675
Harald Weltebda367c2011-07-28 00:03:49 +02001676 switch (oh->mdisc) {
1677 case ABIS_OM_MDISC_FOM:
1678 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_FOM\n");
1679 rc = abis_nm_rcvmsg_fom(msg);
1680 break;
1681 case ABIS_OM_MDISC_MANUF:
1682 LOGP(DNM, LOGL_INFO, "ABIS_OM_MDISC_MANUF\n");
1683 break;
1684 case ABIS_OM_MDISC_MMI:
1685 case ABIS_OM_MDISC_TRAU:
1686 LOGP(DNM, LOGL_ERROR,
1687 "unimplemented ABIS OML message discriminator 0x%x\n",
1688 oh->mdisc);
1689 break;
1690 default:
1691 LOGP(DNM, LOGL_ERROR,
1692 "unknown ABIS OML message discriminator 0x%x\n",
1693 oh->mdisc);
1694 return -EINVAL;
1695 }
Dieter Spaar16646022011-07-28 00:01:50 +02001696
Harald Weltebda367c2011-07-28 00:03:49 +02001697 msgb_free(msg);
1698 return rc;
Dieter Spaar16646022011-07-28 00:01:50 +02001699}
1700
1701static int bts_model_nokia_site_start(struct gsm_network *net);
1702
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001703static void bts_model_nokia_site_e1line_bind_ops(struct e1inp_line *line)
1704{
1705 e1inp_line_bind_ops(line, &bts_isdn_e1inp_line_ops);
1706}
1707
Dieter Spaar16646022011-07-28 00:01:50 +02001708static struct gsm_bts_model model_nokia_site = {
Harald Weltebda367c2011-07-28 00:03:49 +02001709 .type = GSM_BTS_TYPE_NOKIA_SITE,
1710 .name = "nokia_site",
1711 .start = bts_model_nokia_site_start,
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001712 .oml_rcvmsg = &abis_nokia_rcvmsg,
1713 .e1line_bind_ops = &bts_model_nokia_site_e1line_bind_ops,
Dieter Spaar16646022011-07-28 00:01:50 +02001714};
1715
1716static struct gsm_network *my_net;
1717
1718static int bts_model_nokia_site_start(struct gsm_network *net)
1719{
Harald Weltebda367c2011-07-28 00:03:49 +02001720 model_nokia_site.features.data = &model_nokia_site._features_data[0];
1721 model_nokia_site.features.data_len =
1722 sizeof(model_nokia_site._features_data);
Dieter Spaar16646022011-07-28 00:01:50 +02001723
Philipp Maier8c498fc2018-02-21 13:24:36 +01001724 osmo_bts_set_feature(&model_nokia_site.features, BTS_FEAT_HOPPING);
1725 osmo_bts_set_feature(&model_nokia_site.features, BTS_FEAT_HSCSD);
1726 osmo_bts_set_feature(&model_nokia_site.features, BTS_FEAT_MULTI_TSC);
Dieter Spaar16646022011-07-28 00:01:50 +02001727
Pablo Neira Ayusoed5cacb2011-08-17 22:44:07 +02001728 osmo_signal_register_handler(SS_L_INPUT, inp_sig_cb, NULL);
1729 osmo_signal_register_handler(SS_L_GLOBAL, gbl_sig_cb, NULL);
Harald Weltebda367c2011-07-28 00:03:49 +02001730 osmo_signal_register_handler(SS_NM, nm_sig_cb, NULL);
Dieter Spaar16646022011-07-28 00:01:50 +02001731
Harald Weltebda367c2011-07-28 00:03:49 +02001732 my_net = net;
1733
1734 return 0;
Dieter Spaar16646022011-07-28 00:01:50 +02001735}
1736
1737int bts_model_nokia_site_init(void)
1738{
Harald Weltebda367c2011-07-28 00:03:49 +02001739 return gsm_bts_model_register(&model_nokia_site);
Dieter Spaar16646022011-07-28 00:01:50 +02001740}