changeset 35:499d065ee591

new program itt-pcm-br (PCM bridge)
author Mychaela Falconia <falcon@freecalypso.org>
date Wed, 28 Aug 2024 05:00:38 +0000
parents f0b026615f3b
children e4a0b4a61649
files .hgignore pcm-br/Makefile pcm-br/globals.h pcm-br/main.c pcm-br/record_ctrl.c pcm-br/showbuf.c pcm-br/user_cmd.c pcm-br/xconn.c
diffstat 8 files changed, 323 insertions(+), 0 deletions(-) [+]
line wrap: on
line diff
--- a/.hgignore	Tue Aug 13 23:07:24 2024 +0000
+++ b/.hgignore	Wed Aug 28 05:00:38 2024 +0000
@@ -6,3 +6,4 @@
 ^abis/itt-abis-16$
 ^ater/itt-ater-16$
 ^pcm/itt-pcm-one$
+^pcm-br/itt-pcm-br$
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcm-br/Makefile	Wed Aug 28 05:00:38 2024 +0000
@@ -0,0 +1,22 @@
+PROG=	itt-pcm-br
+OBJS=	main.o record_ctrl.o showbuf.o user_cmd.o xconn.o
+LIBUTIL=../libutil/libutil.a
+
+include ../config.defs
+
+CPPFLAGS=${OSMO_INCLUDE}
+OSMO_LINK=${OSMO_LPATH} ${OSMO_RPATH} ${OSMO_LIBS}
+
+all:	${PROG}
+
+${OBJS}:	globals.h
+
+${PROG}: ${OBJS} ${LIBUTIL}
+	${CC} -o $@ ${OBJS} ${LIBUTIL} ${OSMO_LINK}
+
+install:
+	mkdir -p ${DESTDIR}${bindir}
+	install -c -m 755 ${PROG} ${DESTDIR}${bindir}
+
+clean:
+	rm -f *.o ${PROG} errs
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcm-br/globals.h	Wed Aug 28 05:00:38 2024 +0000
@@ -0,0 +1,19 @@
+/* global vars and intermodule-linkage functions in itt-pcm-br */
+
+#pragma once
+
+extern struct osmo_e1dp_client *g_client;
+extern int tsa_fd, tsb_fd;
+extern uint8_t readbuf_a[160], readbuf_b[160];
+extern FILE *rec_file_a, *rec_file_b;
+
+int tsa_fd_cb(struct osmo_fd *ofd, unsigned int what);
+int tsb_fd_cb(struct osmo_fd *ofd, unsigned int what);
+
+void handle_user_cmd(int argc, char **argv);
+void cmd_record_a_start(int argc, char **argv);
+void cmd_record_a_stop(int argc, char **argv);
+void cmd_record_b_start(int argc, char **argv);
+void cmd_record_b_stop(int argc, char **argv);
+void cmd_show_a(int argc, char **argv);
+void cmd_show_b(int argc, char **argv);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcm-br/main.c	Wed Aug 28 05:00:38 2024 +0000
@@ -0,0 +1,87 @@
+/*
+ * This C module is the main for itt-pcm-br, a program in the icE1 TRAU tester
+ * suite that bridges two different timeslots (two TRAU channels) on the A i/f.
+ *
+ * This code is based on osmo-e1d-pipe,
+ * (C) 2020-2022 by Harald Welte <laforge@osmocom.org>,
+ * SPDX-License-Identifier: GPL-2.0+
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <osmocom/core/talloc.h>
+#include <osmocom/core/select.h>
+#include <osmocom/core/application.h>
+#include <osmocom/e1d/proto_clnt.h>
+
+#include "../libutil/open_ts.h"
+#include "../libutil/stdin_handler.h"
+#include "globals.h"
+
+struct osmo_e1dp_client *g_client;
+int tsa_fd, tsb_fd;
+
+static const char *e1d_socket_path = E1DP_DEFAULT_SOCKET;
+static const char *timeslot_spec_a, *timeslot_spec_b;
+static void *g_ctx;
+static struct osmo_fd tsa_ofd, tsb_ofd, stdin_ofd;
+
+static void process_cmdline(int argc, char **argv)
+{
+	extern int optind;
+	extern char *optarg;
+	int c;
+
+	while ((c = getopt(argc, argv, "p:")) != EOF) {
+		switch (c) {
+		case 'p':
+			e1d_socket_path = optarg;
+			continue;
+		default:
+		usage:
+			fprintf(stderr,
+			"usage: %s [-p socket] intf:line:ts intf:line:ts\n",
+				argv[0]);
+			exit(1);
+		}
+	}
+	if (argc != optind + 2)
+		goto usage;
+	timeslot_spec_a = argv[optind];
+	timeslot_spec_b = argv[optind+1];
+}
+
+int main(int argc, char **argv)
+{
+	process_cmdline(argc, argv);
+	g_ctx = talloc_named_const(NULL, 0, "g_ctx");
+	OSMO_ASSERT(g_ctx);
+	osmo_init_logging2(g_ctx, NULL);
+
+	g_client = osmo_e1dp_client_create(g_ctx, e1d_socket_path);
+	if (!g_client) {
+		fprintf(stderr, "error: cannot connect to osmo-e1d at %s\n",
+			e1d_socket_path);
+		exit(1);
+	}
+	tsa_fd = open_e1d_ts(g_client, timeslot_spec_a);
+	tsb_fd = open_e1d_ts(g_client, timeslot_spec_b);
+
+	osmo_fd_setup(&tsa_ofd, tsa_fd, OSMO_FD_READ, tsa_fd_cb, NULL, 0);
+	OSMO_ASSERT(osmo_fd_register(&tsa_ofd) == 0);
+
+	osmo_fd_setup(&tsb_ofd, tsb_fd, OSMO_FD_READ, tsb_fd_cb, NULL, 0);
+	OSMO_ASSERT(osmo_fd_register(&tsb_ofd) == 0);
+
+	osmo_fd_setup(&stdin_ofd, 0, OSMO_FD_READ, stdin_select_cb,
+			handle_user_cmd, 0);
+	OSMO_ASSERT(osmo_fd_register(&stdin_ofd) == 0);
+
+	while (1) {
+		osmo_select_main(0);
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcm-br/record_ctrl.c	Wed Aug 28 05:00:38 2024 +0000
@@ -0,0 +1,63 @@
+/*
+ * Here we implement stdin commands that control recording of E1 timeslot
+ * read stream.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <osmocom/core/select.h>
+
+#include "globals.h"
+
+void cmd_record_a_start(int argc, char **argv)
+{
+	if (argc != 2) {
+		printf("error: record-a command needs 1 argument\n");
+		return;
+	}
+	if (rec_file_a) {
+		printf("error: recording of ts A already in progress\n");
+		return;
+	}
+	rec_file_a = fopen(argv[1], "w");
+	if (!rec_file_a)
+		perror(argv[1]);
+}
+
+void cmd_record_a_stop(int argc, char **argv)
+{
+	if (!rec_file_a) {
+		printf("error: no recording of ts A in progress\n");
+		return;
+	}
+	fclose(rec_file_a);
+	rec_file_a = NULL;
+}
+
+void cmd_record_b_start(int argc, char **argv)
+{
+	if (argc != 2) {
+		printf("error: record-b command needs 1 argument\n");
+		return;
+	}
+	if (rec_file_b) {
+		printf("error: recording of ts B already in progress\n");
+		return;
+	}
+	rec_file_b = fopen(argv[1], "w");
+	if (!rec_file_b)
+		perror(argv[1]);
+}
+
+void cmd_record_b_stop(int argc, char **argv)
+{
+	if (!rec_file_b) {
+		printf("error: no recording of ts B in progress\n");
+		return;
+	}
+	fclose(rec_file_b);
+	rec_file_b = NULL;
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcm-br/showbuf.c	Wed Aug 28 05:00:38 2024 +0000
@@ -0,0 +1,37 @@
+/*
+ * Here we implement stdin commands that display current instantaneous
+ * state of each read channel.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <osmocom/core/select.h>
+
+#include "globals.h"
+
+void cmd_show_a(int argc, char **argv)
+{
+	int i, j, off;
+
+	off = 0;
+	for (i = 0; i < 10; i++) {
+		for (j = 0; j < 16; j++)
+			printf(" %02X", readbuf_a[off++]);
+		putchar('\n');
+	}
+}
+
+void cmd_show_b(int argc, char **argv)
+{
+	int i, j, off;
+
+	off = 0;
+	for (i = 0; i < 10; i++) {
+		for (j = 0; j < 16; j++)
+			printf(" %02X", readbuf_b[off++]);
+		putchar('\n');
+	}
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcm-br/user_cmd.c	Wed Aug 28 05:00:38 2024 +0000
@@ -0,0 +1,42 @@
+/*
+ * In this module we handle user-issued stdin commands during
+ * itt-pcm-br running session.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+
+#include <osmocom/core/select.h>
+
+#include "globals.h"
+
+static struct cmdtab {
+	char	*cmd;
+	void	(*func)(int argc, char **argv);
+} cmdtab[] = {
+	{"record-a", cmd_record_a_start},
+	{"record-a-stop", cmd_record_a_stop},
+	{"record-b", cmd_record_b_start},
+	{"record-b-stop", cmd_record_b_stop},
+	{"show-a", cmd_show_a},
+	{"show-b", cmd_show_b},
+	/* table search terminator */
+	{NULL, NULL}
+};
+
+void handle_user_cmd(int argc, char **argv)
+{
+	struct cmdtab *tp;
+
+	for (tp = cmdtab; tp->cmd; tp++)
+		if (!strcmp(tp->cmd, argv[0]))
+			break;
+	if (!tp->func) {
+		printf("error: unknown or unimplemented command\n");
+		return;
+	}
+	tp->func(argc, argv);
+}
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/pcm-br/xconn.c	Wed Aug 28 05:00:38 2024 +0000
@@ -0,0 +1,52 @@
+/*
+ * The two functions in this module get called from Osmocom select loop
+ * whenever each timeslot data socket to osmo-e1d is ready for reading;
+ * the cross-connect of the two timeslots is implemented here.
+ */
+
+#include <stdint.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+#include <osmocom/core/select.h>
+
+#include "globals.h"
+
+uint8_t readbuf_a[160], readbuf_b[160];
+FILE *rec_file_a, *rec_file_b;
+
+int tsa_fd_cb(struct osmo_fd *ofd, unsigned int what)
+{
+	int rc;
+
+	rc = read(tsa_fd, readbuf_a, 160);
+	if (rc != 160) {
+		fprintf(stderr,
+			"error: read from ts A returned %d instead of 160\n",
+			rc);
+		exit(1);
+	}
+	if (rec_file_a)
+		fwrite(readbuf_a, 1, 160, rec_file_a);
+	write(tsb_fd, readbuf_a, 160);
+	return 0;
+}
+
+int tsb_fd_cb(struct osmo_fd *ofd, unsigned int what)
+{
+	int rc;
+
+	rc = read(tsb_fd, readbuf_b, 160);
+	if (rc != 160) {
+		fprintf(stderr,
+			"error: read from ts B returned %d instead of 160\n",
+			rc);
+		exit(1);
+	}
+	if (rec_file_b)
+		fwrite(readbuf_b, 1, 160, rec_file_b);
+	write(tsa_fd, readbuf_b, 160);
+	return 0;
+}