/* isdnsync.c
 *
 * Author       Andreas Eversberg <jolly@eversberg.eu>
 *
 * All rights reserved
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program; if not, write to the Free Software Foundation, Inc.,
 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/socket.h>
#include "mISDNif.h"
#define MISDN_OLD_AF_COMPATIBILITY
#define AF_COMPATIBILITY_FUNC
#include "compat_af_isdn.h"

int card = 0;
int sock = -1;

int mISDN_open(void)
{
	int			fd, ret;
	struct mISDN_devinfo	devinfo;
	struct sockaddr_mISDN	l2addr;

	fd = socket(PF_ISDN, SOCK_RAW, ISDN_P_BASE);
	if (fd < 0) {
		fprintf(stderr, "could not open socket (%s)\n", strerror(errno));
		return fd;
	}
	devinfo.id = card;
	ret = ioctl(fd, IMGETDEVINFO, &devinfo);
	if (ret < 0) {
		fprintf(stderr,"could not send IOCTL IMGETCOUNT (%s)\n", strerror(errno));
		close(fd);
		return ret;
	}
	close(fd);
	if (!(devinfo.Dprotocols & (1 << ISDN_P_TE_S0))
	 && !(devinfo.Dprotocols & (1 << ISDN_P_TE_E1))) {
		fprintf(stderr,"Interface does not support TE mode (%s)\n", strerror(errno));
		close(fd);
		return ret;
	}
	fd = socket(PF_ISDN, SOCK_DGRAM, ISDN_P_LAPD_TE);
	if (fd < 0) {
		fprintf(stderr,"could not open ISDN_P_LAPD_TE socket (%s)\n", strerror(errno));
		return fd;
	}
	l2addr.family = AF_ISDN;
	l2addr.dev = card;
	l2addr.channel = 0;
	l2addr.sapi = 0;
	l2addr.tei = 0;
	ret = bind(fd, (struct sockaddr *)&l2addr, sizeof(l2addr));
	if (ret < 0) {
		fprintf(stderr,"could not bind socket for card %d (%s)\n", card, strerror(errno));
		close(fd);
		return ret;
	}
	sock = fd;

	return sock;
}


void mISDN_handle(void)
{
	int ret;
	fd_set rfd;
	struct timeval tv;
	struct sockaddr_mISDN addr;
	socklen_t alen;
	unsigned char buffer[2048];
	struct mISDNhead *hh = (struct mISDNhead *)buffer;
	int l1 = 0, l2 = 0, tei = 0;

	while(1) {
again:
		FD_ZERO(&rfd);
		FD_SET(sock, &rfd);
		tv.tv_sec = 2;
		tv.tv_usec = 0;
		ret = select(sock+1, &rfd, NULL, NULL, &tv);
		if (ret < 0) {
			if (errno == EINTR)
				continue;
			fprintf(stderr, "%s aborted: %s\n", __FUNCTION__, strerror(errno));
			break;
		}
		if (FD_ISSET(sock, &rfd)) {
			alen = sizeof(addr);
			ret = recvfrom(sock, buffer, sizeof(buffer), 0, (struct sockaddr *) &addr, &alen);
			if (ret < 0) {
				fprintf(stderr, "%s read socket error %s\n", __FUNCTION__, strerror(errno));
			} else if (ret < MISDN_HEADER_LEN) {
					fprintf(stderr, "%s read socket shor frame\n", __FUNCTION__);
			} else {
				switch(hh->prim) {
					case MPH_ACTIVATE_IND:
					case PH_ACTIVATE_IND:
						if (!l1) {
							printf("PH_ACTIVATE\n");
							printf("*** Sync available from interface :-)\n");
							l1 = 1;
						}
						goto again;
					break;
					case MPH_DEACTIVATE_IND:
					case PH_DEACTIVATE_IND:
						if (l1) {
							printf("PH_DEACTIVATE\n");
							printf("*** Lost sync on interface        :-(\n");
							l1 = 0;
						}
						goto again;
					break;
					case DL_ESTABLISH_IND:
					case DL_ESTABLISH_CNF:
						printf("DL_ESTABLISH\n");
						l2 = 1;
						goto again;
					break;
					case DL_RELEASE_IND:
					case DL_RELEASE_CNF:
						printf("DL_RELEASE\n");
						l2 = 0;
						goto again;
					break;
					case DL_INFORMATION_IND:
						printf("DL_INFORMATION (tei %d sapi %d)\n", addr.tei, addr.sapi);
						tei = 1;
					break;
					default:
//						printf("prim %x\n", hh->prim);
						goto again;
				}
			}
		}
		if (tei && !l2) {
			hh->prim = DL_ESTABLISH_REQ;
			printf("-> activating layer 2\n");
			sendto(sock, buffer, MISDN_HEADER_LEN, 0, (struct sockaddr *) &addr, alen);
		}
	}
}

int main(int argc, char *argv[])
{
	int ret;

	if (argc <= 1)
	{
		printf("Usage: %s <card>\n\n", argv[0]);
		printf("Opens given card number in TE-mode PTP and tries to keep layer 2 established.\n");
		printf("This keeps layer 1 activated to retrieve a steady sync signal from network.\n");
		return(0);
	}

	card = atoi(argv[1]);

	init_af_isdn();

	if ((ret = mISDN_open() < 0))
		return(ret);

	mISDN_handle();

	close(sock);

	return 0;
}
