blob: 6b232233c93da9a798960a0c2c4f1cb620d8ad10 [file] [log] [blame]
Harald Welte52b1f982008-12-23 20:25:15 +00001/* OpenBSC Abis interface to mISDNuser
2 *
3 * (C) 2008 by Harald Welte <laforge@gnumonks.org>
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 General Public License as published by
9 * the Free Software Foundation; either version 2 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 General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 */
22
23#include <stdio.h>
24#include <unistd.h>
25#include <stdlib.h>
26#include <errno.h>
27#include <string.h>
28#include <sys/types.h>
29#include <sys/socket.h>
30#include <sys/ioctl.h>
31#include <mISDNif.h>
32
33#define AF_COMPATIBILITY_FUNC
34#include <compat_af_isdn.h>
35
36#define NUM_E1_TS 32
37
38/* data structure for one E1 interface with A-bis */
39struct mi_e1_handle {
40 struct gsm_bts *bts;
41
42 /* The mISDN card number of the card we use */
43 int cardnr;
44
45 /* The RSL adress */
46 struct sockaddr_mISDN l2addr;
47
48 /* The OML adress */
49 struct sockaddr_mISDN omladdr;
50
51 struct gsm_fd fd[NUM_E1_TS];
52};
53
54#define SAPI_L2ML 0
55#define SAPI_OML 62
56#define SAPI_RSL 63
57
58#define TEI_L2ML 127
59#define TEI_OML 25
60#define TEI_RSL 1
61
62static void hexdump(unsigned char *buf, int len)
63{
64 int i;
65 for (i = 0; i < len; i++) {
66 fprintf(stdout, "%02x ", buf[i]);
67 }
68 fprintf(stdout, "\n");
69}
70
71#define TS1_ALLOC_SIZE 300
72
73static int handle_ts1_read(struct bsc_fd *bfd)
74{
75 struct mi_e1_handle *e1h = bfd->data;
76 struct msgb *msg = msgb_alloc(TS1_ALLOC_SIZE);
77 struct sockaddr_mISDN l2dadr;
78 socklen_t alen;
79
80 if (!msg)
81 return -ENOMEM;
82
83 msg->bts = e1h->bts;
84
85 alen = sizeof(l2addr);
86 ret = recvfrom(bfd->fd, msg->data, 300, 0,
87 (struct sockaddr *) &l2addr, &alen);
88 if (ret < 0) {
89 fprintf(stderr, "recvfrom error %s\n", strerror(errno));
90 return ret;
91 }
92
93 if (alen != sizeof(l2addr))
94 return -EINVAL;
95
96 msgb_put(msg, ret);
97
98 DEBUGP(DMI, "alen =%d, dev(%d) channel(%d) sapi(%d) tei(%d)\n",
99 alen, l2addr.dev, l2addr.channel, l2addr.sapi, l2addr.tei);
100
101 DEBUGP(DMI, "<= len = %d, prim(0x%x) id(0x%x)\n",
102 ret, hh->prim, hh->id);
103
104 switch (hh->prim) {
105 case DL_INFORMATION_IND:
106 DEBUGP(DMI, "got DL_INFORMATION_IND\n");
107 struct sockaddr_mISDN *sa;
108 char *lstr = "UNKN";
109
110 switch (l2addr.tei) {
111 case TEI_OML:
112 sa = &e1h->omladdr;
113 lstr = "OML";
114 break;
115 case TEI_RSL:
116 sa = &e1h->l2addr;
117 lstr = "RSL";
118 break;
119 default:
120 continue;
121 }
122 DEBUGP(DMI, "%s use channel(%d) sapi(%d) tei(%d) for now\n",
123 lstr, l2addr.channel, l2addr.sapi, l2addr.tei);
124 memcpy(sa, &l2addr, sizeof(l2addr));
125 break;
126 case DL_ESTABLISH_IND:
127 DEBUGP(DMI, "got DL_ESTABLISH_IND\n");
128 break;
129 case DL_ESTABLISH_CNF:
130 DEBUGP(DMI, "got DL_ESTABLISH_CNF\n");
131 break;
132 case DL_RELEASE_IND:
133 DEBUGP(DMI, "got DL_RELEASE_IND\n");
134 break;
135 case MPH_ACTIVATE_IND:
136 DEBUGP(DMI, "got MPH_ACTIVATE_IND\n");
137 break;
138 case MPH_DEACTIVATE_IND:
139 DEBUGP(DMI, "got MPH_DEACTIVATE_IND\n");
140 break;
141 case DL_DATA_IND:
142 DEBUGP(DMI, "got DL_DATA_IND\n");
143 msg->l2_off = MISDN_HEADER_LEN;
144 hexdump(msgb_l2(msg), ret - MISDN_HEADER_LEN);
145 switch (l2addr.tei) {
146 case TEI_OML:
147 ret = abis_nm_rcvmsg(msg);
148 break;
149 case TEI_RSL:
150 ret = abis_rsl_rcvmsg(msg);
151 break;
152 default:
153 fprintf(stderr, "DATA_IND for unknown TEI\n");
154 break;
155 }
156 break;
157 default:
158 DEBUGP(DMI, "got unexpected 0x%x prim\n", hh->prim);
159 break;
160 }
161 return ret;
162}
163
164static int handle_ts1_write(struct bsc_fd *bfd)
165{
166 struct mi_e1_handle *e1h = bfd->data;
167
168 /* FIXME: dequeue a pending msgb for RSL / OML */
169
170 /* prepend the mISDNhead */
171 hh = (struct mISDNhed *) msg_
172 hh->prim = DL_DATA_REQ;
173
174 /* FIXME: send it off */
175}
176
177static int handle_tsX_read(struct bsc_fd *bfd)
178{
179 /* FIXME: read from a B channel TS */
180}
181
182static int handle_TsX_write(struct bsc_fd *bfd)
183{
184 /* FIXME: write to a B channel TS */
185}
186
187/* callback from select.c in case one of the fd's can be read/written */
188static int misdn_fd_cb(struct gsm_fd *bfd, unsigned int what)
189{
190 unsigned int e1_ts = bfd->priv_nr;
191 int rc = 0;
192
193 switch (e1_ts) {
194 case 1:
195 if (what & BSC_FD_READ)
196 rc = handle_ts1_read(bfd);
197 if (what & BSC_FD_WRITE)
198 rc = handle_ts1_write(bfd);
199 break;
200 default:
201 if (what & BSC_FD_READ)
202 rc = handle_tsX_read(bfd);
203 if (what & BSC_FD_WRITE)
204 rc = handle_tsX_write(bfd);
205 break;
206 }
207
208 return rc;
209}
210
211static int mi_setup(devinfo_t *di)
212{
213 int ts, sk, ret;
214 struct mISDN_devinfo devinfo;
215
216 sk = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
217 if (sk < 0)
218 fprintf(stderr, "could not open socket %s\n", strerror(errno));
219 return sk;
220 }
221
222 ret = ioctl(sk, IMGETCOUNT, &cnt);
223 if (ret) {
224 fprintf(stderr, "error getting interf count: %s\n",
225 strerror(errno));
226 close(sk);
227 return -ENODEV;
228 }
229 DEBUGP(DMI,"%d device%s found\n", cnt, (cnt==1)?"":"s");
230#if 0
231 devinfo.id = di->cardnr;
232 ret = ioctl(sk, IMGETDEVINFO, &devinfo);
233 if (ret < 0) {
234 fprintf(stdout, "error getting info for device %d: %s\n",
235 di->cardnr, strerror(errno));
236 return -ENODEV;
237 }
238 fprintf(stdout, " id: %d\n", devinfo.id);
239 fprintf(stdout, " Dprotocols: %08x\n", devinfo.Dprotocols);
240 fprintf(stdout, " Bprotocols: %08x\n", devinfo.Bprotocols);
241 fprintf(stdout, " protocol: %d\n", devinfo.protocol);
242 fprintf(stdout, " nrbchan: %d\n", devinfo.nrbchan);
243 fprintf(stdout, " name: %s\n", devinfo.name);
244#endif
245
246 /* TS0 is CRC4, don't need any fd for it */
247 for (ts = 1; ts < NUM_E1_TS; ts++) {
248 unsigned int idx = i-1;
249 struct bsc_fd *bfd = &e1h->fd[idx];
250 struct sockaddr_mISDN addr;
251
252 if (ts == 1)
253 bfd->fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_LAPD_NT);
254 else
255 bfd->fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_B_RAW);
256
257 if (bfd->fd < 0)
258 fprintf(stderr, "could not open socket %s\n",
259 strerror(errno));
260 return bfd->fd;
261 }
262
263 memset(&addr, 0, sizeof(addr));
264 addr.family = AF_ISDN;
265 addr.dev = e1h->cardnr;
266 if (ts == 1) {
267 addr.channel = 0;
268 addr.sapi = 0;/* SAPI not supported yet in kernel */
269 addr.tei = TEI_L2ML;
270 } else
271 addr.channel = ts;
272
273 ret = bind(bfd->fd, (struct sockaddr *) &addr, sizeof(addr));
274 if (ret < 0) {
275 fprintf(stdout, "could not bind l2 socket %s\n",
276 strerror(errno));
277 return -EIO;
278 }
279 }
280}
281