blob: afa90321c685b9d584c5a511f8bf2f45737b7d06 [file] [log] [blame]
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +02001/* OpenBSC Abis input driver for mISDNuser */
2
3/* (C) 2008-2009 by Harald Welte <laforge@gnumonks.org>
4 * (C) 2009 by Holger Hans Peter Freyther <zecke@selfish.org>
5 *
6 * 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 Affero General Public License as published by
10 * the Free Software Foundation; either version 3 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 Affero General Public License for more details.
17 *
18 * You should have received a copy of the GNU Affero General Public License
19 * along with this program. If not, see <http://www.gnu.org/licenses/>.
20 *
21 */
22
23#include "internal.h"
24
25#include <stdio.h>
26#include <unistd.h>
27#include <stdlib.h>
28#include <errno.h>
29#include <string.h>
30#include <time.h>
31#include <sys/fcntl.h>
32#include <sys/socket.h>
33#include <sys/ioctl.h>
34#include <arpa/inet.h>
35#include <mISDNif.h>
36
37//#define AF_COMPATIBILITY_FUNC
38//#include <compat_af_isdn.h>
39#ifndef AF_ISDN
40#define AF_ISDN 34
41#define PF_ISDN AF_ISDN
42#endif
43
44#include <osmocom/core/select.h>
45#include <osmocom/core/msgb.h>
46#include <osmocom/core/logging.h>
Pablo Neira Ayuso177094b2011-06-07 12:21:51 +020047#include <osmocom/abis/e1_input.h>
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +020048#include <talloc.h>
49/*#include <openbsc/debug.h>
50#include <openbsc/gsm_data.h>
51#include <openbsc/abis_nm.h>
52#include <openbsc/abis_rsl.h>
53#include <openbsc/subchan_demux.h>
54#include <openbsc/e1_input.h>
55#include <openbsc/signal.h> */
56
57#define TS1_ALLOC_SIZE 300
58
59struct prim_name {
60 unsigned int prim;
61 const char *name;
62};
63
64const struct prim_name prim_names[] = {
65 { PH_CONTROL_IND, "PH_CONTROL_IND" },
66 { PH_DATA_IND, "PH_DATA_IND" },
67 { PH_DATA_CNF, "PH_DATA_CNF" },
68 { PH_ACTIVATE_IND, "PH_ACTIVATE_IND" },
69 { DL_ESTABLISH_IND, "DL_ESTABLISH_IND" },
70 { DL_ESTABLISH_CNF, "DL_ESTABLISH_CNF" },
71 { DL_RELEASE_IND, "DL_RELEASE_IND" },
72 { DL_RELEASE_CNF, "DL_RELEASE_CNF" },
73 { DL_DATA_IND, "DL_DATA_IND" },
74 { DL_UNITDATA_IND, "DL_UNITDATA_IND" },
75 { DL_INFORMATION_IND, "DL_INFORMATION_IND" },
76 { MPH_ACTIVATE_IND, "MPH_ACTIVATE_IND" },
77 { MPH_DEACTIVATE_IND, "MPH_DEACTIVATE_IND" },
78};
79
80const char *get_prim_name(unsigned int prim)
81{
82 int i;
83
84 for (i = 0; i < ARRAY_SIZE(prim_names); i++) {
85 if (prim_names[i].prim == prim)
86 return prim_names[i].name;
87 }
88
89 return "UNKNOWN";
90}
91
92static int handle_ts1_read(struct osmo_fd *bfd)
93{
94 struct e1inp_line *line = bfd->data;
95 unsigned int ts_nr = bfd->priv_nr;
96 struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
97 struct e1inp_sign_link *link;
98 struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE, "mISDN TS1");
99 struct sockaddr_mISDN l2addr;
100 struct mISDNhead *hh;
101 socklen_t alen;
102 int ret;
103
104 if (!msg)
105 return -ENOMEM;
106
107 hh = (struct mISDNhead *) msg->data;
108
109 alen = sizeof(l2addr);
110 ret = recvfrom(bfd->fd, msg->data, 300, 0,
111 (struct sockaddr *) &l2addr, &alen);
112 if (ret < 0) {
113 fprintf(stderr, "recvfrom error %s\n", strerror(errno));
114 return ret;
115 }
116
117 if (alen != sizeof(l2addr)) {
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200118 if (line->ops.error)
119 line->ops.error(NULL, -EBADMSG);
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200120 return -EINVAL;
121 }
122
123 msgb_put(msg, ret);
124
125 DEBUGP(DMI, "alen =%d, dev(%d) channel(%d) sapi(%d) tei(%d)\n",
126 alen, l2addr.dev, l2addr.channel, l2addr.sapi, l2addr.tei);
127
128 DEBUGP(DMI, "<= len = %d, prim(0x%x) id(0x%x): %s\n",
129 ret, hh->prim, hh->id, get_prim_name(hh->prim));
130
131 switch (hh->prim) {
132 case DL_INFORMATION_IND:
133 /* mISDN tells us which channel number is allocated for this
134 * tuple of (SAPI, TEI). */
135 DEBUGP(DMI, "DL_INFORMATION_IND: use channel(%d) sapi(%d) tei(%d) for now\n",
136 l2addr.channel, l2addr.sapi, l2addr.tei);
137 link = e1inp_lookup_sign_link(e1i_ts, l2addr.tei, l2addr.sapi);
138 if (!link) {
139 DEBUGPC(DMI, "mISDN message for unknown sign_link\n");
140 msgb_free(msg);
141 return -EINVAL;
142 }
143 /* save the channel number in the driver private struct */
144 link->driver.misdn.channel = l2addr.channel;
145 break;
146 case DL_ESTABLISH_IND:
147 DEBUGP(DMI, "DL_ESTABLISH_IND: channel(%d) sapi(%d) tei(%d)\n",
148 l2addr.channel, l2addr.sapi, l2addr.tei);
149 /* For some strange reason, sometimes the DL_INFORMATION_IND tells
150 * us the wrong channel, and we only get the real channel number
151 * during the DL_ESTABLISH_IND */
152 link = e1inp_lookup_sign_link(e1i_ts, l2addr.tei, l2addr.sapi);
153 if (!link) {
154 DEBUGPC(DMI, "mISDN message for unknown sign_link\n");
155 msgb_free(msg);
156 return -EINVAL;
157 }
158 /* save the channel number in the driver private struct */
159 link->driver.misdn.channel = l2addr.channel;
160 ret = e1inp_event(e1i_ts, S_INP_TEI_UP, l2addr.tei, l2addr.sapi);
161 break;
162 case DL_RELEASE_IND:
163 DEBUGP(DMI, "DL_RELEASE_IND: channel(%d) sapi(%d) tei(%d)\n",
164 l2addr.channel, l2addr.sapi, l2addr.tei);
165 ret = e1inp_event(e1i_ts, S_INP_TEI_DN, l2addr.tei, l2addr.sapi);
166 break;
167 case DL_DATA_IND:
168 case DL_UNITDATA_IND:
169 msg->l2h = msg->data + MISDN_HEADER_LEN;
170 DEBUGP(DMI, "RX: %s\n", osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
171 ret = e1inp_rx_ts(e1i_ts, msg, l2addr.tei, l2addr.sapi);
172 break;
173 case PH_ACTIVATE_IND:
174 DEBUGP(DMI, "PH_ACTIVATE_IND: channel(%d) sapi(%d) tei(%d)\n",
175 l2addr.channel, l2addr.sapi, l2addr.tei);
176 break;
177 case PH_DEACTIVATE_IND:
178 DEBUGP(DMI, "PH_DEACTIVATE_IND: channel(%d) sapi(%d) tei(%d)\n",
179 l2addr.channel, l2addr.sapi, l2addr.tei);
180 break;
181 default:
Pablo Neira Ayuso5a4b7c52011-06-07 14:07:48 +0200182 if (line->ops.error)
183 line->ops.error(NULL, -EBADMSG);
Pablo Neira Ayuso0ba77d52011-06-05 18:32:44 +0200184 break;
185 }
186 return ret;
187}
188
189static int ts_want_write(struct e1inp_ts *e1i_ts)
190{
191 /* We never include the mISDN B-Channel FD into the
192 * writeset, since it doesn't support poll() based
193 * write flow control */
194 if (e1i_ts->type == E1INP_TS_TYPE_TRAU)
195 return 0;
196
197 e1i_ts->driver.misdn.fd.when |= BSC_FD_WRITE;
198
199 return 0;
200}
201
202static void timeout_ts1_write(void *data)
203{
204 struct e1inp_ts *e1i_ts = (struct e1inp_ts *)data;
205
206 /* trigger write of ts1, due to tx delay timer */
207 ts_want_write(e1i_ts);
208}
209
210static int handle_ts1_write(struct osmo_fd *bfd)
211{
212 struct e1inp_line *line = bfd->data;
213 unsigned int ts_nr = bfd->priv_nr;
214 struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
215 struct e1inp_sign_link *sign_link;
216 struct sockaddr_mISDN sa;
217 struct msgb *msg;
218 struct mISDNhead *hh;
219 uint8_t *l2_data;
220 int ret;
221
222 bfd->when &= ~BSC_FD_WRITE;
223
224 /* get the next msg for this timeslot */
225 msg = e1inp_tx_ts(e1i_ts, &sign_link);
226 if (!msg) {
227 /* no message after tx delay timer */
228 return 0;
229 }
230
231 l2_data = msg->data;
232
233 /* prepend the mISDNhead */
234 hh = (struct mISDNhead *) msgb_push(msg, sizeof(*hh));
235 hh->prim = DL_DATA_REQ;
236
237 DEBUGP(DMI, "TX channel(%d) TEI(%d) SAPI(%d): %s\n",
238 sign_link->driver.misdn.channel, sign_link->tei,
239 sign_link->sapi, osmo_hexdump(l2_data, msg->len - MISDN_HEADER_LEN));
240
241 /* construct the sockaddr */
242 sa.family = AF_ISDN;
243 sa.sapi = sign_link->sapi;
244 sa.dev = sign_link->tei;
245 sa.channel = sign_link->driver.misdn.channel;
246
247 ret = sendto(bfd->fd, msg->data, msg->len, 0,
248 (struct sockaddr *)&sa, sizeof(sa));
249 if (ret < 0)
250 fprintf(stderr, "%s sendto failed %d\n", __func__, ret);
251 msgb_free(msg);
252
253 /* set tx delay timer for next event */
254 e1i_ts->sign.tx_timer.cb = timeout_ts1_write;
255 e1i_ts->sign.tx_timer.data = e1i_ts;
256 osmo_timer_schedule(&e1i_ts->sign.tx_timer, 0, e1i_ts->sign.delay);
257
258 return ret;
259}
260
261#define BCHAN_TX_GRAN 160
262/* write to a B channel TS */
263static int handle_tsX_write(struct osmo_fd *bfd)
264{
265 struct e1inp_line *line = bfd->data;
266 unsigned int ts_nr = bfd->priv_nr;
267 struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
268 struct mISDNhead *hh;
269 uint8_t tx_buf[BCHAN_TX_GRAN + sizeof(*hh)];
270 struct subch_mux *mx = &e1i_ts->trau.mux;
271 int ret;
272
273 hh = (struct mISDNhead *) tx_buf;
274 hh->prim = PH_DATA_REQ;
275
276 subchan_mux_out(mx, tx_buf+sizeof(*hh), BCHAN_TX_GRAN);
277
278 DEBUGP(DMIB, "BCHAN TX: %s\n",
279 osmo_hexdump(tx_buf+sizeof(*hh), BCHAN_TX_GRAN));
280
281 ret = send(bfd->fd, tx_buf, sizeof(*hh) + BCHAN_TX_GRAN, 0);
282 if (ret < sizeof(*hh) + BCHAN_TX_GRAN)
283 DEBUGP(DMIB, "send returns %d instead of %zu\n", ret,
284 sizeof(*hh) + BCHAN_TX_GRAN);
285
286 return ret;
287}
288
289#define TSX_ALLOC_SIZE 4096
290/* FIXME: read from a B channel TS */
291static int handle_tsX_read(struct osmo_fd *bfd)
292{
293 struct e1inp_line *line = bfd->data;
294 unsigned int ts_nr = bfd->priv_nr;
295 struct e1inp_ts *e1i_ts = &line->ts[ts_nr-1];
296 struct msgb *msg = msgb_alloc(TSX_ALLOC_SIZE, "mISDN TSx");
297 struct mISDNhead *hh;
298 int ret;
299
300 if (!msg)
301 return -ENOMEM;
302
303 hh = (struct mISDNhead *) msg->data;
304
305 ret = recv(bfd->fd, msg->data, TSX_ALLOC_SIZE, 0);
306 if (ret < 0) {
307 fprintf(stderr, "recvfrom error %s\n", strerror(errno));
308 return ret;
309 }
310
311 msgb_put(msg, ret);
312
313 if (hh->prim != PH_CONTROL_IND)
314 DEBUGP(DMIB, "<= BCHAN len = %d, prim(0x%x) id(0x%x): %s\n",
315 ret, hh->prim, hh->id, get_prim_name(hh->prim));
316
317 switch (hh->prim) {
318 case PH_DATA_IND:
319 msg->l2h = msg->data + MISDN_HEADER_LEN;
320 DEBUGP(DMIB, "BCHAN RX: %s\n",
321 osmo_hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN));
322 ret = e1inp_rx_ts(e1i_ts, msg, 0, 0);
323 break;
324 case PH_ACTIVATE_IND:
325 case PH_DATA_CNF:
326 /* physical layer indicates that data has been sent,
327 * we thus can send some more data */
328 ret = handle_tsX_write(bfd);
329 default:
330 break;
331 }
332 /* FIXME: why do we free signalling msgs in the caller, and trau not? */
333 msgb_free(msg);
334
335 return ret;
336}
337
338/* callback from select.c in case one of the fd's can be read/written */
339static int misdn_fd_cb(struct osmo_fd *bfd, unsigned int what)
340{
341 struct e1inp_line *line = bfd->data;
342 unsigned int ts_nr = bfd->priv_nr;
343 unsigned int idx = ts_nr-1;
344 struct e1inp_ts *e1i_ts = &line->ts[idx];
345 int rc = 0;
346
347 switch (e1i_ts->type) {
348 case E1INP_TS_TYPE_SIGN:
349 if (what & BSC_FD_READ)
350 rc = handle_ts1_read(bfd);
351 if (what & BSC_FD_WRITE)
352 rc = handle_ts1_write(bfd);
353 break;
354 case E1INP_TS_TYPE_TRAU:
355 if (what & BSC_FD_READ)
356 rc = handle_tsX_read(bfd);
357 /* We never include the mISDN B-Channel FD into the
358 * writeset, since it doesn't support poll() based
359 * write flow control */
360 break;
361 default:
362 fprintf(stderr, "unknown E1 TS type %u\n", e1i_ts->type);
363 break;
364 }
365
366 return rc;
367}
368
369static int activate_bchan(struct e1inp_line *line, int ts, int act)
370{
371 struct mISDNhead hh;
372 int ret;
373 unsigned int idx = ts-1;
374 struct e1inp_ts *e1i_ts = &line->ts[idx];
375 struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd;
376
377 fprintf(stdout, "activate bchan\n");
378 if (act)
379 hh.prim = PH_ACTIVATE_REQ;
380 else
381 hh.prim = PH_DEACTIVATE_REQ;
382
383 hh.id = MISDN_ID_ANY;
384 ret = sendto(bfd->fd, &hh, sizeof(hh), 0, NULL, 0);
385 if (ret < 0) {
386 fprintf(stdout, "could not send ACTIVATE_RQ %s\n",
387 strerror(errno));
388 }
389
390 return ret;
391}
392
393static int
394mi_e1_line_update(struct e1inp_line *line, enum e1inp_line_role role);
395
396struct e1inp_driver misdn_driver = {
397 .name = "misdn",
398 .want_write = ts_want_write,
399 .default_delay = 50000,
400 .line_update = &mi_e1_line_update,
401};
402
403static int mi_e1_setup(struct e1inp_line *line, int release_l2)
404{
405 int ts, ret;
406
407 /* TS0 is CRC4, don't need any fd for it */
408 for (ts = 1; ts < NUM_E1_TS; ts++) {
409 unsigned int idx = ts-1;
410 struct e1inp_ts *e1i_ts = &line->ts[idx];
411 struct osmo_fd *bfd = &e1i_ts->driver.misdn.fd;
412 struct sockaddr_mISDN addr;
413
414 bfd->data = line;
415 bfd->priv_nr = ts;
416 bfd->cb = misdn_fd_cb;
417
418 switch (e1i_ts->type) {
419 case E1INP_TS_TYPE_NONE:
420 continue;
421 break;
422 case E1INP_TS_TYPE_SIGN:
423 bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_NT);
424 bfd->when = BSC_FD_READ;
425 break;
426 case E1INP_TS_TYPE_TRAU:
427 bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
428 /* We never include the mISDN B-Channel FD into the
429 * writeset, since it doesn't support poll() based
430 * write flow control */
431 bfd->when = BSC_FD_READ;
432 break;
433 }
434
435 if (bfd->fd < 0) {
436 fprintf(stderr, "%s could not open socket %s\n",
437 __func__, strerror(errno));
438 return bfd->fd;
439 }
440
441 memset(&addr, 0, sizeof(addr));
442 addr.family = AF_ISDN;
443 addr.dev = line->num;
444 switch (e1i_ts->type) {
445 case E1INP_TS_TYPE_SIGN:
446 addr.channel = 0;
447 /* SAPI not supported yet in kernel */
448 //addr.sapi = e1inp_ts->sign.sapi;
449 addr.sapi = 0;
450 addr.tei = GROUP_TEI;
451 break;
452 case E1INP_TS_TYPE_TRAU:
453 addr.channel = ts;
454 break;
455 default:
456 DEBUGP(DMI, "unsupported E1 TS type: %u\n",
457 e1i_ts->type);
458 break;
459 }
460
461 ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
462 if (ret < 0) {
463 fprintf(stderr, "could not bind l2 socket %s\n",
464 strerror(errno));
465 return -EIO;
466 }
467
468 if (e1i_ts->type == E1INP_TS_TYPE_SIGN) {
469 ret = ioctl(bfd->fd, IMCLEAR_L2, &release_l2);
470 if (ret < 0) {
471 fprintf(stderr, "could not send IOCTL IMCLEAN_L2 %s\n", strerror(errno));
472 return -EIO;
473 }
474 }
475
476 /* FIXME: only activate B-Channels once we start to
477 * use them to conserve CPU power */
478 if (e1i_ts->type == E1INP_TS_TYPE_TRAU)
479 activate_bchan(line, ts, 1);
480
481 ret = osmo_fd_register(bfd);
482 if (ret < 0) {
483 fprintf(stderr, "could not register FD: %s\n",
484 strerror(ret));
485 return ret;
486 }
487 }
488
489 return 0;
490}
491
492static int
493mi_e1_line_update(struct e1inp_line *line, enum e1inp_line_role role)
494{
495 struct mISDN_devinfo devinfo;
496 int sk, ret, cnt;
497
498 if (line->driver != &misdn_driver)
499 return -EINVAL;
500
501 /* open the ISDN card device */
502 sk = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
503 if (sk < 0) {
504 fprintf(stderr, "%s could not open socket %s\n",
505 __func__, strerror(errno));
506 return sk;
507 }
508
509 ret = ioctl(sk, IMGETCOUNT, &cnt);
510 if (ret) {
511 fprintf(stderr, "%s error getting interf count: %s\n",
512 __func__, strerror(errno));
513 close(sk);
514 return -ENODEV;
515 }
516 //DEBUGP(DMI,"%d device%s found\n", cnt, (cnt==1)?"":"s");
517 printf("%d device%s found\n", cnt, (cnt==1)?"":"s");
518#if 1
519 devinfo.id = line->num;
520 ret = ioctl(sk, IMGETDEVINFO, &devinfo);
521 if (ret < 0) {
522 fprintf(stdout, "error getting info for device %d: %s\n",
523 line->num, strerror(errno));
524 return -ENODEV;
525 }
526 fprintf(stdout, " id: %d\n", devinfo.id);
527 fprintf(stdout, " Dprotocols: %08x\n", devinfo.Dprotocols);
528 fprintf(stdout, " Bprotocols: %08x\n", devinfo.Bprotocols);
529 fprintf(stdout, " protocol: %d\n", devinfo.protocol);
530 fprintf(stdout, " nrbchan: %d\n", devinfo.nrbchan);
531 fprintf(stdout, " name: %s\n", devinfo.name);
532#endif
533
534 if (!(devinfo.Dprotocols & (1 << ISDN_P_NT_E1))) {
535 fprintf(stderr, "error: card is not of type E1 (NT-mode)\n");
536 return -EINVAL;
537 }
538
539 ret = mi_e1_setup(line, 1);
540 if (ret)
541 return ret;
542
543 return 0;
544}
545
546void e1inp_misdn_init(void)
547{
548 /* register the driver with the core */
549 e1inp_driver_register(&misdn_driver);
550}