blob: d8819ac6bd09c51146f941a0af0dac06ea6eac7e [file] [log] [blame]
Holger Freyther3cf00fb2009-06-08 10:33:06 +00001/* isdnsync.c
2 *
3 * Author Andreas Eversberg <jolly@eversberg.eu>
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#include <stdio.h>
23#include <stdlib.h>
24#include <string.h>
25#include <unistd.h>
26#include <sys/ioctl.h>
27#include <sys/types.h>
28#include <sys/stat.h>
29#include <fcntl.h>
30#include <errno.h>
31#include <sys/socket.h>
32#include "mISDNif.h"
33#define MISDN_OLD_AF_COMPATIBILITY
34#define AF_COMPATIBILITY_FUNC
35#include "compat_af_isdn.h"
36
37int card = 0;
38int sock = -1;
39
40int mISDN_open(void)
41{
42 int fd, ret;
43 struct mISDN_devinfo devinfo;
44 struct sockaddr_mISDN l2addr;
45
46 fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
47 if (fd < 0) {
48 fprintf(stderr, "could not open socket (%s)\n", strerror(errno));
49 return fd;
50 }
51 devinfo.id = card;
52 ret = ioctl(fd, IMGETDEVINFO, &devinfo);
53 if (ret < 0) {
54 fprintf(stderr,"could not send IOCTL IMGETCOUNT (%s)\n", strerror(errno));
55 close(fd);
56 return ret;
57 }
58 close(fd);
59 if (!(devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
60 && !(devinfo.Dprotocols & (1 << ISDN_P_TE_E1))) {
61 fprintf(stderr,"Interface does not support TE mode (%s)\n", strerror(errno));
62 close(fd);
63 return ret;
64 }
65 fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_TE);
66 if (fd < 0) {
67 fprintf(stderr,"could not open ISDN_P_LAPD_TE socket (%s)\n", strerror(errno));
68 return fd;
69 }
70 l2addr.family = AF_ISDN;
71 l2addr.dev = card;
72 l2addr.channel = 0;
73 l2addr.sapi = 0;
74 l2addr.tei = 0;
75 ret = bind(fd, (struct sockaddr *)&l2addr, sizeof(l2addr));
76 if (ret < 0) {
77 fprintf(stderr,"could not bind socket for card %d (%s)\n", card, strerror(errno));
78 close(fd);
79 return ret;
80 }
81 sock = fd;
82
83 return sock;
84}
85
86
87void mISDN_handle(void)
88{
89 int ret;
90 fd_set rfd;
91 struct timeval tv;
92 struct sockaddr_mISDN addr;
93 socklen_t alen;
94 unsigned char buffer[2048];
95 struct mISDNhead *hh = (struct mISDNhead *)buffer;
96 int l1 = 0, l2 = 0, tei = 0;
97
98 while(1) {
99again:
100 FD_ZERO(&rfd);
101 FD_SET(sock, &rfd);
102 tv.tv_sec = 2;
103 tv.tv_usec = 0;
104 ret = select(sock+1, &rfd, NULL, NULL, &tv);
105 if (ret < 0) {
106 if (errno == EINTR)
107 continue;
108 fprintf(stderr, "%s aborted: %s\n", __FUNCTION__, strerror(errno));
109 break;
110 }
111 if (FD_ISSET(sock, &rfd)) {
112 alen = sizeof(addr);
113 ret = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &alen);
114 if (ret < 0) {
115 fprintf(stderr, "%s read socket error %s\n", __FUNCTION__, strerror(errno));
116 } else if (ret < MISDN_HEADER_LEN) {
117 fprintf(stderr, "%s read socket shor frame\n", __FUNCTION__);
118 } else {
119 switch(hh->prim) {
120 case MPH_ACTIVATE_IND:
121 case PH_ACTIVATE_IND:
122 if (!l1) {
123 printf("PH_ACTIVATE\n");
124 printf("*** Sync available from interface :-)\n");
125 l1 = 1;
126 }
127 goto again;
128 break;
129 case MPH_DEACTIVATE_IND:
130 case PH_DEACTIVATE_IND:
131 if (l1) {
132 printf("PH_DEACTIVATE\n");
133 printf("*** Lost sync on interface :-(\n");
134 l1 = 0;
135 }
136 goto again;
137 break;
138 case DL_ESTABLISH_IND:
139 case DL_ESTABLISH_CNF:
140 printf("DL_ESTABLISH\n");
141 l2 = 1;
142 goto again;
143 break;
144 case DL_RELEASE_IND:
145 case DL_RELEASE_CNF:
146 printf("DL_RELEASE\n");
147 l2 = 0;
148 goto again;
149 break;
150 case DL_INFORMATION_IND:
151 printf("DL_INFORMATION (tei %d sapi %d)\n", addr.tei, addr.sapi);
152 tei = 1;
153 break;
154 default:
155// printf("prim %x\n", hh->prim);
156 goto again;
157 }
158 }
159 }
160 if (tei && !l2) {
161 hh->prim = DL_ESTABLISH_REQ;
162 printf("-> activating layer 2\n");
163 sendto(sock, buffer, MISDN_HEADER_LEN, 0, (struct sockaddr *) &addr, alen);
164 }
165 }
166}
167
168int main(int argc, char *argv[])
169{
170 int ret;
171
172 if (argc <= 1)
173 {
174 printf("Usage: %s <card>\n\n", argv[0]);
175 printf("Opens given card number in TE-mode PTP and tries to keep layer 2 established.\n");
176 printf("This keeps layer 1 activated to retrieve a steady sync signal from network.\n");
177 return(0);
178 }
179
180 card = atoi(argv[1]);
181
182 init_af_isdn();
183
184 if ((ret = mISDN_open() < 0))
185 return(ret);
186
187 mISDN_handle();
188
189 close(sock);
190
191 return 0;
192}