blob: 2ce5923a35843335390cb61cd20f63f31371e849 [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* GSM Network Management (OML) messages on the A-bis interface
2 * 3GPP TS 12.21 version 8.0.0 Release 1999 / ETSI TS 100 623 V8.0.0 */
3
4/* (C) 2008 by Harald Welte <laforge@gnumonks.org>
Harald Welte8470bf22008-12-25 23:28:35 +00005 *
Harald Welte52b1f982008-12-23 20:25:15 +00006 * All Rights Reserved
7 *
8 * This program is free software; you can redistribute it and/or modify
9 * it under the terms of the GNU General Public License as published by
10 * the Free Software Foundation; either version 2 of the License, or
11 * (at your option) any later version.
12 *
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
17 *
18 * You should have received a copy of the GNU General Public License along
19 * with this program; if not, write to the Free Software Foundation, Inc.,
20 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
21 *
22 */
23
24
25#include <errno.h>
26#include <stdio.h>
27#include <sys/types.h>
Harald Welte8470bf22008-12-25 23:28:35 +000028#include <netinet/in.h>
Harald Welte52b1f982008-12-23 20:25:15 +000029
Harald Welte8470bf22008-12-25 23:28:35 +000030#include <openbsc/gsm_data.h>
31#include <openbsc/debug.h>
32#include <openbsc/msgb.h>
33#include <openbsc/tlv.h>
34#include <openbsc/abis_nm.h>
Holger Freytherca362a62009-01-04 21:05:01 +000035#include <openbsc/misdn.h>
Harald Welte52b1f982008-12-23 20:25:15 +000036
Harald Welte8470bf22008-12-25 23:28:35 +000037#define OM_ALLOC_SIZE 1024
38#define OM_HEADROOM_SIZE 128
Harald Welte52b1f982008-12-23 20:25:15 +000039
40/* unidirectional messages from BTS to BSC */
41static const enum abis_nm_msgtype reports[] = {
42 NM_MT_SW_ACTIVATED_REP,
43 NM_MT_TEST_REP,
44 NM_MT_STATECHG_EVENT_REP,
45 NM_MT_FAILURE_EVENT_REP,
46};
47
48/* messages without ACK/NACK */
49static const enum abis_nm_msgtype no_ack_nack[] = {
50 NM_MT_MEAS_RES_REQ,
51 NM_MT_STOP_MEAS,
52 NM_MT_START_MEAS,
53};
54
55/* Attributes that the BSC can set, not only get, according to Section 9.4 */
56static const enum abis_nm_attr nm_att_settable[] = {
57 NM_ATT_ADD_INFO,
58 NM_ATT_ADD_TEXT,
59 NM_ATT_DEST,
60 NM_ATT_EVENT_TYPE,
61 NM_ATT_FILE_DATA,
62 NM_ATT_GET_ARI,
63 NM_ATT_HW_CONF_CHG,
64 NM_ATT_LIST_REQ_ATTR,
65 NM_ATT_MDROP_LINK,
66 NM_ATT_MDROP_NEXT,
67 NM_ATT_NACK_CAUSES,
68 NM_ATT_OUTST_ALARM,
69 NM_ATT_PHYS_CONF,
70 NM_ATT_PROB_CAUSE,
71 NM_ATT_RAD_SUBC,
72 NM_ATT_SOURCE,
73 NM_ATT_SPEC_PROB,
74 NM_ATT_START_TIME,
75 NM_ATT_TEST_DUR,
76 NM_ATT_TEST_NO,
77 NM_ATT_TEST_REPORT,
78 NM_ATT_WINDOW_SIZE,
79 NM_ATT_SEVERITY,
80 NM_ATT_MEAS_RES,
81 NM_ATT_MEAS_TYPE,
82};
83
84static int is_in_arr(enum abis_nm_msgtype mt, const enum abis_nm_msgtype *arr, int size)
85{
86 int i;
87
88 for (i = 0; i < size; i++) {
89 if (arr[i] == mt)
90 return 1;
91 }
92
93 return 0;
94}
95
Holger Freytherca362a62009-01-04 21:05:01 +000096#if 0
Harald Welte52b1f982008-12-23 20:25:15 +000097/* is this msgtype the usual ACK/NACK type ? */
98static int is_ack_nack(enum abis_nm_msgtype mt)
99{
100 return !is_in_arr(mt, no_ack_nack, ARRAY_SIZE(no_ack_nack));
101}
Holger Freytherca362a62009-01-04 21:05:01 +0000102#endif
Harald Welte52b1f982008-12-23 20:25:15 +0000103
104/* is this msgtype a report ? */
105static int is_report(enum abis_nm_msgtype mt)
106{
Harald Welte8470bf22008-12-25 23:28:35 +0000107 return is_in_arr(mt, reports, ARRAY_SIZE(reports));
Harald Welte52b1f982008-12-23 20:25:15 +0000108}
109
110#define MT_ACK(x) (x+1)
111#define MT_NACK(x) (x+2)
112
113static void fill_om_hdr(struct abis_om_hdr *oh, u_int8_t len)
114{
115 oh->mdisc = ABIS_OM_MDISC_FOM;
116 oh->placement = ABIS_OM_PLACEMENT_ONLY;
117 oh->sequence = 0;
118 oh->length = len;
119}
120
121static void fill_om_fom_hdr(struct abis_om_hdr *oh, u_int8_t len,
122 u_int8_t msg_type, u_int8_t obj_class,
123 u_int8_t bts_nr, u_int8_t trx_nr, u_int8_t ts_nr)
124{
125 struct abis_om_fom_hdr *foh =
126 (struct abis_om_fom_hdr *) oh->data;
127
Harald Welte702d8702008-12-26 20:25:35 +0000128 fill_om_hdr(oh, len+sizeof(*foh));
Harald Welte52b1f982008-12-23 20:25:15 +0000129 foh->msg_type = msg_type;
130 foh->obj_class = obj_class;
131 foh->obj_inst.bts_nr = bts_nr;
132 foh->obj_inst.trx_nr = trx_nr;
133 foh->obj_inst.ts_nr = ts_nr;
134}
135
Harald Welte8470bf22008-12-25 23:28:35 +0000136static struct msgb *nm_msgb_alloc(void)
137{
138 return msgb_alloc_headroom(OM_ALLOC_SIZE, OM_HEADROOM_SIZE);
139}
140
Harald Welte52b1f982008-12-23 20:25:15 +0000141/* Send a OML NM Message from BSC to BTS */
142int abis_nm_sendmsg(struct gsm_bts *bts, struct msgb *msg)
143{
Harald Weltead384642008-12-26 10:20:07 +0000144 return _abis_nm_sendmsg(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000145}
146
147/* Receive a OML NM Message from BTS */
Harald Welte8470bf22008-12-25 23:28:35 +0000148static int abis_nm_rcvmsg_fom(struct msgb *mb)
Harald Welte52b1f982008-12-23 20:25:15 +0000149{
150 struct abis_om_fom_hdr *foh = msgb_l3(mb);
151 u_int8_t mt = foh->msg_type;
152
153 /* check for unsolicited message */
154 if (is_report(mt)) {
Harald Weltead384642008-12-26 10:20:07 +0000155 DEBUGP(DNM, "reporting NM MT 0x%02x\n", mt);
156 //nmh->cfg->report_cb(mb, foh);
Harald Welte52b1f982008-12-23 20:25:15 +0000157 return 0;
158 }
159
Harald Weltead384642008-12-26 10:20:07 +0000160#if 0
Harald Welte52b1f982008-12-23 20:25:15 +0000161 /* check if last message is to be acked */
162 if (is_ack_nack(nmh->last_msgtype)) {
163 if (mt == MT_ACK(nmh->last_msgtype)) {
164 fprintf(stderr, "received ACK (0x%x)\n",
165 foh->msg_type);
166 /* we got our ACK, continue sending the next msg */
167 } else if (mt == MT_NACK(nmh->last_msgtype)) {
168 /* we got a NACK, signal this to the caller */
169 fprintf(stderr, "received NACK (0x%x)\n",
170 foh->msg_type);
171 /* FIXME: somehow signal this to the caller */
172 } else {
173 /* really strange things happen */
174 return -EINVAL;
175 }
176 }
Harald Weltead384642008-12-26 10:20:07 +0000177#endif
178
179 return 0;
Harald Welte52b1f982008-12-23 20:25:15 +0000180}
181
182/* High-Level API */
183/* Entry-point where L2 OML from BTS enters the NM code */
Harald Welte8470bf22008-12-25 23:28:35 +0000184int abis_nm_rcvmsg(struct msgb *msg)
Harald Welte52b1f982008-12-23 20:25:15 +0000185{
186 int rc;
187 struct abis_om_hdr *oh = msgb_l2(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000188
189 /* Various consistency checks */
190 if (oh->placement != ABIS_OM_PLACEMENT_ONLY) {
191 fprintf(stderr, "ABIS OML placement 0x%x not supported\n",
192 oh->placement);
193 return -EINVAL;
194 }
195 if (oh->sequence != 0) {
196 fprintf(stderr, "ABIS OML sequence 0x%x != 0x00\n",
197 oh->sequence);
198 return -EINVAL;
199 }
Harald Welte702d8702008-12-26 20:25:35 +0000200#if 0
Holger Freytherca362a62009-01-04 21:05:01 +0000201 unsigned int l2_len = msg->tail - (u_int8_t *)msgb_l2(msg);
202 unsigned int hlen = sizeof(*oh) + sizeof(struct abis_om_fom_hdr);
Harald Welte702d8702008-12-26 20:25:35 +0000203 if (oh->length + hlen > l2_len) {
Harald Welte52b1f982008-12-23 20:25:15 +0000204 fprintf(stderr, "ABIS OML truncated message (%u > %u)\n",
205 oh->length + sizeof(*oh), l2_len);
206 return -EINVAL;
207 }
Harald Welte702d8702008-12-26 20:25:35 +0000208 if (oh->length + hlen < l2_len)
209 fprintf(stderr, "ABIS OML message with extra trailer?!? (oh->len=%d, sizeof_oh=%d l2_len=%d\n", oh->length, sizeof(*oh), l2_len);
210#endif
Harald Weltead384642008-12-26 10:20:07 +0000211 msg->l3h = (unsigned char *)oh + sizeof(*oh);
Harald Welte52b1f982008-12-23 20:25:15 +0000212
213 switch (oh->mdisc) {
214 case ABIS_OM_MDISC_FOM:
Harald Welte8470bf22008-12-25 23:28:35 +0000215 rc = abis_nm_rcvmsg_fom(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000216 break;
217 case ABIS_OM_MDISC_MMI:
218 case ABIS_OM_MDISC_TRAU:
219 case ABIS_OM_MDISC_MANUF:
220 default:
221 fprintf(stderr, "unknown ABIS OML message discriminator 0x%x\n",
222 oh->mdisc);
223 return -EINVAL;
224 }
225
Harald Weltead384642008-12-26 10:20:07 +0000226 msgb_free(msg);
Harald Welte52b1f982008-12-23 20:25:15 +0000227 return rc;
228}
229
230#if 0
231/* initialized all resources */
232struct abis_nm_h *abis_nm_init(struct abis_nm_cfg *cfg)
233{
234 struct abis_nm_h *nmh;
235
236 nmh = malloc(sizeof(*nmh));
237 if (!nmh)
238 return NULL;
239
240 nmh->cfg = cfg;
241
242 return nmh;
243}
244
245/* free all resources */
246void abis_nm_fini(struct abis_nm_h *nmh)
247{
248 free(nmh);
249}
250#endif
251
252/* Here we are trying to define a high-level API that can be used by
253 * the actual BSC implementation. However, the architecture is currently
254 * still under design. Ideally the calls to this API would be synchronous,
255 * while the underlying stack behind the APi runs in a traditional select
256 * based state machine.
257 */
258
259/* 6.2 Software Load: FIXME */
260
261
262#if 0
263struct abis_nm_sw {
264 /* this will become part of the SW LOAD INITIATE */
265 u_int8_t obj_class;
266 u_int8_t obj_instance[3];
267 u_int8_t sw_description[255];
268 u_int16_t window_size;
269 /* the actual data that is to be sent subsequently */
270 unsigned char *sw;
271 unsigned int sw_len;
272};
273
274/* Load the specified software into the BTS */
275int abis_nm_sw_load(struct abis_nm_h *h, struct abis_nm_sw *sw);
276{
277 /* FIXME: Implementation */
278}
279
280/* Activate the specified software into the BTS */
281int abis_nm_sw_activate(struct abis_nm_h *h)
282{
283
284}
285#endif
286
Harald Welte8470bf22008-12-25 23:28:35 +0000287static void fill_nm_channel(struct abis_nm_channel *ch, u_int8_t bts_port,
Harald Welte52b1f982008-12-23 20:25:15 +0000288 u_int8_t ts_nr, u_int8_t subslot_nr)
289{
Harald Welteadaf08b2009-01-18 11:08:10 +0000290 ch->attrib = NM_ATT_ABIS_CHANNEL;
Harald Welte52b1f982008-12-23 20:25:15 +0000291 ch->bts_port = bts_port;
292 ch->timeslot = ts_nr;
293 ch->subslot = subslot_nr;
294}
295
296int abis_nm_establish_tei(struct gsm_bts *bts, u_int8_t trx_nr,
297 u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot,
298 u_int8_t tei)
299{
300 struct abis_om_hdr *oh;
301 struct abis_nm_channel *ch;
Harald Welte702d8702008-12-26 20:25:35 +0000302 u_int8_t len = sizeof(*ch) + 2;
Harald Welte8470bf22008-12-25 23:28:35 +0000303 struct msgb *msg = nm_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000304
305 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
306 fill_om_fom_hdr(oh, len, NM_MT_ESTABLISH_TEI, NM_OC_RADIO_CARRIER,
307 bts->bts_nr, trx_nr, 0xff);
308
Harald Welte8470bf22008-12-25 23:28:35 +0000309 msgb_tv_put(msg, NM_ATT_TEI, tei);
Harald Welte52b1f982008-12-23 20:25:15 +0000310
311 ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
312 fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
313
314 return abis_nm_sendmsg(bts, msg);
315}
316
317/* connect signalling of one (BTS,TRX) to a particular timeslot on the E1 */
318int abis_nm_conn_terr_sign(struct gsm_bts_trx *trx,
319 u_int8_t e1_port, u_int8_t e1_timeslot, u_int8_t e1_subslot)
320{
Harald Welte8470bf22008-12-25 23:28:35 +0000321 struct gsm_bts *bts = trx->bts;
Harald Welte52b1f982008-12-23 20:25:15 +0000322 struct abis_om_hdr *oh;
323 struct abis_nm_channel *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000324 struct msgb *msg = nm_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000325
326 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
Harald Welte05188ee2009-01-18 11:39:08 +0000327 /* FIXME: len correct? */
Harald Welte702d8702008-12-26 20:25:35 +0000328 fill_om_fom_hdr(oh, sizeof(*oh), NM_MT_CONN_TERR_SIGN,
Harald Welte52b1f982008-12-23 20:25:15 +0000329 NM_OC_RADIO_CARRIER, bts->bts_nr, trx->nr, 0xff);
330
331 ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
332 fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
333
334 return abis_nm_sendmsg(bts, msg);
335}
336
337#if 0
338int abis_nm_disc_terr_sign(struct abis_nm_h *h, struct abis_om_obj_inst *inst,
339 struct abis_nm_abis_channel *chan)
340{
341}
342#endif
343
344int abis_nm_conn_terr_traf(struct gsm_bts_trx_ts *ts,
345 u_int8_t e1_port, u_int8_t e1_timeslot,
346 u_int8_t e1_subslot)
347{
348 struct gsm_bts *bts = ts->trx->bts;
349 struct abis_om_hdr *oh;
350 struct abis_nm_channel *ch;
Harald Welte8470bf22008-12-25 23:28:35 +0000351 struct msgb *msg = nm_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000352
353 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
Harald Welte05188ee2009-01-18 11:39:08 +0000354 /* FIXME: len correct? */
Harald Welte52b1f982008-12-23 20:25:15 +0000355 fill_om_fom_hdr(oh, sizeof(*ch), NM_MT_CONN_TERR_TRAF,
356 NM_OC_BASEB_TRANSC, bts->bts_nr, ts->trx->nr, ts->nr);
357
358 ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
359 fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
360
361 return abis_nm_sendmsg(bts, msg);
362}
363
364#if 0
365int abis_nm_disc_terr_traf(struct abis_nm_h *h, struct abis_om_obj_inst *inst,
366 struct abis_nm_abis_channel *chan,
367 u_int8_t subchan)
368{
369}
370#endif
371
372int abis_nm_set_channel_attr(struct gsm_bts_trx_ts *ts, u_int8_t chan_comb)
373{
374 struct gsm_bts *bts = ts->trx->bts;
375 struct abis_om_hdr *oh;
Harald Welte8470bf22008-12-25 23:28:35 +0000376 u_int16_t arfcn = htons(ts->trx->arfcn);
Harald Welte52b1f982008-12-23 20:25:15 +0000377 u_int8_t zero = 0x00;
Harald Welte8470bf22008-12-25 23:28:35 +0000378 struct msgb *msg = nm_msgb_alloc();
Harald Welte702d8702008-12-26 20:25:35 +0000379 u_int8_t len = 4 + 2 + 2 + 2 + 2 +3;
Harald Welte52b1f982008-12-23 20:25:15 +0000380
381 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
Harald Welte702d8702008-12-26 20:25:35 +0000382 fill_om_fom_hdr(oh, len, NM_MT_SET_CHAN_ATTR,
Harald Welte52b1f982008-12-23 20:25:15 +0000383 NM_OC_BASEB_TRANSC, bts->bts_nr,
384 ts->trx->nr, ts->nr);
385 /* FIXME: don't send ARFCN list, hopping sequence, mAIO, ...*/
386 msgb_tlv16_put(msg, NM_ATT_ARFCN_LIST, 1, &arfcn);
387 msgb_tv_put(msg, NM_ATT_CHAN_COMB, chan_comb);
388 msgb_tv_put(msg, NM_ATT_HSN, 0x00);
389 msgb_tv_put(msg, NM_ATT_MAIO, 0x00);
390 msgb_tv_put(msg, NM_ATT_TSC, 0x07); /* training sequence */
391 msgb_tlv_put(msg, 0x59, 1, &zero);
392
393 return abis_nm_sendmsg(bts, msg);
394}
395
Harald Welte8470bf22008-12-25 23:28:35 +0000396int abis_nm_raw_msg(struct gsm_bts *bts, int len, u_int8_t *rawmsg)
Harald Welte52b1f982008-12-23 20:25:15 +0000397{
Harald Welte8470bf22008-12-25 23:28:35 +0000398 struct msgb *msg = nm_msgb_alloc();
399 struct abis_om_hdr *oh;
Harald Welte52b1f982008-12-23 20:25:15 +0000400 u_int8_t *data;
401
402 oh = (struct abis_om_hdr *) msgb_put(msg, sizeof(*oh));
403 fill_om_hdr(oh, len);
404 data = msgb_put(msg, len);
Harald Weltead384642008-12-26 10:20:07 +0000405 memcpy(data, rawmsg, len);
Harald Welte52b1f982008-12-23 20:25:15 +0000406
407 return abis_nm_sendmsg(bts, msg);
408}
409
410/* Siemens specific commands */
411static int __simple_cmd(struct gsm_bts *bts, u_int8_t msg_type)
412{
413 struct abis_om_hdr *oh;
Harald Welte8470bf22008-12-25 23:28:35 +0000414 struct msgb *msg = nm_msgb_alloc();
Harald Welte52b1f982008-12-23 20:25:15 +0000415
416 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
Harald Welte702d8702008-12-26 20:25:35 +0000417 fill_om_fom_hdr(oh, 0, msg_type, NM_OC_SITE_MANAGER,
Harald Welte52b1f982008-12-23 20:25:15 +0000418 0xff, 0xff, 0xff);
419
420 return abis_nm_sendmsg(bts, msg);
421}
422
423int abis_nm_event_reports(struct gsm_bts *bts, int on)
424{
425 if (on == 0)
Harald Welte227d4072009-01-03 08:16:25 +0000426 return __simple_cmd(bts, NM_MT_STOP_EVENT_REP);
Harald Welte52b1f982008-12-23 20:25:15 +0000427 else
Harald Welte227d4072009-01-03 08:16:25 +0000428 return __simple_cmd(bts, NM_MT_REST_EVENT_REP);
Harald Welte52b1f982008-12-23 20:25:15 +0000429}
430
Harald Welte47d88ae2009-01-04 12:02:08 +0000431/* Siemens (or BS-11) specific commands */
432
Harald Welte05188ee2009-01-18 11:39:08 +0000433int abis_nm_bs11_reset_resource(struct gsm_bts *bts)
Harald Welte52b1f982008-12-23 20:25:15 +0000434{
Harald Welte4668fda2009-01-03 08:19:29 +0000435 return __simple_cmd(bts, NM_MT_BS11_RESET_RESOURCE);
Harald Welte52b1f982008-12-23 20:25:15 +0000436}
437
Harald Welte05188ee2009-01-18 11:39:08 +0000438int abis_nm_bs11_db_transmission(struct gsm_bts *bts, int begin)
Harald Welte52b1f982008-12-23 20:25:15 +0000439{
440 if (begin)
Harald Welte4668fda2009-01-03 08:19:29 +0000441 return __simple_cmd(bts, NM_MT_BS11_BEGIN_DB_TX);
Harald Welte52b1f982008-12-23 20:25:15 +0000442 else
Harald Welte4668fda2009-01-03 08:19:29 +0000443 return __simple_cmd(bts, NM_MT_BS11_END_DB_TX);
Harald Welte52b1f982008-12-23 20:25:15 +0000444}
Harald Welte47d88ae2009-01-04 12:02:08 +0000445
Harald Welte05188ee2009-01-18 11:39:08 +0000446int abis_nm_bs11_create_object(struct gsm_bts *bts,
447 enum abis_bs11_objtype type, u_int8_t idx)
Harald Welte47d88ae2009-01-04 12:02:08 +0000448{
449 struct abis_om_hdr *oh;
450 struct msgb *msg = nm_msgb_alloc();
451
452 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
453 fill_om_fom_hdr(oh, 0, NM_MT_BS11_CREATE_OBJ, NM_OC_BS11,
454 type, idx, 0);
455
456 return abis_nm_sendmsg(bts, msg);
457}
458
Harald Welte05188ee2009-01-18 11:39:08 +0000459int abis_nm_bs11_create_envaBTSE(struct gsm_bts *bts, u_int8_t idx)
Harald Welte47d88ae2009-01-04 12:02:08 +0000460{
461 struct abis_om_hdr *oh;
462 struct msgb *msg = nm_msgb_alloc();
463
464 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
465 fill_om_fom_hdr(oh, 0, NM_MT_BS11_CREATE_OBJ, NM_OC_BS11_ENVABTSE,
466 0, idx, 0);
467
468 return abis_nm_sendmsg(bts, msg);
469}
470
Harald Welte05188ee2009-01-18 11:39:08 +0000471int abis_nm_bs11_create_bport(struct gsm_bts *bts, u_int8_t idx)
Harald Welte47d88ae2009-01-04 12:02:08 +0000472{
473 struct abis_om_hdr *oh;
474 struct msgb *msg = nm_msgb_alloc();
475
476 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
477 fill_om_fom_hdr(oh, 0, NM_MT_BS11_CREATE_OBJ, NM_OC_BS11_BPORT,
478 idx, 0, 0);
479
480 return abis_nm_sendmsg(bts, msg);
481}
Harald Welte05188ee2009-01-18 11:39:08 +0000482
483int abis_nm_bs11_set_oml_tei(struct gsm_bts *bts, u_int8_t tei)
484{
485 struct abis_om_hdr *oh;
486 struct msgb *msg = nm_msgb_alloc();
487 u_int8_t len = sizeof(*oh) + 2;
488
489 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
490 fill_om_fom_hdr(oh, len, NM_MT_BS11_SET_ATTR, NM_OC_SITE_MANAGER,
491 0xff, 0xff, 0xff);
492 msgb_tv_put(msg, NM_ATT_TEI, tei);
493
494 return abis_nm_sendmsg(bts, msg);
495}
496
497/* like abis_nm_conn_terr_traf */
498int abis_nm_bs11_conn_oml(struct gsm_bts *bts, u_int8_t e1_port,
499 u_int8_t e1_timeslot, u_int8_t e1_subslot)
500{
501 struct abis_om_hdr *oh;
502 struct abis_nm_channel *ch;
503 struct msgb *msg = nm_msgb_alloc();
504
505 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
506 /* FIXME: len correct? */
507 fill_om_fom_hdr(oh, sizeof(*ch), NM_MT_BS11_SET_ATTR,
508 NM_OC_SITE_MANAGER, 0xff, 0xff, 0xff);
509
510 ch = (struct abis_nm_channel *) msgb_put(msg, sizeof(*ch));
511 fill_nm_channel(ch, e1_port, e1_timeslot, e1_subslot);
512
513 return abis_nm_sendmsg(bts, msg);
514}
515
516int abis_nm_bs11_set_trx_power(struct gsm_bts_trx *trx, u_int8_t level)
517{
518 struct abis_om_hdr *oh;
519 struct msgb *msg = nm_msgb_alloc();
520 u_int8_t len = sizeof(*oh) + 3;
521
522 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
523 fill_om_fom_hdr(oh, len, NM_MT_BS11_SET_ATTR,
524 NM_OC_BS11, BS11_OBJ_PA, 0x00, trx->nr);
525 msgb_tlv_put(msg, NM_ATT_BS11_TXPWR, 1, &level);
526
527 return abis_nm_sendmsg(trx->bts, msg);
528}
529
530static const u_int8_t bs11_logon_c7[] =
531 { 0x07, 0xd9, 0x01, 0x11, 0x0d, 0x10, 0x20 };
532static const u_int8_t bs11_logon_c8[] = { 0x01, 0x02 };
533static const u_int8_t bs11_logon_c9[] = "FACTORY";
534
535int abis_nm_bs11_factory_logon(struct gsm_bts *bts)
536{
537 struct abis_om_hdr *oh;
538 struct msgb *msg = nm_msgb_alloc();
539 u_int8_t len = sizeof(*oh) + 3*2 + sizeof(bs11_logon_c7)
540 + sizeof(bs11_logon_c8) + sizeof(bs11_logon_c9);
541
542 oh = (struct abis_om_hdr *) msgb_put(msg, ABIS_OM_FOM_HDR_SIZE);
543 fill_om_fom_hdr(oh, len, NM_MT_BS11_FACTORY_LOGON,
544 NM_OC_BS11_A3, 0xff, 0xff, 0xff);
545 msgb_tlv_put(msg, 0xc7, sizeof(bs11_logon_c7), bs11_logon_c7);
546 msgb_tlv_put(msg, 0xc8, sizeof(bs11_logon_c8), bs11_logon_c8);
547 msgb_tlv_put(msg, 0xc9, sizeof(bs11_logon_c9), bs11_logon_c9);
548
549 return abis_nm_sendmsg(bts, msg);
550}