view rvinterf/asyncshell/tchplay.c @ 964:a96cb97b66a2

ringtools/imy: fix duplicate definition of tdma_durations[] The bug was reported by Vadim Yanitskiy <fixeria@osmocom.org>, although the present fix is slightly different from the contributed patch: because main.c doesn't need this tdma_durations[] array at all, let's simply remove the reference to this array from main.c rather than turn it into an extern. I no longer remember my original thought flow that resulted (by mistake) in tdma_durations[] being multiply defined in main.c and durations.c. My intent might have been to define all globals in main.c and have the reference in durations.c be an extern - and I missed that extern - but without clear memory, I have no certainty. In any case, having this data array defined in the same module that fills it (durations.c) is sensible, so let's make it the new way.
author Mychaela Falconia <falcon@freecalypso.org>
date Thu, 31 Aug 2023 19:38:18 +0000
parents 971906d7763d
children
line wrap: on
line source

/*
 * TCH uplink play-from-file functionality
 */

#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include "pktmux.h"
#include "tch_feature.h"

extern u_char rvi_msg[];
extern int rvi_msg_len;

extern void async_msg_output();

static FILE *play_file;
static int queued_frames;

#define	QUEUE_LIMIT	3

static void
sync_msgout(msg)
	char *msg;
{
	printf("%s\n", msg);
}

static
decode_hex_digit(ch)
{
	if (isdigit(ch))
		return(ch - '0');
	else if (isupper(ch))
		return(ch - 'A' + 10);
	else
		return(ch - 'a' + 10);
}

static
decode_hex_line(line, bytes)
	char *line;
	u_char *bytes;
{
	int i;

	for (i = 0; i < 33; i++) {
		if (!isxdigit(line[0]) || !isxdigit(line[1]))
			return(-1);
		bytes[i] = (decode_hex_digit(line[0]) << 4) |
				decode_hex_digit(line[1]);
		line += 2;
	}
	for (; *line; line++)
		if (!isspace(*line))
			return(-1);
	return(0);
}

static void
fill_uplink(msgout)
	void (*msgout)();
{
	char line[80];
	u_char sendpkt[35];
	int cc;

	sendpkt[0] = RVT_TCH_HEADER;
	sendpkt[1] = TCH_ULBITS_REQ;
	while (queued_frames < QUEUE_LIMIT) {
		if (!fgets(line, sizeof line, play_file)) {
			msgout("TCH UL: file play finished");
			fclose(play_file);
			play_file = 0;
			return;
		}
		if (decode_hex_line(line, sendpkt + 2) < 0) {
			msgout("TCH UL: bad file input, play aborted");
			fclose(play_file);
			play_file = 0;
			return;
		}
		send_pkt_to_target(sendpkt, 35);
		queued_frames++;
	}
}

void
tch_ulbits_conf()
{
	if (queued_frames > 0)
		queued_frames--;
	if (play_file)
		fill_uplink(async_msg_output);
}

static void
cmd_tch_play_start(filename)
	char *filename;
{
	if (play_file) {
		printf("error: tch play session already in progress\n");
		return;
	}
	play_file = fopen(filename, "r");
	if (!play_file) {
		perror(filename);
		return;
	}
	printf("Starting TCH UL play from file\n");
	tch_rx_control(1);
	fill_uplink(sync_msgout);
}

static void
cmd_tch_play_stop()
{
	if (!play_file) {
		printf("error: no tch play session in progress\n");
		return;
	}
	fclose(play_file);
	play_file = 0;
	printf("TCH UL play from file terminated\n");
}

void
cmd_tch_play(argc, argv)
	char **argv;
{
	if (argc < 2) {
		printf("error: too few arguments\n");
		return;
	}
	if (strcmp(argv[1], "stop"))
		cmd_tch_play_start(argv[1]);
	else
		cmd_tch_play_stop();
}

void
show_tch_play_status()
{
	printf("TCH UL play from file: %s\n",
		play_file ? "RUNNING" : "not running");
	printf("Outstanding UL frames: %d\n", queued_frames);
}