blob: af73d23aedd91384676e8ea1124ad37e8a571354 [file] [log] [blame]
Harald Welte61e42ad2009-01-18 19:10:46 +00001/* Siemens BS-11 microBTS configuration tool */
2
3/* (C) 2009 by Harald Welte <laforge@gnumonks.org>
4 * All Rights Reserved
5 *
6 * This software is based on ideas (but not code) of BS11Config
7 * (C) 2009 by Dieter Spaar <spaar@mirider.augusta.de>
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 *
23 */
24
25#include <unistd.h>
26#include <stdlib.h>
27#include <stdio.h>
28#include <errno.h>
29#include <string.h>
30#include <getopt.h>
31#include <fcntl.h>
Harald Weltef186c462009-01-29 08:45:19 +000032#include <termios.h>
Harald Welte14f09342009-01-29 19:28:38 +000033#include <signal.h>
Harald Welte61e42ad2009-01-18 19:10:46 +000034
35#include <sys/types.h>
36#include <sys/stat.h>
37
38#include <openbsc/gsm_data.h>
39#include <openbsc/abis_nm.h>
40#include <openbsc/msgb.h>
41#include <openbsc/tlv.h>
42#include <openbsc/debug.h>
Harald Welte14f09342009-01-29 19:28:38 +000043#include <openbsc/select.h>
Harald Welte61e42ad2009-01-18 19:10:46 +000044
Harald Welte3b8ba212009-01-29 12:27:58 +000045/* state of our bs11_config application */
46enum bs11cfg_state {
47 STATE_NONE,
48 STATE_LOGON_WAIT,
49 STATE_LOGON_ACK,
50 STATE_SWLOAD,
51};
52static enum bs11cfg_state bs11cfg_state = STATE_NONE;
53
Harald Welte61e42ad2009-01-18 19:10:46 +000054static const u_int8_t obj_li_attr[] = {
Harald Welte5e4d1b32009-02-01 13:36:56 +000055 NM_ATT_BS11_BIT_ERR_THESH, 0x09, 0x00,
56 NM_ATT_BS11_L1_PROT_TYPE, 0x00,
57 NM_ATT_BS11_LINE_CFG, 0x00,
Harald Welte61e42ad2009-01-18 19:10:46 +000058};
59static const u_int8_t obj_bbsig0_attr[] = {
Harald Welte5e4d1b32009-02-01 13:36:56 +000060 NM_ATT_BS11_RSSI_OFFS, 0x02, 0x00, 0x00,
61 NM_ATT_BS11_DIVERSITY, 0x01, 0x00,
Harald Welte61e42ad2009-01-18 19:10:46 +000062};
63static const u_int8_t obj_pa0_attr[] = {
Harald Welte5e4d1b32009-02-01 13:36:56 +000064 NM_ATT_BS11_TXPWR, 0x01, BS11_TRX_POWER_GSM_30mW,
Harald Welte61e42ad2009-01-18 19:10:46 +000065};
66static const char *trx1_password = "1111111111";
67#define TEI_OML 25
68
Harald Welte3b8ba212009-01-29 12:27:58 +000069static const u_int8_t too_fast[] = { 0x12, 0x80, 0x00, 0x00, 0x02, 0x02 };
70
Harald Welte14f09342009-01-29 19:28:38 +000071struct serial_handle {
72 struct bsc_fd fd;
73 struct llist_head tx_queue;
74
75 struct msgb *rx_msg;
76 unsigned int rxmsg_bytes_missing;
77};
78
79/* FIXME: this needs to go */
80static struct serial_handle _ser_handle, *ser_handle = &_ser_handle;
81
82static int handle_serial_msg(struct msgb *rx_msg);
83
Harald Welte268bb402009-02-01 19:11:56 +000084static int create_trx1_objects(struct gsm_bts *bts)
85{
86 u_int8_t bbsig1_attr[sizeof(obj_bbsig0_attr)+12];
87 u_int8_t *cur = bbsig1_attr;
88
89 abis_nm_bs11_set_trx1_pw(bts, trx1_password);
90
91 cur = tlv_put(cur, NM_ATT_BS11_PASSWORD, 10,
92 (u_int8_t *)trx1_password);
93 memcpy(cur, obj_bbsig0_attr, sizeof(obj_bbsig0_attr));
94 abis_nm_bs11_create_object(bts, BS11_OBJ_BBSIG, 1,
95 sizeof(bbsig1_attr), bbsig1_attr);
96
97 abis_nm_bs11_create_object(bts, BS11_OBJ_PA, 1,
98 sizeof(obj_pa0_attr), obj_pa0_attr);
99
100 abis_nm_bs11_set_trx_power(&bts->trx[1], BS11_TRX_POWER_GSM_30mW);
101
102 return 0;
103}
104
Harald Welte61e42ad2009-01-18 19:10:46 +0000105/* create all objects for an initial configuration */
106static int create_objects(struct gsm_bts *bts, int trx1)
107{
Harald Welte5e4d1b32009-02-01 13:36:56 +0000108 //abis_nm_bs11_factory_logon(bts, 1);
Harald Welte61e42ad2009-01-18 19:10:46 +0000109 abis_nm_bs11_create_object(bts, BS11_OBJ_LI, 0, sizeof(obj_li_attr),
110 obj_li_attr);
111 abis_nm_bs11_create_object(bts, BS11_OBJ_GPSU, 0, 0, NULL);
112 abis_nm_bs11_create_object(bts, BS11_OBJ_ALCO, 0, 0, NULL);
Harald Welte623d5312009-01-29 21:14:05 +0000113 abis_nm_bs11_create_object(bts, BS11_OBJ_CCLK, 0, 0, NULL);
Harald Welte61e42ad2009-01-18 19:10:46 +0000114 abis_nm_bs11_create_object(bts, BS11_OBJ_BBSIG, 0,
115 sizeof(obj_bbsig0_attr), obj_bbsig0_attr);
116 abis_nm_bs11_create_object(bts, BS11_OBJ_PA, 0,
117 sizeof(obj_pa0_attr), obj_pa0_attr);
Harald Welte61e42ad2009-01-18 19:10:46 +0000118 abis_nm_bs11_create_envaBTSE(bts, 0);
119 abis_nm_bs11_create_envaBTSE(bts, 1);
120 abis_nm_bs11_create_envaBTSE(bts, 2);
121 abis_nm_bs11_create_envaBTSE(bts, 3);
122
123 abis_nm_bs11_conn_oml(bts, 0, 1, 0xff);
124 abis_nm_bs11_set_oml_tei(bts, TEI_OML);
125
Harald Welte5e4d1b32009-02-01 13:36:56 +0000126 abis_nm_bs11_set_trx_power(&bts->trx[0], BS11_TRX_POWER_GSM_30mW);
Harald Welte5e4d1b32009-02-01 13:36:56 +0000127 //abis_nm_bs11_factory_logon(bts, 0);
Harald Welte61e42ad2009-01-18 19:10:46 +0000128
129 return 0;
130}
131
132static char *serial_port = "/dev/ttyUSB0";
133static char *fname_safety = "BTSBMC76.SWI";
134static char *fname_software = "HS011106.SWL";
Harald Welte623d5312009-01-29 21:14:05 +0000135static int delay_ms = 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000136static int serial_fd = -1;
137static int have_trx1 = 0;
Harald Welte623d5312009-01-29 21:14:05 +0000138static int win_size = 8;
Harald Welte61e42ad2009-01-18 19:10:46 +0000139static struct gsm_bts *g_bts;
140
141/* adaption layer from GSM 08.59 + 12.21 to RS232 */
142
143#define LAPD_HDR_LEN 10
144
145/* callback from abis_nm */
146int _abis_nm_sendmsg(struct msgb *msg)
147{
Harald Welte14f09342009-01-29 19:28:38 +0000148 struct serial_handle *sh = ser_handle;
Harald Welte61e42ad2009-01-18 19:10:46 +0000149 u_int8_t *lapd;
Harald Welte14f09342009-01-29 19:28:38 +0000150 unsigned int len;
Harald Welte61e42ad2009-01-18 19:10:46 +0000151
152 msg->l2h = msg->data;
153
154 /* prepend LAPD header */
155 lapd = msgb_push(msg, LAPD_HDR_LEN);
156
Harald Welte14f09342009-01-29 19:28:38 +0000157 len = msg->len - 2;
158
159 lapd[0] = (len >> 8) & 0xff;
160 lapd[1] = len & 0xff; /* length of bytes startign at lapd[2] */
Harald Welte61e42ad2009-01-18 19:10:46 +0000161 lapd[2] = 0x00;
162 lapd[3] = 0x07;
163 lapd[4] = 0x01;
164 lapd[5] = 0x3e;
165 lapd[6] = 0x00;
166 lapd[7] = 0x00;
167 lapd[8] = msg->len - 10; /* length of bytes starting at lapd[10] */
168 lapd[9] = lapd[8] ^ 0x38;
169
Harald Welte14f09342009-01-29 19:28:38 +0000170 msgb_enqueue(&sh->tx_queue, msg);
171 sh->fd.when |= BSC_FD_WRITE;
172
173 return 0;
174}
175
Harald Welte5e4d1b32009-02-01 13:36:56 +0000176/* select.c callback in case we can write to the RS232 */
Harald Welte14f09342009-01-29 19:28:38 +0000177static int handle_ser_write(struct bsc_fd *bfd)
178{
179 struct serial_handle *sh = bfd->data;
180 struct msgb *msg;
181 int written;
182
183 msg = msgb_dequeue(&sh->tx_queue);
184 if (!msg) {
185 bfd->when &= ~BSC_FD_WRITE;
186 return 0;
187 }
188
Harald Welte61e42ad2009-01-18 19:10:46 +0000189 fprintf(stdout, "TX: ");
190 hexdump(msg->data, msg->len);
191
192 /* send over serial line */
193 written = write(serial_fd, msg->data, msg->len);
194 if (written < msg->len) {
195 perror("short write:");
196 msgb_free(msg);
197 return -1;
198 }
199
200 msgb_free(msg);
Harald Welte3b8ba212009-01-29 12:27:58 +0000201 usleep(delay_ms*1000);
Harald Welte61e42ad2009-01-18 19:10:46 +0000202
203 return 0;
204}
205
206#define SERIAL_ALLOC_SIZE 300
207
Harald Welte5e4d1b32009-02-01 13:36:56 +0000208/* select.c callback in case we can read from the RS232 */
Harald Welte14f09342009-01-29 19:28:38 +0000209static int handle_ser_read(struct bsc_fd *bfd)
Harald Welte61e42ad2009-01-18 19:10:46 +0000210{
Harald Welte14f09342009-01-29 19:28:38 +0000211 struct serial_handle *sh = bfd->data;
212 struct msgb *msg;
213 int rc = 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000214
Harald Welte14f09342009-01-29 19:28:38 +0000215 if (!sh->rx_msg) {
216 sh->rx_msg = msgb_alloc(SERIAL_ALLOC_SIZE);
217 sh->rx_msg->l2h = NULL;
218 }
219 msg = sh->rx_msg;
Harald Welte3b8ba212009-01-29 12:27:58 +0000220
Harald Welte61e42ad2009-01-18 19:10:46 +0000221 /* first read two byes to obtain length */
Harald Welte14f09342009-01-29 19:28:38 +0000222 if (msg->len < 2) {
223 rc = read(sh->fd.fd, msg->tail, 2 - msg->len);
Harald Welte61e42ad2009-01-18 19:10:46 +0000224 if (rc < 0) {
Harald Welte14f09342009-01-29 19:28:38 +0000225 perror("ERROR reading from serial port");
Harald Welte61e42ad2009-01-18 19:10:46 +0000226 msgb_free(msg);
Harald Welte14f09342009-01-29 19:28:38 +0000227 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000228 }
229 msgb_put(msg, rc);
Harald Welte61e42ad2009-01-18 19:10:46 +0000230
Harald Welte14f09342009-01-29 19:28:38 +0000231 if (msg->len >= 2) {
232 /* parse LAPD payload length */
233 if (msg->data[0] != 0)
234 fprintf(stderr, "Suspicious header byte 0: 0x%02x\n",
235 msg->data[0]);
Harald Welte61e42ad2009-01-18 19:10:46 +0000236
Harald Welte14f09342009-01-29 19:28:38 +0000237 sh->rxmsg_bytes_missing = msg->data[0] << 8;
238 sh->rxmsg_bytes_missing += msg->data[1];
239
240 if (sh->rxmsg_bytes_missing < LAPD_HDR_LEN -2)
241 fprintf(stderr, "Invalid length in hdr: %u\n",
242 sh->rxmsg_bytes_missing);
243 }
244 } else {
245 /* try to read as many of the missing bytes as are available */
246 rc = read(sh->fd.fd, msg->tail, sh->rxmsg_bytes_missing);
Harald Welte61e42ad2009-01-18 19:10:46 +0000247 if (rc < 0) {
Harald Welte14f09342009-01-29 19:28:38 +0000248 perror("ERROR reading from serial port");
Harald Welte61e42ad2009-01-18 19:10:46 +0000249 msgb_free(msg);
Harald Welte14f09342009-01-29 19:28:38 +0000250 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000251 }
252 msgb_put(msg, rc);
Harald Welte14f09342009-01-29 19:28:38 +0000253 sh->rxmsg_bytes_missing -= rc;
254
255 if (sh->rxmsg_bytes_missing == 0) {
256 /* we have one complete message now */
257 sh->rx_msg = NULL;
258
259 if (msg->len > LAPD_HDR_LEN)
260 msg->l2h = msg->data + LAPD_HDR_LEN;
261
262 fprintf(stdout, "RX: ");
263 hexdump(msg->data, msg->len);
264 rc = handle_serial_msg(msg);
265 }
Harald Welte61e42ad2009-01-18 19:10:46 +0000266 }
267
Harald Welte14f09342009-01-29 19:28:38 +0000268 return rc;
269}
Harald Welte61e42ad2009-01-18 19:10:46 +0000270
Harald Welte5e4d1b32009-02-01 13:36:56 +0000271/* select.c callback */
Harald Welte14f09342009-01-29 19:28:38 +0000272static int serial_fd_cb(struct bsc_fd *bfd, unsigned int what)
273{
274 int rc = 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000275
Harald Welte14f09342009-01-29 19:28:38 +0000276 if (what & BSC_FD_READ)
277 rc = handle_ser_read(bfd);
278
279 if (rc < 0)
280 return rc;
281
282 if (what & BSC_FD_WRITE)
283 rc = handle_ser_write(bfd);
284
285 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000286}
287
288static int file_is_readable(const char *fname)
289{
290 int rc;
291 struct stat st;
292
293 rc = stat(fname, &st);
294 if (rc < 0)
295 return 0;
296
297 if (S_ISREG(st.st_mode) && (st.st_mode & S_IRUSR))
298 return 1;
299
300 return 0;
301}
302
Harald Welte5e4d1b32009-02-01 13:36:56 +0000303/* callback function passed to the ABIS OML code */
304static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
305 void *data, void *param)
306{
307 if (hook != GSM_HOOK_NM_SWLOAD)
308 return 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000309
Harald Welte5e4d1b32009-02-01 13:36:56 +0000310 switch (event) {
311 case NM_MT_LOAD_INIT_ACK:
312 fprintf(stdout, "Software Load Initiate ACK\n");
313 break;
314 case NM_MT_LOAD_INIT_NACK:
315 fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
316 exit(5);
317 break;
318 case NM_MT_LOAD_END_ACK:
319 /* FIXME: activate in case we want to */
320 if (data)
321 abis_nm_software_activate(g_bts, fname_safety,
322 swload_cbfn, g_bts);
323 break;
324 case NM_MT_LOAD_END_NACK:
325 fprintf(stderr, "ERROR: Software Load End NACK\n");
326 exit(3);
327 break;
328 case NM_MT_ACTIVATE_SW_NACK:
329 fprintf(stderr, "ERROR: Activate Software NACK\n");
330 exit(4);
331 break;
332 case NM_MT_ACTIVATE_SW_ACK:
333 bs11cfg_state = STATE_NONE;
334
335 break;
336 }
337 return 0;
338}
339
Harald Welte268bb402009-02-01 19:11:56 +0000340static const char *bs11_link_state[] = {
341 [0x00] = "Down",
342 [0x01] = "Up",
343 [0x02] = "Restoring",
344};
345
346static const char *linkstate_name(u_int8_t linkstate)
Harald Welte61e42ad2009-01-18 19:10:46 +0000347{
Harald Welte268bb402009-02-01 19:11:56 +0000348 if (linkstate > ARRAY_SIZE(bs11_link_state))
349 return "Unknown";
Harald Welte3b8ba212009-01-29 12:27:58 +0000350
Harald Welte268bb402009-02-01 19:11:56 +0000351 return bs11_link_state[linkstate];
352}
Harald Welte3b8ba212009-01-29 12:27:58 +0000353
Harald Welte268bb402009-02-01 19:11:56 +0000354static const char *mbccu_load[] = {
355 [0] = "No Load",
356 [1] = "Load BTSCAC",
357 [2] = "Load BTSDRX",
358 [3] = "Load BTSBBX",
359 [4] = "Load BTSARC",
360 [5] = "Load",
361};
362
363static const char *mbccu_load_name(u_int8_t linkstate)
364{
365 if (linkstate > ARRAY_SIZE(mbccu_load))
366 return "Unknown";
367
368 return mbccu_load[linkstate];
369}
370
371
372static void print_state(struct abis_nm_bs11_state *st)
373{
374 enum abis_bs11_phase phase = st->phase;
375
376 printf("T-Link: %-9s Abis-link: %-9s MBCCU0: %-11s MBCCU1: %-11s PHASE: %u SUBPHASE: ",
377 linkstate_name(st->t_link), linkstate_name(st->abis_link),
378 mbccu_load_name(st->mbccu >> 4), mbccu_load_name(st->mbccu & 0xf),
379 phase & 0xf);
380
381 switch (phase) {
Harald Welte61e42ad2009-01-18 19:10:46 +0000382 case BS11_STATE_WARM_UP:
383 printf("Warm Up...\n");
Harald Welte61e42ad2009-01-18 19:10:46 +0000384 break;
385 case BS11_STATE_LOAD_SMU_SAFETY:
386 printf("Load SMU Safety...\n");
Harald Welte268bb402009-02-01 19:11:56 +0000387 break;
388 case BS11_STATE_LOAD_SMU_INTENDED:
389 printf("Load SMU Intended...\n");
390 break;
391 case BS11_STATE_LOAD_MBCCU:
392 printf("Load MBCCU...\n");
Harald Welte61e42ad2009-01-18 19:10:46 +0000393 break;
394 case BS11_STATE_SOFTWARE_RQD:
395 printf("Software required...\n");
Harald Welte268bb402009-02-01 19:11:56 +0000396 break;
397 case BS11_STATE_WAIT_MIN_CFG:
398 case BS11_STATE_WAIT_MIN_CFG_2:
399 printf("Wait minimal config...\n");
400 break;
401 case BS11_STATE_MAINTENANCE:
402 printf("Maintenance...\n");
403 break;
404 case BS11_STATE_NORMAL:
405 printf("Normal...\n");
406 break;
407 default:
408 printf("Unknown phase 0x%02x\n", phase);
409 break;
410 }
411}
412
413/* handle a response from the BTS to a GET STATE command */
414static int handle_state_resp(enum abis_bs11_phase state)
415{
416 int rc = 0;
417
418 printf("PHASE: %u STATE: ", state & 0xf);
419
420 switch (state) {
421 case BS11_STATE_WARM_UP:
422 sleep(5);
423 break;
424 case BS11_STATE_LOAD_SMU_SAFETY:
425 sleep(5);
426 break;
427 case BS11_STATE_LOAD_SMU_INTENDED:
428 sleep(5);
429 break;
430 case BS11_STATE_LOAD_MBCCU:
431 break;
432 case BS11_STATE_SOFTWARE_RQD:
Harald Welte3b8ba212009-01-29 12:27:58 +0000433 bs11cfg_state = STATE_SWLOAD;
Harald Welte5e4d1b32009-02-01 13:36:56 +0000434 /* send safety load. Use g_bts as private 'param'
435 * argument, so our swload_cbfn can distinguish
436 * a safety load from a regular software */
Harald Welte61e42ad2009-01-18 19:10:46 +0000437 if (file_is_readable(fname_safety))
Harald Welte623d5312009-01-29 21:14:05 +0000438 rc = abis_nm_software_load(g_bts, fname_safety,
Harald Welte5e4d1b32009-02-01 13:36:56 +0000439 win_size, swload_cbfn,
440 g_bts);
Harald Welte61e42ad2009-01-18 19:10:46 +0000441 else
Harald Welte071f34d2009-01-29 09:24:38 +0000442 fprintf(stderr, "No valid Safety Load file \"%s\"\n",
443 fname_safety);
Harald Welte61e42ad2009-01-18 19:10:46 +0000444 break;
445 case BS11_STATE_WAIT_MIN_CFG:
446 case BS11_STATE_WAIT_MIN_CFG_2:
Harald Welte3b8ba212009-01-29 12:27:58 +0000447 bs11cfg_state = STATE_SWLOAD;
448 rc = create_objects(g_bts, have_trx1);
Harald Welte61e42ad2009-01-18 19:10:46 +0000449 break;
450 case BS11_STATE_MAINTENANCE:
Harald Welte3b8ba212009-01-29 12:27:58 +0000451 bs11cfg_state = STATE_SWLOAD;
Harald Welte61e42ad2009-01-18 19:10:46 +0000452 /* send software (FIXME: over A-bis?) */
453 if (file_is_readable(fname_software))
Harald Welte5e4d1b32009-02-01 13:36:56 +0000454 rc = abis_nm_bs11_load_swl(g_bts, fname_software,
455 win_size, swload_cbfn);
Harald Welte61e42ad2009-01-18 19:10:46 +0000456 else
Harald Welte071f34d2009-01-29 09:24:38 +0000457 fprintf(stderr, "No valid Software file \"%s\"\n",
458 fname_software);
Harald Welte61e42ad2009-01-18 19:10:46 +0000459 break;
460 case BS11_STATE_NORMAL:
Harald Welte268bb402009-02-01 19:11:56 +0000461 if (have_trx1)
462 create_trx1_objects(g_bts);
Harald Welte61e42ad2009-01-18 19:10:46 +0000463 return 1;
464 default:
Harald Welte61e42ad2009-01-18 19:10:46 +0000465 sleep(5);
466 break;
467 }
Harald Welte3b8ba212009-01-29 12:27:58 +0000468 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000469}
470
Harald Welte5e4d1b32009-02-01 13:36:56 +0000471/* handle a fully-received message/packet from the RS232 port */
Harald Welte14f09342009-01-29 19:28:38 +0000472static int handle_serial_msg(struct msgb *rx_msg)
473{
474 struct abis_om_hdr *oh;
475 struct abis_om_fom_hdr *foh;
Harald Welte268bb402009-02-01 19:11:56 +0000476 struct abis_nm_bs11_state *st;
Harald Welte14f09342009-01-29 19:28:38 +0000477 int rc = -1;
478
479 if (rx_msg->len < LAPD_HDR_LEN
480 + sizeof(struct abis_om_fom_hdr)
481 + sizeof(struct abis_om_hdr)) {
482 if (!memcmp(rx_msg->data + 2, too_fast,
483 sizeof(too_fast))) {
484 fprintf(stderr, "BS11 tells us we're too "
485 "fast, try --delay bigger than %u\n",
486 delay_ms);
487 return -E2BIG;
488 } else
489 fprintf(stderr, "unknown BS11 message\n");
490 }
491
492 oh = (struct abis_om_hdr *) msgb_l2(rx_msg);
493 foh = (struct abis_om_fom_hdr *) oh->data;
494 switch (foh->msg_type) {
Harald Welte043d04a2009-01-29 23:15:30 +0000495 case NM_MT_BS11_LMT_LOGON_ACK:
496 printf("LMT LOGON: ACK\n");
Harald Welte14f09342009-01-29 19:28:38 +0000497 if (bs11cfg_state == STATE_NONE)
498 bs11cfg_state = STATE_LOGON_ACK;
499 rc = 0;
500 break;
Harald Welte5e4d1b32009-02-01 13:36:56 +0000501 case NM_MT_BS11_LMT_LOGOFF_ACK:
502 exit(0);
503 break;
Harald Welte14f09342009-01-29 19:28:38 +0000504 case NM_MT_BS11_GET_STATE_ACK:
Harald Welte268bb402009-02-01 19:11:56 +0000505 st = (struct abis_nm_bs11_state *) &foh->data[0];
506 print_state(st);
507 rc = handle_state_resp(st->phase);
Harald Welte14f09342009-01-29 19:28:38 +0000508 break;
509 default:
510 rc = abis_nm_rcvmsg(rx_msg);
511 }
512 if (rc < 0) {
513 perror("ERROR in main loop");
514 //break;
515 }
516 if (rc == 1)
517 return rc;
518
519 switch (bs11cfg_state) {
520 case STATE_NONE:
521 abis_nm_bs11_factory_logon(g_bts, 1);
522 break;
523 case STATE_LOGON_ACK:
524 abis_nm_bs11_get_state(g_bts);
525 break;
526 default:
527 break;
528 }
529
530 return rc;
531}
532
Harald Welte61e42ad2009-01-18 19:10:46 +0000533static void print_banner(void)
534{
535 printf("bs11_config (C) 2009 by Harald Welte and Dieter Spaar\n");
Harald Welte5e4d1b32009-02-01 13:36:56 +0000536 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
Harald Welte61e42ad2009-01-18 19:10:46 +0000537}
538
539static void print_help(void)
540{
541 printf("Supported arguments:\n");
Harald Welte5e4d1b32009-02-01 13:36:56 +0000542 printf("\t-h --help\t\t\tPrint this help text\n");
543 printf("\t-p --port </dev/ttyXXX>\t\tSpecify serial port\n");
544 printf("\t-t --with-trx1\t\t\tAssume the BS-11 has 2 TRX\n");
545 printf("\t-s --software <file>\t\tSpecify Software file\n");
546 printf("\t-S --safety <file>\t\tSpecify Safety Load file\n");
547 printf("\t-d --delay <file>\t\tSpecify delay\n");
548 printf("\t-w --win-size <num>\t\tSpecify Window Size\n");
Harald Welte61e42ad2009-01-18 19:10:46 +0000549}
550
551static void handle_options(int argc, char **argv)
552{
553 print_banner();
554
555 while (1) {
556 int option_index = 0, c;
557 static struct option long_options[] = {
558 { "help", 0, 0, 'h' },
559 { "port", 1, 0, 'p' },
560 { "with-trx1", 0, 0, 't' },
561 { "software", 1, 0, 's' },
562 { "safety", 1, 0, 'S' },
Harald Welte3b8ba212009-01-29 12:27:58 +0000563 { "delay", 1, 0, 'd' },
Harald Welte623d5312009-01-29 21:14:05 +0000564 { "win-size", 1, 0, 'w' },
Harald Welte61e42ad2009-01-18 19:10:46 +0000565 };
566
Harald Welte623d5312009-01-29 21:14:05 +0000567 c = getopt_long(argc, argv, "hp:s:S:td:w:",
Harald Welte61e42ad2009-01-18 19:10:46 +0000568 long_options, &option_index);
569
570 if (c == -1)
571 break;
572
573 switch (c) {
574 case 'h':
575 print_help();
576 exit(0);
577 case 'p':
578 serial_port = optarg;
579 break;
580 case 't':
581 have_trx1 = 1;
582 break;
583 case 's':
584 fname_software = optarg;
585 break;
586 case 'S':
587 fname_safety = optarg;
588 break;
Harald Welte3b8ba212009-01-29 12:27:58 +0000589 case 'd':
590 delay_ms = atoi(optarg);
591 break;
Harald Welte623d5312009-01-29 21:14:05 +0000592 case 'w':
593 win_size = atoi(optarg);
594 break;
Harald Welte61e42ad2009-01-18 19:10:46 +0000595 default:
596 break;
597 }
598 }
599}
600
Harald Welte14f09342009-01-29 19:28:38 +0000601static void signal_handler(int signal)
602{
603 fprintf(stdout, "signal %u received\n", signal);
604
605 switch (signal) {
Harald Welte5e4d1b32009-02-01 13:36:56 +0000606 case SIGINT:
Harald Welte14f09342009-01-29 19:28:38 +0000607 abis_nm_bs11_factory_logon(g_bts, 0);
608 break;
609 }
610}
611
Harald Welte61e42ad2009-01-18 19:10:46 +0000612int main(int argc, char **argv)
613{
614 struct gsm_network *gsmnet;
Harald Weltef186c462009-01-29 08:45:19 +0000615 struct termios tio;
616 int rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000617
618 handle_options(argc, argv);
619
620 serial_fd = open(serial_port, O_RDWR);
621 if (serial_fd < 0) {
622 perror("cannot open serial port:");
623 exit(1);
624 }
625
Harald Weltef186c462009-01-29 08:45:19 +0000626 /* set baudrate */
627 rc = tcgetattr(serial_fd, &tio);
628 if (rc < 0) {
629 perror("tcgetattr()");
630 exit(1);
631 }
632 cfsetispeed(&tio, B19200);
633 cfsetospeed(&tio, B19200);
Harald Welte071f34d2009-01-29 09:24:38 +0000634 tio.c_cflag |= (CREAD | CLOCAL | CS8);
635 tio.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
636 tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
637 tio.c_iflag |= (INPCK | ISTRIP);
638 tio.c_iflag &= ~(ISTRIP | IXON | IXOFF | IGNBRK | INLCR | ICRNL | IGNCR);
Harald Welte623d5312009-01-29 21:14:05 +0000639 tio.c_oflag &= ~(OPOST);
Harald Weltef186c462009-01-29 08:45:19 +0000640 rc = tcsetattr(serial_fd, TCSADRAIN, &tio);
641 if (rc < 0) {
642 perror("tcsetattr()");
643 exit(1);
644 }
Harald Welte61e42ad2009-01-18 19:10:46 +0000645
646 gsmnet = gsm_network_init(1, 1, 1);
647 if (!gsmnet) {
648 fprintf(stderr, "Unable to allocate gsm network\n");
649 exit(1);
650 }
651 g_bts = &gsmnet->bts[0];
652
Harald Welte14f09342009-01-29 19:28:38 +0000653 INIT_LLIST_HEAD(&ser_handle->tx_queue);
654 ser_handle->fd.fd = serial_fd;
655 ser_handle->fd.when = BSC_FD_READ;
656 ser_handle->fd.cb = serial_fd_cb;
657 ser_handle->fd.data = ser_handle;
658 rc = bsc_register_fd(&ser_handle->fd);
659 if (rc < 0) {
660 fprintf(stderr, "could not register FD: %s\n",
661 strerror(rc));
662 exit(1);
663 }
664
Harald Welte5e4d1b32009-02-01 13:36:56 +0000665 signal(SIGINT, &signal_handler);
Harald Welte14f09342009-01-29 19:28:38 +0000666
Harald Welte61e42ad2009-01-18 19:10:46 +0000667 abis_nm_bs11_factory_logon(g_bts, 1);
Harald Welte5e4d1b32009-02-01 13:36:56 +0000668 //abis_nm_bs11_get_serno(g_bts);
Harald Welte61e42ad2009-01-18 19:10:46 +0000669
670 while (1) {
Harald Welte14f09342009-01-29 19:28:38 +0000671 bsc_select_main();
Harald Welte61e42ad2009-01-18 19:10:46 +0000672 }
673
674 abis_nm_bs11_factory_logon(g_bts, 0);
675
676 close(serial_fd);
677 exit(0);
678}