blob: 6166c841425bd795cd7f6265c9a498c1a73d06cd [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 Welte61e42ad2009-01-18 19:10:46 +000084/* create all objects for an initial configuration */
85static int create_objects(struct gsm_bts *bts, int trx1)
86{
Harald Welte5e4d1b32009-02-01 13:36:56 +000087 //abis_nm_bs11_factory_logon(bts, 1);
Harald Welte61e42ad2009-01-18 19:10:46 +000088 abis_nm_bs11_create_object(bts, BS11_OBJ_LI, 0, sizeof(obj_li_attr),
89 obj_li_attr);
90 abis_nm_bs11_create_object(bts, BS11_OBJ_GPSU, 0, 0, NULL);
91 abis_nm_bs11_create_object(bts, BS11_OBJ_ALCO, 0, 0, NULL);
Harald Welte623d5312009-01-29 21:14:05 +000092 abis_nm_bs11_create_object(bts, BS11_OBJ_CCLK, 0, 0, NULL);
Harald Welte61e42ad2009-01-18 19:10:46 +000093 abis_nm_bs11_create_object(bts, BS11_OBJ_BBSIG, 0,
94 sizeof(obj_bbsig0_attr), obj_bbsig0_attr);
95 abis_nm_bs11_create_object(bts, BS11_OBJ_PA, 0,
96 sizeof(obj_pa0_attr), obj_pa0_attr);
97 if (trx1) {
98 u_int8_t bbsig1_attr[sizeof(obj_bbsig0_attr)+12];
99 u_int8_t *cur = bbsig1_attr;
100
101 abis_nm_bs11_set_trx1_pw(bts, trx1_password);
102
103 cur = tlv_put(cur, NM_ATT_BS11_PASSWORD, 10,
104 (u_int8_t *)trx1_password);
105 memcpy(cur, obj_bbsig0_attr, sizeof(obj_bbsig0_attr));
106 abis_nm_bs11_create_object(bts, BS11_OBJ_BBSIG, 1,
107 sizeof(bbsig1_attr), bbsig1_attr);
108
109 abis_nm_bs11_create_object(bts, BS11_OBJ_PA, 1,
110 sizeof(obj_pa0_attr), obj_pa0_attr);
111 }
112
113 abis_nm_bs11_create_envaBTSE(bts, 0);
114 abis_nm_bs11_create_envaBTSE(bts, 1);
115 abis_nm_bs11_create_envaBTSE(bts, 2);
116 abis_nm_bs11_create_envaBTSE(bts, 3);
117
118 abis_nm_bs11_conn_oml(bts, 0, 1, 0xff);
119 abis_nm_bs11_set_oml_tei(bts, TEI_OML);
120
Harald Welte5e4d1b32009-02-01 13:36:56 +0000121 abis_nm_bs11_set_trx_power(&bts->trx[0], BS11_TRX_POWER_GSM_30mW);
Harald Welte61e42ad2009-01-18 19:10:46 +0000122
123 if (trx1)
Harald Welte5e4d1b32009-02-01 13:36:56 +0000124 abis_nm_bs11_set_trx_power(&bts->trx[1], BS11_TRX_POWER_GSM_30mW);
Harald Welte61e42ad2009-01-18 19:10:46 +0000125
Harald Welte5e4d1b32009-02-01 13:36:56 +0000126 //abis_nm_bs11_factory_logon(bts, 0);
Harald Welte61e42ad2009-01-18 19:10:46 +0000127
128 return 0;
129}
130
131static char *serial_port = "/dev/ttyUSB0";
132static char *fname_safety = "BTSBMC76.SWI";
133static char *fname_software = "HS011106.SWL";
Harald Welte623d5312009-01-29 21:14:05 +0000134static int delay_ms = 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000135static int serial_fd = -1;
136static int have_trx1 = 0;
Harald Welte623d5312009-01-29 21:14:05 +0000137static int win_size = 8;
Harald Welte61e42ad2009-01-18 19:10:46 +0000138static struct gsm_bts *g_bts;
139
140/* adaption layer from GSM 08.59 + 12.21 to RS232 */
141
142#define LAPD_HDR_LEN 10
143
144/* callback from abis_nm */
145int _abis_nm_sendmsg(struct msgb *msg)
146{
Harald Welte14f09342009-01-29 19:28:38 +0000147 struct serial_handle *sh = ser_handle;
Harald Welte61e42ad2009-01-18 19:10:46 +0000148 u_int8_t *lapd;
Harald Welte14f09342009-01-29 19:28:38 +0000149 unsigned int len;
Harald Welte61e42ad2009-01-18 19:10:46 +0000150
151 msg->l2h = msg->data;
152
153 /* prepend LAPD header */
154 lapd = msgb_push(msg, LAPD_HDR_LEN);
155
Harald Welte14f09342009-01-29 19:28:38 +0000156 len = msg->len - 2;
157
158 lapd[0] = (len >> 8) & 0xff;
159 lapd[1] = len & 0xff; /* length of bytes startign at lapd[2] */
Harald Welte61e42ad2009-01-18 19:10:46 +0000160 lapd[2] = 0x00;
161 lapd[3] = 0x07;
162 lapd[4] = 0x01;
163 lapd[5] = 0x3e;
164 lapd[6] = 0x00;
165 lapd[7] = 0x00;
166 lapd[8] = msg->len - 10; /* length of bytes starting at lapd[10] */
167 lapd[9] = lapd[8] ^ 0x38;
168
Harald Welte14f09342009-01-29 19:28:38 +0000169 msgb_enqueue(&sh->tx_queue, msg);
170 sh->fd.when |= BSC_FD_WRITE;
171
172 return 0;
173}
174
Harald Welte5e4d1b32009-02-01 13:36:56 +0000175/* select.c callback in case we can write to the RS232 */
Harald Welte14f09342009-01-29 19:28:38 +0000176static int handle_ser_write(struct bsc_fd *bfd)
177{
178 struct serial_handle *sh = bfd->data;
179 struct msgb *msg;
180 int written;
181
182 msg = msgb_dequeue(&sh->tx_queue);
183 if (!msg) {
184 bfd->when &= ~BSC_FD_WRITE;
185 return 0;
186 }
187
Harald Welte61e42ad2009-01-18 19:10:46 +0000188 fprintf(stdout, "TX: ");
189 hexdump(msg->data, msg->len);
190
191 /* send over serial line */
192 written = write(serial_fd, msg->data, msg->len);
193 if (written < msg->len) {
194 perror("short write:");
195 msgb_free(msg);
196 return -1;
197 }
198
199 msgb_free(msg);
Harald Welte3b8ba212009-01-29 12:27:58 +0000200 usleep(delay_ms*1000);
Harald Welte61e42ad2009-01-18 19:10:46 +0000201
202 return 0;
203}
204
205#define SERIAL_ALLOC_SIZE 300
206
Harald Welte5e4d1b32009-02-01 13:36:56 +0000207/* select.c callback in case we can read from the RS232 */
Harald Welte14f09342009-01-29 19:28:38 +0000208static int handle_ser_read(struct bsc_fd *bfd)
Harald Welte61e42ad2009-01-18 19:10:46 +0000209{
Harald Welte14f09342009-01-29 19:28:38 +0000210 struct serial_handle *sh = bfd->data;
211 struct msgb *msg;
212 int rc = 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000213
Harald Welte14f09342009-01-29 19:28:38 +0000214 if (!sh->rx_msg) {
215 sh->rx_msg = msgb_alloc(SERIAL_ALLOC_SIZE);
216 sh->rx_msg->l2h = NULL;
217 }
218 msg = sh->rx_msg;
Harald Welte3b8ba212009-01-29 12:27:58 +0000219
Harald Welte61e42ad2009-01-18 19:10:46 +0000220 /* first read two byes to obtain length */
Harald Welte14f09342009-01-29 19:28:38 +0000221 if (msg->len < 2) {
222 rc = read(sh->fd.fd, msg->tail, 2 - msg->len);
Harald Welte61e42ad2009-01-18 19:10:46 +0000223 if (rc < 0) {
Harald Welte14f09342009-01-29 19:28:38 +0000224 perror("ERROR reading from serial port");
Harald Welte61e42ad2009-01-18 19:10:46 +0000225 msgb_free(msg);
Harald Welte14f09342009-01-29 19:28:38 +0000226 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000227 }
228 msgb_put(msg, rc);
Harald Welte61e42ad2009-01-18 19:10:46 +0000229
Harald Welte14f09342009-01-29 19:28:38 +0000230 if (msg->len >= 2) {
231 /* parse LAPD payload length */
232 if (msg->data[0] != 0)
233 fprintf(stderr, "Suspicious header byte 0: 0x%02x\n",
234 msg->data[0]);
Harald Welte61e42ad2009-01-18 19:10:46 +0000235
Harald Welte14f09342009-01-29 19:28:38 +0000236 sh->rxmsg_bytes_missing = msg->data[0] << 8;
237 sh->rxmsg_bytes_missing += msg->data[1];
238
239 if (sh->rxmsg_bytes_missing < LAPD_HDR_LEN -2)
240 fprintf(stderr, "Invalid length in hdr: %u\n",
241 sh->rxmsg_bytes_missing);
242 }
243 } else {
244 /* try to read as many of the missing bytes as are available */
245 rc = read(sh->fd.fd, msg->tail, sh->rxmsg_bytes_missing);
Harald Welte61e42ad2009-01-18 19:10:46 +0000246 if (rc < 0) {
Harald Welte14f09342009-01-29 19:28:38 +0000247 perror("ERROR reading from serial port");
Harald Welte61e42ad2009-01-18 19:10:46 +0000248 msgb_free(msg);
Harald Welte14f09342009-01-29 19:28:38 +0000249 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000250 }
251 msgb_put(msg, rc);
Harald Welte14f09342009-01-29 19:28:38 +0000252 sh->rxmsg_bytes_missing -= rc;
253
254 if (sh->rxmsg_bytes_missing == 0) {
255 /* we have one complete message now */
256 sh->rx_msg = NULL;
257
258 if (msg->len > LAPD_HDR_LEN)
259 msg->l2h = msg->data + LAPD_HDR_LEN;
260
261 fprintf(stdout, "RX: ");
262 hexdump(msg->data, msg->len);
263 rc = handle_serial_msg(msg);
264 }
Harald Welte61e42ad2009-01-18 19:10:46 +0000265 }
266
Harald Welte14f09342009-01-29 19:28:38 +0000267 return rc;
268}
Harald Welte61e42ad2009-01-18 19:10:46 +0000269
Harald Welte5e4d1b32009-02-01 13:36:56 +0000270/* select.c callback */
Harald Welte14f09342009-01-29 19:28:38 +0000271static int serial_fd_cb(struct bsc_fd *bfd, unsigned int what)
272{
273 int rc = 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000274
Harald Welte14f09342009-01-29 19:28:38 +0000275 if (what & BSC_FD_READ)
276 rc = handle_ser_read(bfd);
277
278 if (rc < 0)
279 return rc;
280
281 if (what & BSC_FD_WRITE)
282 rc = handle_ser_write(bfd);
283
284 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000285}
286
287static int file_is_readable(const char *fname)
288{
289 int rc;
290 struct stat st;
291
292 rc = stat(fname, &st);
293 if (rc < 0)
294 return 0;
295
296 if (S_ISREG(st.st_mode) && (st.st_mode & S_IRUSR))
297 return 1;
298
299 return 0;
300}
301
Harald Welte5e4d1b32009-02-01 13:36:56 +0000302/* callback function passed to the ABIS OML code */
303static int swload_cbfn(unsigned int hook, unsigned int event, struct msgb *msg,
304 void *data, void *param)
305{
306 if (hook != GSM_HOOK_NM_SWLOAD)
307 return 0;
Harald Welte61e42ad2009-01-18 19:10:46 +0000308
Harald Welte5e4d1b32009-02-01 13:36:56 +0000309 switch (event) {
310 case NM_MT_LOAD_INIT_ACK:
311 fprintf(stdout, "Software Load Initiate ACK\n");
312 break;
313 case NM_MT_LOAD_INIT_NACK:
314 fprintf(stderr, "ERROR: Software Load Initiate NACK\n");
315 exit(5);
316 break;
317 case NM_MT_LOAD_END_ACK:
318 /* FIXME: activate in case we want to */
319 if (data)
320 abis_nm_software_activate(g_bts, fname_safety,
321 swload_cbfn, g_bts);
322 break;
323 case NM_MT_LOAD_END_NACK:
324 fprintf(stderr, "ERROR: Software Load End NACK\n");
325 exit(3);
326 break;
327 case NM_MT_ACTIVATE_SW_NACK:
328 fprintf(stderr, "ERROR: Activate Software NACK\n");
329 exit(4);
330 break;
331 case NM_MT_ACTIVATE_SW_ACK:
332 bs11cfg_state = STATE_NONE;
333
334 break;
335 }
336 return 0;
337}
338
339/* handle a response from the BTS to a GET STATE command */
Harald Welte61e42ad2009-01-18 19:10:46 +0000340static int handle_state_resp(u_int8_t state)
341{
Harald Welte3b8ba212009-01-29 12:27:58 +0000342 int rc = 0;
343
Harald Welte61e42ad2009-01-18 19:10:46 +0000344 printf("STATE: ");
Harald Welte3b8ba212009-01-29 12:27:58 +0000345
Harald Welte61e42ad2009-01-18 19:10:46 +0000346 switch (state) {
347 case BS11_STATE_WARM_UP:
348 printf("Warm Up...\n");
349 sleep(5);
350 break;
351 case BS11_STATE_LOAD_SMU_SAFETY:
352 printf("Load SMU Safety...\n");
353 sleep(5);
354 break;
355 case BS11_STATE_SOFTWARE_RQD:
356 printf("Software required...\n");
Harald Welte3b8ba212009-01-29 12:27:58 +0000357 bs11cfg_state = STATE_SWLOAD;
Harald Welte5e4d1b32009-02-01 13:36:56 +0000358 /* send safety load. Use g_bts as private 'param'
359 * argument, so our swload_cbfn can distinguish
360 * a safety load from a regular software */
Harald Welte61e42ad2009-01-18 19:10:46 +0000361 if (file_is_readable(fname_safety))
Harald Welte623d5312009-01-29 21:14:05 +0000362 rc = abis_nm_software_load(g_bts, fname_safety,
Harald Welte5e4d1b32009-02-01 13:36:56 +0000363 win_size, swload_cbfn,
364 g_bts);
Harald Welte61e42ad2009-01-18 19:10:46 +0000365 else
Harald Welte071f34d2009-01-29 09:24:38 +0000366 fprintf(stderr, "No valid Safety Load file \"%s\"\n",
367 fname_safety);
Harald Welte61e42ad2009-01-18 19:10:46 +0000368 break;
369 case BS11_STATE_WAIT_MIN_CFG:
370 case BS11_STATE_WAIT_MIN_CFG_2:
371 printf("Wait minimal config...\n");
Harald Welte3b8ba212009-01-29 12:27:58 +0000372 bs11cfg_state = STATE_SWLOAD;
373 rc = create_objects(g_bts, have_trx1);
Harald Welte61e42ad2009-01-18 19:10:46 +0000374 break;
375 case BS11_STATE_MAINTENANCE:
376 printf("Maintenance...\n");
Harald Welte3b8ba212009-01-29 12:27:58 +0000377 bs11cfg_state = STATE_SWLOAD;
Harald Welte61e42ad2009-01-18 19:10:46 +0000378 /* send software (FIXME: over A-bis?) */
379 if (file_is_readable(fname_software))
Harald Welte5e4d1b32009-02-01 13:36:56 +0000380 rc = abis_nm_bs11_load_swl(g_bts, fname_software,
381 win_size, swload_cbfn);
Harald Welte61e42ad2009-01-18 19:10:46 +0000382 else
Harald Welte071f34d2009-01-29 09:24:38 +0000383 fprintf(stderr, "No valid Software file \"%s\"\n",
384 fname_software);
Harald Welte61e42ad2009-01-18 19:10:46 +0000385 break;
386 case BS11_STATE_NORMAL:
387 printf("Normal...\n");
388 return 1;
389 default:
390 printf("Unknown state 0x%02u\n", state);
391 sleep(5);
392 break;
393 }
Harald Welte3b8ba212009-01-29 12:27:58 +0000394 return rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000395}
396
Harald Welte5e4d1b32009-02-01 13:36:56 +0000397/* handle a fully-received message/packet from the RS232 port */
Harald Welte14f09342009-01-29 19:28:38 +0000398static int handle_serial_msg(struct msgb *rx_msg)
399{
400 struct abis_om_hdr *oh;
401 struct abis_om_fom_hdr *foh;
402 int rc = -1;
403
404 if (rx_msg->len < LAPD_HDR_LEN
405 + sizeof(struct abis_om_fom_hdr)
406 + sizeof(struct abis_om_hdr)) {
407 if (!memcmp(rx_msg->data + 2, too_fast,
408 sizeof(too_fast))) {
409 fprintf(stderr, "BS11 tells us we're too "
410 "fast, try --delay bigger than %u\n",
411 delay_ms);
412 return -E2BIG;
413 } else
414 fprintf(stderr, "unknown BS11 message\n");
415 }
416
417 oh = (struct abis_om_hdr *) msgb_l2(rx_msg);
418 foh = (struct abis_om_fom_hdr *) oh->data;
419 switch (foh->msg_type) {
Harald Welte043d04a2009-01-29 23:15:30 +0000420 case NM_MT_BS11_LMT_LOGON_ACK:
421 printf("LMT LOGON: ACK\n");
Harald Welte14f09342009-01-29 19:28:38 +0000422 if (bs11cfg_state == STATE_NONE)
423 bs11cfg_state = STATE_LOGON_ACK;
424 rc = 0;
425 break;
Harald Welte5e4d1b32009-02-01 13:36:56 +0000426 case NM_MT_BS11_LMT_LOGOFF_ACK:
427 exit(0);
428 break;
Harald Welte14f09342009-01-29 19:28:38 +0000429 case NM_MT_BS11_GET_STATE_ACK:
430 rc = handle_state_resp(foh->data[2]);
431 break;
432 default:
433 rc = abis_nm_rcvmsg(rx_msg);
434 }
435 if (rc < 0) {
436 perror("ERROR in main loop");
437 //break;
438 }
439 if (rc == 1)
440 return rc;
441
442 switch (bs11cfg_state) {
443 case STATE_NONE:
444 abis_nm_bs11_factory_logon(g_bts, 1);
445 break;
446 case STATE_LOGON_ACK:
447 abis_nm_bs11_get_state(g_bts);
448 break;
449 default:
450 break;
451 }
452
453 return rc;
454}
455
Harald Welte61e42ad2009-01-18 19:10:46 +0000456static void print_banner(void)
457{
458 printf("bs11_config (C) 2009 by Harald Welte and Dieter Spaar\n");
Harald Welte5e4d1b32009-02-01 13:36:56 +0000459 printf("This is FREE SOFTWARE with ABSOLUTELY NO WARRANTY\n\n");
Harald Welte61e42ad2009-01-18 19:10:46 +0000460}
461
462static void print_help(void)
463{
464 printf("Supported arguments:\n");
Harald Welte5e4d1b32009-02-01 13:36:56 +0000465 printf("\t-h --help\t\t\tPrint this help text\n");
466 printf("\t-p --port </dev/ttyXXX>\t\tSpecify serial port\n");
467 printf("\t-t --with-trx1\t\t\tAssume the BS-11 has 2 TRX\n");
468 printf("\t-s --software <file>\t\tSpecify Software file\n");
469 printf("\t-S --safety <file>\t\tSpecify Safety Load file\n");
470 printf("\t-d --delay <file>\t\tSpecify delay\n");
471 printf("\t-w --win-size <num>\t\tSpecify Window Size\n");
Harald Welte61e42ad2009-01-18 19:10:46 +0000472}
473
474static void handle_options(int argc, char **argv)
475{
476 print_banner();
477
478 while (1) {
479 int option_index = 0, c;
480 static struct option long_options[] = {
481 { "help", 0, 0, 'h' },
482 { "port", 1, 0, 'p' },
483 { "with-trx1", 0, 0, 't' },
484 { "software", 1, 0, 's' },
485 { "safety", 1, 0, 'S' },
Harald Welte3b8ba212009-01-29 12:27:58 +0000486 { "delay", 1, 0, 'd' },
Harald Welte623d5312009-01-29 21:14:05 +0000487 { "win-size", 1, 0, 'w' },
Harald Welte61e42ad2009-01-18 19:10:46 +0000488 };
489
Harald Welte623d5312009-01-29 21:14:05 +0000490 c = getopt_long(argc, argv, "hp:s:S:td:w:",
Harald Welte61e42ad2009-01-18 19:10:46 +0000491 long_options, &option_index);
492
493 if (c == -1)
494 break;
495
496 switch (c) {
497 case 'h':
498 print_help();
499 exit(0);
500 case 'p':
501 serial_port = optarg;
502 break;
503 case 't':
504 have_trx1 = 1;
505 break;
506 case 's':
507 fname_software = optarg;
508 break;
509 case 'S':
510 fname_safety = optarg;
511 break;
Harald Welte3b8ba212009-01-29 12:27:58 +0000512 case 'd':
513 delay_ms = atoi(optarg);
514 break;
Harald Welte623d5312009-01-29 21:14:05 +0000515 case 'w':
516 win_size = atoi(optarg);
517 break;
Harald Welte61e42ad2009-01-18 19:10:46 +0000518 default:
519 break;
520 }
521 }
522}
523
Harald Welte14f09342009-01-29 19:28:38 +0000524static void signal_handler(int signal)
525{
526 fprintf(stdout, "signal %u received\n", signal);
527
528 switch (signal) {
Harald Welte5e4d1b32009-02-01 13:36:56 +0000529 case SIGINT:
Harald Welte14f09342009-01-29 19:28:38 +0000530 abis_nm_bs11_factory_logon(g_bts, 0);
531 break;
532 }
533}
534
Harald Welte61e42ad2009-01-18 19:10:46 +0000535int main(int argc, char **argv)
536{
537 struct gsm_network *gsmnet;
Harald Weltef186c462009-01-29 08:45:19 +0000538 struct termios tio;
539 int rc;
Harald Welte61e42ad2009-01-18 19:10:46 +0000540
541 handle_options(argc, argv);
542
543 serial_fd = open(serial_port, O_RDWR);
544 if (serial_fd < 0) {
545 perror("cannot open serial port:");
546 exit(1);
547 }
548
Harald Weltef186c462009-01-29 08:45:19 +0000549 /* set baudrate */
550 rc = tcgetattr(serial_fd, &tio);
551 if (rc < 0) {
552 perror("tcgetattr()");
553 exit(1);
554 }
555 cfsetispeed(&tio, B19200);
556 cfsetospeed(&tio, B19200);
Harald Welte071f34d2009-01-29 09:24:38 +0000557 tio.c_cflag |= (CREAD | CLOCAL | CS8);
558 tio.c_cflag &= ~(PARENB | CSTOPB | CSIZE | CRTSCTS);
559 tio.c_lflag &= ~(ICANON | ECHO | ECHOE | ISIG);
560 tio.c_iflag |= (INPCK | ISTRIP);
561 tio.c_iflag &= ~(ISTRIP | IXON | IXOFF | IGNBRK | INLCR | ICRNL | IGNCR);
Harald Welte623d5312009-01-29 21:14:05 +0000562 tio.c_oflag &= ~(OPOST);
Harald Weltef186c462009-01-29 08:45:19 +0000563 rc = tcsetattr(serial_fd, TCSADRAIN, &tio);
564 if (rc < 0) {
565 perror("tcsetattr()");
566 exit(1);
567 }
Harald Welte61e42ad2009-01-18 19:10:46 +0000568
569 gsmnet = gsm_network_init(1, 1, 1);
570 if (!gsmnet) {
571 fprintf(stderr, "Unable to allocate gsm network\n");
572 exit(1);
573 }
574 g_bts = &gsmnet->bts[0];
575
Harald Welte14f09342009-01-29 19:28:38 +0000576 INIT_LLIST_HEAD(&ser_handle->tx_queue);
577 ser_handle->fd.fd = serial_fd;
578 ser_handle->fd.when = BSC_FD_READ;
579 ser_handle->fd.cb = serial_fd_cb;
580 ser_handle->fd.data = ser_handle;
581 rc = bsc_register_fd(&ser_handle->fd);
582 if (rc < 0) {
583 fprintf(stderr, "could not register FD: %s\n",
584 strerror(rc));
585 exit(1);
586 }
587
Harald Welte5e4d1b32009-02-01 13:36:56 +0000588 signal(SIGINT, &signal_handler);
Harald Welte14f09342009-01-29 19:28:38 +0000589
Harald Welte61e42ad2009-01-18 19:10:46 +0000590 abis_nm_bs11_factory_logon(g_bts, 1);
Harald Welte5e4d1b32009-02-01 13:36:56 +0000591 //abis_nm_bs11_get_serno(g_bts);
Harald Welte61e42ad2009-01-18 19:10:46 +0000592
593 while (1) {
Harald Welte14f09342009-01-29 19:28:38 +0000594 bsc_select_main();
Harald Welte61e42ad2009-01-18 19:10:46 +0000595 }
596
597 abis_nm_bs11_factory_logon(g_bts, 0);
598
599 close(serial_fd);
600 exit(0);
601}