From 17287576555a5c46fa23549e2e5f073660dccb70 Mon Sep 17 00:00:00 2001 From: Ralf Baechle Date: Wed, 21 Apr 1999 09:51:03 +0200 Subject: Import ax25-tools 0.0.1 from tarball --- hdlcutil/Makefile.am | 31 ++ hdlcutil/Makefile.in | 403 ++++++++++++++++++++++++++ hdlcutil/hdrvcomm.c | 663 ++++++++++++++++++++++++++++++++++++++++++ hdlcutil/hdrvcomm.h | 109 +++++++ hdlcutil/setcrystal.c | 136 +++++++++ hdlcutil/sethdlc.c | 598 ++++++++++++++++++++++++++++++++++++++ hdlcutil/smdiag.c | 434 ++++++++++++++++++++++++++++ hdlcutil/smmixer.c | 781 ++++++++++++++++++++++++++++++++++++++++++++++++++ hdlcutil/usersmdiag.h | 118 ++++++++ 9 files changed, 3273 insertions(+) create mode 100644 hdlcutil/Makefile.am create mode 100644 hdlcutil/Makefile.in create mode 100644 hdlcutil/hdrvcomm.c create mode 100644 hdlcutil/hdrvcomm.h create mode 100644 hdlcutil/setcrystal.c create mode 100644 hdlcutil/sethdlc.c create mode 100644 hdlcutil/smdiag.c create mode 100644 hdlcutil/smmixer.c create mode 100644 hdlcutil/usersmdiag.h (limited to 'hdlcutil') diff --git a/hdlcutil/Makefile.am b/hdlcutil/Makefile.am new file mode 100644 index 0000000..32059d1 --- /dev/null +++ b/hdlcutil/Makefile.am @@ -0,0 +1,31 @@ + +installconf: + +sbin_PROGRAMS = setcrystal sethdlc smmixer smdiag + +man_MANS = sethdlc.8 smdiag.8 smmixer.8 baycom.9 hdlcdrv.9 soundmodem.9 + +setcrystal_SOURCES = \ + setcrystal.c + +sethdlc_SOURCES = \ + sethdlc.c \ + hdrvcomm.c \ + hdrvcomm.h \ + usersmdiag.h + +smmixer_SOURCES = \ + smmixer.c \ + hdrvcomm.c \ + hdrvcomm.h \ + usersmdiag.h + +smdiag_SOURCES = \ + smdiag.c \ + hdrvcomm.c \ + hdrvcomm.h \ + usersmdiag.h + +smdiag_LDADD = \ + $(X_LIBS) \ + -lX11 diff --git a/hdlcutil/Makefile.in b/hdlcutil/Makefile.in new file mode 100644 index 0000000..edf7170 --- /dev/null +++ b/hdlcutil/Makefile.in @@ -0,0 +1,403 @@ +# Makefile.in generated automatically by automake 1.4 from Makefile.am + +# Copyright (C) 1994, 1995-8, 1999 Free Software Foundation, Inc. +# This Makefile.in is free software; the Free Software Foundation +# gives unlimited permission to copy and/or distribute it, +# with or without modifications, as long as this notice is preserved. + +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY, to the extent permitted by law; without +# even the implied warranty of MERCHANTABILITY or FITNESS FOR A +# PARTICULAR PURPOSE. + + +SHELL = @SHELL@ + +srcdir = @srcdir@ +top_srcdir = @top_srcdir@ +VPATH = @srcdir@ +prefix = @prefix@ +exec_prefix = @exec_prefix@ + +bindir = @bindir@ +sbindir = @sbindir@ +libexecdir = @libexecdir@ +datadir = @datadir@ +sysconfdir = @sysconfdir@ +sharedstatedir = @sharedstatedir@ +localstatedir = @localstatedir@ +libdir = @libdir@ +infodir = @infodir@ +mandir = @mandir@ +includedir = @includedir@ +oldincludedir = /usr/include + +DESTDIR = + +pkgdatadir = $(datadir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ + +top_builddir = .. + +ACLOCAL = @ACLOCAL@ +AUTOCONF = @AUTOCONF@ +AUTOMAKE = @AUTOMAKE@ +AUTOHEADER = @AUTOHEADER@ + +INSTALL = @INSTALL@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ $(AM_INSTALL_PROGRAM_FLAGS) +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +transform = @program_transform_name@ + +NORMAL_INSTALL = : +PRE_INSTALL = : +POST_INSTALL = : +NORMAL_UNINSTALL = : +PRE_UNINSTALL = : +POST_UNINSTALL = : +AWK = @AWK@ +CC = @CC@ +MAKEINFO = @MAKEINFO@ +NCURSES_LIB = @NCURSES_LIB@ +PACKAGE = @PACKAGE@ +VERSION = @VERSION@ + +sbin_PROGRAMS = setcrystal sethdlc smmixer smdiag + +man_MANS = sethdlc.8 smdiag.8 smmixer.8 baycom.9 hdlcdrv.9 soundmodem.9 + +setcrystal_SOURCES = setcrystal.c + + +sethdlc_SOURCES = sethdlc.c hdrvcomm.c hdrvcomm.h usersmdiag.h + + +smmixer_SOURCES = smmixer.c hdrvcomm.c hdrvcomm.h usersmdiag.h + + +smdiag_SOURCES = smdiag.c hdrvcomm.c hdrvcomm.h usersmdiag.h + + +smdiag_LDADD = $(X_LIBS) -lX11 + +mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs +CONFIG_HEADER = ../config.h +CONFIG_CLEAN_FILES = +PROGRAMS = $(sbin_PROGRAMS) + + +DEFS = @DEFS@ -I. -I$(srcdir) -I.. +CPPFLAGS = @CPPFLAGS@ +LDFLAGS = @LDFLAGS@ +LIBS = @LIBS@ +X_CFLAGS = @X_CFLAGS@ +X_LIBS = @X_LIBS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +setcrystal_OBJECTS = setcrystal.o +setcrystal_LDADD = $(LDADD) +setcrystal_DEPENDENCIES = +setcrystal_LDFLAGS = +sethdlc_OBJECTS = sethdlc.o hdrvcomm.o +sethdlc_LDADD = $(LDADD) +sethdlc_DEPENDENCIES = +sethdlc_LDFLAGS = +smmixer_OBJECTS = smmixer.o hdrvcomm.o +smmixer_LDADD = $(LDADD) +smmixer_DEPENDENCIES = +smmixer_LDFLAGS = +smdiag_OBJECTS = smdiag.o hdrvcomm.o +smdiag_DEPENDENCIES = +smdiag_LDFLAGS = +CFLAGS = @CFLAGS@ +COMPILE = $(CC) $(DEFS) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +CCLD = $(CC) +LINK = $(CCLD) $(AM_CFLAGS) $(CFLAGS) $(LDFLAGS) -o $@ +man8dir = $(mandir)/man8 +man9dir = $(mandir)/man9 +MANS = $(man_MANS) + +NROFF = nroff +DIST_COMMON = Makefile.am Makefile.in + + +DISTFILES = $(DIST_COMMON) $(SOURCES) $(HEADERS) $(TEXINFOS) $(EXTRA_DIST) + +TAR = tar +GZIP_ENV = --best +SOURCES = $(setcrystal_SOURCES) $(sethdlc_SOURCES) $(smmixer_SOURCES) $(smdiag_SOURCES) +OBJECTS = $(setcrystal_OBJECTS) $(sethdlc_OBJECTS) $(smmixer_OBJECTS) $(smdiag_OBJECTS) + +all: all-redirect +.SUFFIXES: +.SUFFIXES: .S .c .o .s +$(srcdir)/Makefile.in: Makefile.am $(top_srcdir)/configure.in $(ACLOCAL_M4) + cd $(top_srcdir) && $(AUTOMAKE) --gnu --include-deps hdlcutil/Makefile + +Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status + cd $(top_builddir) \ + && CONFIG_FILES=$(subdir)/$@ CONFIG_HEADERS= $(SHELL) ./config.status + + +mostlyclean-sbinPROGRAMS: + +clean-sbinPROGRAMS: + -test -z "$(sbin_PROGRAMS)" || rm -f $(sbin_PROGRAMS) + +distclean-sbinPROGRAMS: + +maintainer-clean-sbinPROGRAMS: + +install-sbinPROGRAMS: $(sbin_PROGRAMS) + @$(NORMAL_INSTALL) + $(mkinstalldirs) $(DESTDIR)$(sbindir) + @list='$(sbin_PROGRAMS)'; for p in $$list; do \ + if test -f $$p; then \ + echo " $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`"; \ + $(INSTALL_PROGRAM) $$p $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + else :; fi; \ + done + +uninstall-sbinPROGRAMS: + @$(NORMAL_UNINSTALL) + list='$(sbin_PROGRAMS)'; for p in $$list; do \ + rm -f $(DESTDIR)$(sbindir)/`echo $$p|sed 's/$(EXEEXT)$$//'|sed '$(transform)'|sed 's/$$/$(EXEEXT)/'`; \ + done + +.c.o: + $(COMPILE) -c $< + +.s.o: + $(COMPILE) -c $< + +.S.o: + $(COMPILE) -c $< + +mostlyclean-compile: + -rm -f *.o core *.core + +clean-compile: + +distclean-compile: + -rm -f *.tab.c + +maintainer-clean-compile: + +setcrystal: $(setcrystal_OBJECTS) $(setcrystal_DEPENDENCIES) + @rm -f setcrystal + $(LINK) $(setcrystal_LDFLAGS) $(setcrystal_OBJECTS) $(setcrystal_LDADD) $(LIBS) + +sethdlc: $(sethdlc_OBJECTS) $(sethdlc_DEPENDENCIES) + @rm -f sethdlc + $(LINK) $(sethdlc_LDFLAGS) $(sethdlc_OBJECTS) $(sethdlc_LDADD) $(LIBS) + +smmixer: $(smmixer_OBJECTS) $(smmixer_DEPENDENCIES) + @rm -f smmixer + $(LINK) $(smmixer_LDFLAGS) $(smmixer_OBJECTS) $(smmixer_LDADD) $(LIBS) + +smdiag: $(smdiag_OBJECTS) $(smdiag_DEPENDENCIES) + @rm -f smdiag + $(LINK) $(smdiag_LDFLAGS) $(smdiag_OBJECTS) $(smdiag_LDADD) $(LIBS) + +install-man8: + $(mkinstalldirs) $(DESTDIR)$(man8dir) + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man8dir)/$$inst; \ + done + +uninstall-man8: + @list='$(man8_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.8*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man8dir)/$$inst"; \ + rm -f $(DESTDIR)$(man8dir)/$$inst; \ + done + +install-man9: + $(mkinstalldirs) $(DESTDIR)$(man9dir) + @list='$(man9_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.9*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + if test -f $(srcdir)/$$i; then file=$(srcdir)/$$i; \ + else file=$$i; fi; \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " $(INSTALL_DATA) $$file $(DESTDIR)$(man9dir)/$$inst"; \ + $(INSTALL_DATA) $$file $(DESTDIR)$(man9dir)/$$inst; \ + done + +uninstall-man9: + @list='$(man9_MANS)'; \ + l2='$(man_MANS)'; for i in $$l2; do \ + case "$$i" in \ + *.9*) list="$$list $$i" ;; \ + esac; \ + done; \ + for i in $$list; do \ + ext=`echo $$i | sed -e 's/^.*\\.//'`; \ + inst=`echo $$i | sed -e 's/\\.[0-9a-z]*$$//'`; \ + inst=`echo $$inst | sed '$(transform)'`.$$ext; \ + echo " rm -f $(DESTDIR)$(man9dir)/$$inst"; \ + rm -f $(DESTDIR)$(man9dir)/$$inst; \ + done +install-man: $(MANS) + @$(NORMAL_INSTALL) + $(MAKE) $(AM_MAKEFLAGS) install-man8 install-man9 +uninstall-man: + @$(NORMAL_UNINSTALL) + $(MAKE) $(AM_MAKEFLAGS) uninstall-man8 uninstall-man9 + +tags: TAGS + +ID: $(HEADERS) $(SOURCES) $(LISP) + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + here=`pwd` && cd $(srcdir) \ + && mkid -f$$here/ID $$unique $(LISP) + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) $(LISP) + tags=; \ + here=`pwd`; \ + list='$(SOURCES) $(HEADERS)'; \ + unique=`for i in $$list; do echo $$i; done | \ + awk ' { files[$$0] = 1; } \ + END { for (i in files) print i; }'`; \ + test -z "$(ETAGS_ARGS)$$unique$(LISP)$$tags" \ + || (cd $(srcdir) && etags $(ETAGS_ARGS) $$tags $$unique $(LISP) -o $$here/TAGS) + +mostlyclean-tags: + +clean-tags: + +distclean-tags: + -rm -f TAGS ID + +maintainer-clean-tags: + +distdir = $(top_builddir)/$(PACKAGE)-$(VERSION)/$(subdir) + +subdir = hdlcutil + +distdir: $(DISTFILES) + @for file in $(DISTFILES); do \ + d=$(srcdir); \ + if test -d $$d/$$file; then \ + cp -pr $$/$$file $(distdir)/$$file; \ + else \ + test -f $(distdir)/$$file \ + || ln $$d/$$file $(distdir)/$$file 2> /dev/null \ + || cp -p $$d/$$file $(distdir)/$$file || :; \ + fi; \ + done +hdrvcomm.o: hdrvcomm.c hdrvcomm.h usersmdiag.h +setcrystal.o: setcrystal.c +sethdlc.o: sethdlc.c hdrvcomm.h +smdiag.o: smdiag.c hdrvcomm.h +smmixer.o: smmixer.c hdrvcomm.h + +info-am: +info: info-am +dvi-am: +dvi: dvi-am +check-am: all-am +check: check-am +installcheck-am: +installcheck: installcheck-am +install-exec-am: install-sbinPROGRAMS +install-exec: install-exec-am + +install-data-am: install-man +install-data: install-data-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am +install: install-am +uninstall-am: uninstall-sbinPROGRAMS uninstall-man +uninstall: uninstall-am +all-am: Makefile $(PROGRAMS) $(MANS) +all-redirect: all-am +install-strip: + $(MAKE) $(AM_MAKEFLAGS) AM_INSTALL_PROGRAM_FLAGS=-s install +installdirs: + $(mkinstalldirs) $(DESTDIR)$(sbindir) $(DESTDIR)$(mandir)/man8 \ + $(DESTDIR)$(mandir)/man9 + + +mostlyclean-generic: + +clean-generic: + +distclean-generic: + -rm -f Makefile $(CONFIG_CLEAN_FILES) + -rm -f config.cache config.log stamp-h stamp-h[0-9]* + +maintainer-clean-generic: +mostlyclean-am: mostlyclean-sbinPROGRAMS mostlyclean-compile \ + mostlyclean-tags mostlyclean-generic + +mostlyclean: mostlyclean-am + +clean-am: clean-sbinPROGRAMS clean-compile clean-tags clean-generic \ + mostlyclean-am + +clean: clean-am + +distclean-am: distclean-sbinPROGRAMS distclean-compile distclean-tags \ + distclean-generic clean-am + +distclean: distclean-am + +maintainer-clean-am: maintainer-clean-sbinPROGRAMS \ + maintainer-clean-compile maintainer-clean-tags \ + maintainer-clean-generic distclean-am + @echo "This command is intended for maintainers to use;" + @echo "it deletes files that may require special tools to rebuild." + +maintainer-clean: maintainer-clean-am + +.PHONY: mostlyclean-sbinPROGRAMS distclean-sbinPROGRAMS \ +clean-sbinPROGRAMS maintainer-clean-sbinPROGRAMS uninstall-sbinPROGRAMS \ +install-sbinPROGRAMS mostlyclean-compile distclean-compile \ +clean-compile maintainer-clean-compile install-man8 uninstall-man8 \ +install-man9 uninstall-man9 install-man uninstall-man tags \ +mostlyclean-tags distclean-tags clean-tags maintainer-clean-tags \ +distdir info-am info dvi-am dvi check check-am installcheck-am \ +installcheck install-exec-am install-exec install-data-am install-data \ +install-am install uninstall-am uninstall all-redirect all-am all \ +installdirs mostlyclean-generic distclean-generic clean-generic \ +maintainer-clean-generic clean mostlyclean distclean maintainer-clean + + +installconf: + +# Tell versions [3.59,3.63) of GNU make to not export all variables. +# Otherwise a system limit (for SysV at least) may be exceeded. +.NOEXPORT: diff --git a/hdlcutil/hdrvcomm.c b/hdlcutil/hdrvcomm.c new file mode 100644 index 0000000..55f0f38 --- /dev/null +++ b/hdlcutil/hdrvcomm.c @@ -0,0 +1,663 @@ +/*****************************************************************************/ + +/* + * hdrvcomm.c -- HDLC driver communications. + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + * + * History: + * 0.1 10.5.97 Started + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include +#include "hdrvcomm.h" +#include "usersmdiag.h" + +#include +/* ---------------------------------------------------------------------- */ + +#ifdef HDRVC_KERNEL +static int kernel_mode = 1; +#endif /* HDRVC_KERNEL */ +static char *if_name = "bc0"; +static char *prg_name; +static int fd = -1; +static struct ifreq ifr_h; +static int promisc = 0; +static int msqid = -1; + +/* ---------------------------------------------------------------------- */ + +static void terminate(void) +{ +#ifdef HDRVC_KERNEL + if (kernel_mode) { + if (ioctl(fd, SIOCSIFFLAGS, &ifr_h) < 0) { + perror("ioctl (SIOCSIFFLAGS)"); + exit(1); + } + } +#endif /* HDRVC_KERNEL */ + exit(0); +} + +/* ---------------------------------------------------------------------- */ + +static void terminate_sig(int signal) +{ + printf("signal %i caught\n", signal); + terminate(); +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_recvpacket(char *pkt, int maxlen) +{ + struct ifreq ifr_new; + struct sockaddr from; + int from_len = sizeof(from); + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + if (!promisc) { + struct sockaddr sa; + + strcpy(sa.sa_data, if_name); + sa.sa_family = AF_INET; + if (bind(fd, &sa, sizeof(struct sockaddr)) < 0) { + fprintf(stderr, "%s: Error %s (%i) bind failed\n", + prg_name, strerror(errno), errno); + exit(-2); + } + ifr_new = ifr_h; + ifr_new.ifr_flags |= IFF_PROMISC; + if (ioctl(fd, SIOCSIFFLAGS, &ifr_new) < 0) { + perror("ioctl (SIOCSIFFLAGS)"); + exit(1); + } + signal(SIGTERM, terminate_sig); + signal(SIGQUIT, terminate_sig); + if (atexit((void (*)(void))terminate)) { + perror("atexit"); + terminate(); + } + promisc = 1; + fcntl(fd, F_SETFL, fcntl(fd, F_GETFL, 0) | O_NONBLOCK); + } + if (!pkt || maxlen < 2) + return 0; + return recvfrom(fd, pkt, maxlen, 0, &from, &from_len); + } +#endif /* HDRVC_KERNEL */ + return -1; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_getfd(void) +{ + return fd; +} + +/* ---------------------------------------------------------------------- */ + +char *hdrvc_ifname(void) +{ + return if_name; +} + +/* ---------------------------------------------------------------------- */ + +void hdrvc_args(int *argc, char *argv[], char *def_if) +{ + int ac, i; + + if (def_if) + if_name = def_if; + if (!argc || !argv || (ac = *argc) < 1) + return; + prg_name = argv[0]; + for (i = 1; i < ac-1; i++) { +#ifdef HDRVC_KERNEL + if (!strcmp(argv[i], "-i")) { + kernel_mode = 1; + if_name = argv[i+1]; + ac -= 2; + if (i < ac) + memmove(argv+i, argv+i+2, (ac-i) * sizeof(void *)); + i--; + } else +#endif /* HDRVC_KERNEL */ + if (!strcmp(argv[i], "-u")) { +#ifdef HDRVC_KERNEL + kernel_mode = 0; +#endif /* HDRVC_KERNEL */ + if_name = argv[i+1]; + ac -= 2; + if (i < ac) + memmove(argv+i, argv+i+2, (ac-i) * sizeof(void *)); + i--; + } + } + *argc = ac; +} + +/* ---------------------------------------------------------------------- */ + +void hdrvc_init(void) +{ +#ifdef HDRVC_KERNEL + if (kernel_mode) { + if ((fd = socket(PF_INET, SOCK_PACKET, htons(ETH_P_AX25))) < 0) { + fprintf(stderr, "%s: Error %s (%i), cannot open %s\n", prg_name, + strerror(errno), errno, if_name); + exit(-1); + } + strcpy(ifr_h.ifr_name, if_name); + if (ioctl(fd, SIOCGIFFLAGS, &ifr_h) < 0) { + fprintf(stderr, "%s: Error %s (%i), cannot ioctl %s\n", prg_name, + strerror(errno), errno, if_name); + exit(-1); + } + } else +#endif /* HDRVC_KERNEL */ + { + key_t k = ftok(if_name, USERSM_KEY_PROJ); + + if (k == (key_t)-1) { + fprintf(stderr, "%s: Error %s (%i), cannot ftok on %s\n", prg_name, + strerror(errno), errno, if_name); + exit(-1); + } + if ((msqid = msgget(k, 0700)) < 0) { + fprintf(stderr, "%s: Error %s (%i), cannot msgget %d\n", prg_name, + strerror(errno), errno, k); + exit(-1); + } + } +} + +/* ---------------------------------------------------------------------- */ + +extern __inline__ void hdrvc_sendmsg(struct usersmmsg *msg, int len) +{ + if (msgsnd(msqid, (struct msgbuf *)msg, len+sizeof(msg->hdr)-sizeof(long), 0) < 0) { + perror("msgsnd"); + exit(1); + } +} + +extern __inline__ int hdrvc_recvmsg(struct usersmmsg *msg, int maxlen, long type) +{ + int len; + + if ((len = msgrcv(msqid, (struct msgbuf *)msg, maxlen-sizeof(long), type, MSG_NOERROR)) < 0) { + perror("msgrcv"); + exit(1); + } +#if 0 + for (;;) { + if ((len = msgrcv(msqid, (struct msgbuf *)msg, maxlen-sizeof(long), type, IPC_NOWAIT|MSG_NOERROR)) >= 0) + return len+sizeof(long); + if (errno != ENOMSG) { + perror("msgrcv"); + exit(1); + } + usleep(250000); + } +#endif + return len+sizeof(long); +} + +/* ---------------------------------------------------------------------- */ + +#ifdef HDRVC_KERNEL + +int hdrvc_hdlcdrv_ioctl(int cmd, struct hdlcdrv_ioctl *par) +{ + struct ifreq ifr = ifr_h; + + if (!kernel_mode) { + errno = EINVAL; + return -1; + } + ifr.ifr_data = (caddr_t)par; + par->cmd = cmd; + return ioctl(fd, SIOCDEVPRIVATE, &ifr); +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_sm_ioctl(int cmd, struct sm_ioctl *par) +{ + struct ifreq ifr = ifr_h; + + if (!kernel_mode) { + errno = EINVAL; + return -1; + } + ifr.ifr_data = (caddr_t)par; + par->cmd = cmd; + return ioctl(fd, SIOCDEVPRIVATE, &ifr); +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_baycom_ioctl(int cmd, struct baycom_ioctl *par) +{ + struct ifreq ifr = ifr_h; + + if (!kernel_mode) { + errno = EINVAL; + return -1; + } + ifr.ifr_data = (caddr_t)par; + par->cmd = cmd; + return ioctl(fd, SIOCDEVPRIVATE, &ifr); +} + +/* ---------------------------------------------------------------------- */ + +unsigned int hdrvc_get_ifflags(void) +{ + struct ifreq ifr; + + if (kernel_mode) { + memcpy(&ifr, &ifr_h, sizeof(ifr)); + if (ioctl(fd, SIOCGIFFLAGS, &ifr) < 0) { + perror("ioctl: SIOCGIFFLAGS"); + exit(-1); + } + return ifr.ifr_flags; + } + return IFF_UP | IFF_RUNNING; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_diag(struct sm_diag_data *diag) +{ + struct sm_ioctl smi; + int ret; + struct usersmmsg msg; + + if (!diag) { + errno = EINVAL; + return -1; + } + if (kernel_mode) { + memcpy(&smi.data.diag, diag, sizeof(smi.data.diag)); + ret = hdrvc_sm_ioctl(SMCTL_DIAGNOSE, &smi); + memcpy(diag, &smi.data.diag, sizeof(smi.data.diag)); + return ret; + } + msg.hdr.type = USERSM_CMD_REQ_DIAG; + msg.hdr.channel = 0; + msg.data.diag.mode = diag->mode; + msg.data.diag.flags = diag->flags; + msg.data.diag.samplesperbit = diag->samplesperbit; + msg.data.diag.datalen = diag->datalen; + hdrvc_sendmsg(&msg, sizeof(msg.data.diag)); + ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DIAG); + if (ret < 0) + return ret; + if (ret < sizeof(msg.data.diag) || ret < sizeof(msg.data.diag)+msg.data.diag.datalen*sizeof(short)) { + errno = EIO; + return -1; + } + diag->mode = msg.data.diag.mode; + diag->flags = msg.data.diag.flags; + diag->samplesperbit = msg.data.diag.samplesperbit; + diag->datalen = msg.data.diag.datalen; + memcpy(diag->data, msg.data.diag_out.samples, msg.data.diag.datalen*sizeof(short)); + return 0; +} + +#endif /* HDRVC_KERNEL */ + +/* ---------------------------------------------------------------------- */ + +int hdrvc_get_samples(void) +{ + int ret; + struct hdlcdrv_ioctl bi; + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETSAMPLES, &bi); + if (ret < 0) + return ret; + return bi.data.bits & 0xff; + } +#endif /* HDRVC_KERNEL */ + errno = EAGAIN; + return -1; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_get_bits(void) +{ + int ret; + struct hdlcdrv_ioctl bi; + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETBITS, &bi); + if (ret < 0) + return ret; + return bi.data.bits & 0xff; + } +#endif /* HDRVC_KERNEL */ + errno = EAGAIN; + return -1; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_get_channel_access_param(struct hdrvc_channel_params *par) +{ + struct hdlcdrv_ioctl hi; + int ret; + struct usersmmsg msg; + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + if ((ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETCHANNELPAR, &hi)) < 0) + return ret; + if (!par) { + errno = EINVAL; + return -1; + } + par->tx_delay = hi.data.cp.tx_delay; + par->tx_tail = hi.data.cp.tx_tail; + par->slottime = hi.data.cp.slottime; + par->ppersist = hi.data.cp.ppersist; + par->fulldup = hi.data.cp.fulldup; + return 0; + } +#endif /* HDRVC_KERNEL */ + msg.hdr.type = USERSM_CMD_REQ_CHACCESS_PAR; + msg.hdr.channel = 0; + hdrvc_sendmsg(&msg, 0); + ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_CHACCESS_PAR); + if (ret < 0) + return ret; + if (ret < sizeof(msg.data.cp)) { + errno = EIO; + return -1; + } + par->tx_delay = msg.data.cp.tx_delay; + par->tx_tail = msg.data.cp.tx_tail; + par->slottime = msg.data.cp.slottime; + par->ppersist = msg.data.cp.ppersist; + par->fulldup = msg.data.cp.fulldup; + return 0; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_set_channel_access_param(struct hdrvc_channel_params par) +{ + int ret; + struct usersmmsg msg; + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + struct hdlcdrv_ioctl hi; + + hi.data.cp.tx_delay = par.tx_delay; + hi.data.cp.tx_tail = par.tx_tail; + hi.data.cp.slottime = par.slottime; + hi.data.cp.ppersist = par.ppersist; + hi.data.cp.fulldup = par.fulldup; + if ((ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETCHANNELPAR, &hi)) < 0) + return ret; + return 0; + } +#endif /* HDRVC_KERNEL */ + msg.hdr.type = USERSM_CMD_SET_CHACCESS_PAR; + msg.hdr.channel = 0; + msg.data.cp.tx_delay = par.tx_delay; + msg.data.cp.tx_tail = par.tx_tail; + msg.data.cp.slottime = par.slottime; + msg.data.cp.ppersist = par.ppersist; + msg.data.cp.fulldup = par.fulldup; + hdrvc_sendmsg(&msg, sizeof(msg.data.cp)); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_calibrate(int calib) +{ + struct hdlcdrv_ioctl bhi; + struct usersmmsg msg; + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + bhi.data.calibrate = calib; + return hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_CALIBRATE, &bhi); + } +#endif /* HDRVC_KERNEL */ + msg.hdr.type = USERSM_CMD_CALIBRATE; + msg.hdr.channel = 0; + msg.data.calib = calib; + hdrvc_sendmsg(&msg, sizeof(msg.data.calib)); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_get_channel_state(struct hdrvc_channel_state *st) +{ + struct hdlcdrv_ioctl bhi; + int ret; + struct usersmmsg msg; + + if (!st) { + errno = EINVAL; + return -1; + } +#ifdef HDRVC_KERNEL + if (kernel_mode) { + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETSTAT, &bhi); + if (ret >= 0) { + st->ptt = bhi.data.cs.ptt; + st->dcd = bhi.data.cs.dcd; + st->ptt_keyed = bhi.data.cs.ptt_keyed; + st->tx_packets = bhi.data.cs.tx_packets; + st->tx_errors = bhi.data.cs.tx_errors; + st->rx_packets = bhi.data.cs.rx_packets; + st->rx_errors = bhi.data.cs.rx_errors; + } + return ret; + } +#endif /* HDRVC_KERNEL */ + msg.hdr.type = USERSM_CMD_REQ_CHANNELSTATE; + msg.hdr.channel = 0; + hdrvc_sendmsg(&msg, 0); + ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_CHANNELSTATE); + if (ret < 0) + return ret; + if (ret < sizeof(msg.data.cs)) { + errno = EIO; + return -1; + } + st->ptt = msg.data.cs.ptt; + st->dcd = msg.data.cs.dcd; + st->ptt_keyed = msg.data.cs.ptt_keyed; + st->tx_packets = msg.data.cs.tx_packets; + st->tx_errors = msg.data.cs.tx_errors; + st->rx_packets = msg.data.cs.rx_packets; + st->rx_errors = msg.data.cs.rx_errors; + return 0; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_diag2(unsigned int mode, unsigned int flags, short *data, + unsigned int maxdatalen, unsigned int *samplesperbit) +{ + int ret; + struct usersmmsg msg; + static unsigned int modeconvusersm[4] = { + USERSM_DIAGMODE_OFF, USERSM_DIAGMODE_INPUT, USERSM_DIAGMODE_DEMOD, + USERSM_DIAGMODE_CONSTELLATION + }; + + if (mode > HDRVC_DIAGMODE_CONSTELLATION) { + errno = EINVAL; + return -1; + } +#ifdef HDRVC_KERNEL + if (kernel_mode) { + struct sm_ioctl smi; + static unsigned int modeconvsm[4] = { + SM_DIAGMODE_OFF, SM_DIAGMODE_INPUT, SM_DIAGMODE_DEMOD, SM_DIAGMODE_CONSTELLATION + }; + + smi.data.diag.mode = modeconvsm[mode]; + smi.data.diag.flags = (flags & HDRVC_DIAGFLAG_DCDGATE) ? SM_DIAGFLAG_DCDGATE : 0; + smi.data.diag.samplesperbit = 0; + smi.data.diag.datalen = maxdatalen; + smi.data.diag.data = data; + if ((ret = hdrvc_sm_ioctl(SMCTL_DIAGNOSE, &smi)) < 0) + return ret; + if (samplesperbit) + *samplesperbit = smi.data.diag.samplesperbit; + if (smi.data.diag.mode != modeconvsm[mode] || !(smi.data.diag.flags & SM_DIAGFLAG_VALID)) + return 0; + return smi.data.diag.datalen; + } +#endif /* HDRVC_KERNEL */ + msg.hdr.type = USERSM_CMD_REQ_DIAG; + msg.hdr.channel = 0; + msg.data.diag.mode = modeconvusersm[mode]; + msg.data.diag.flags = (flags & HDRVC_DIAGFLAG_DCDGATE) ? USERSM_DIAGFLAG_DCDGATE : 0; + msg.data.diag.samplesperbit = 0; + msg.data.diag.datalen = maxdatalen; + hdrvc_sendmsg(&msg, sizeof(msg.data.diag)); + ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DIAG); + if (ret < 0) + return ret; + if (ret < sizeof(msg.data.diag) || ret < sizeof(msg.data.diag)+msg.data.diag.datalen*sizeof(short)) { + errno = EIO; + return -1; + } + if (samplesperbit) + *samplesperbit = msg.data.diag.samplesperbit; + if (msg.data.diag.mode != modeconvusersm[mode] || !(msg.data.diag.flags & USERSM_DIAGFLAG_VALID)) + return 0; + if (!data || msg.data.diag.datalen <= 0) + return 0; + memcpy(data, msg.data.diag_out.samples, msg.data.diag.datalen*sizeof(short)); + return msg.data.diag.datalen; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_get_driver_name(char *buf, int bufsz) +{ + int ret; + struct usersmmsg msg; + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + struct hdlcdrv_ioctl bhi; + + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_DRIVERNAME, &bhi); + if (ret < 0) + return ret; + strncpy(buf, bhi.data.modename, bufsz); + return 0; + } +#endif /* HDRVC_KERNEL */ + msg.hdr.type = USERSM_CMD_REQ_DRVNAME; + msg.hdr.channel = 0; + hdrvc_sendmsg(&msg, 0); + ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DRVNAME); + if (ret < 0) + return ret; + if (ret < 1) { + errno = EIO; + return -1; + } + if (bufsz < ret) + ret = bufsz; + strncpy(buf, msg.data.by, ret); + buf[ret-1] = 0; + return 0; +} + +/* ---------------------------------------------------------------------- */ + +int hdrvc_get_mode_name(char *buf, int bufsz) +{ + int ret; + struct usersmmsg msg; + +#ifdef HDRVC_KERNEL + if (kernel_mode) { + struct hdlcdrv_ioctl bhi; + + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETMODE, &bhi); + if (ret < 0) + return ret; + strncpy(buf, bhi.data.modename, bufsz); + return 0; + } +#endif /* HDRVC_KERNEL */ + msg.hdr.type = USERSM_CMD_REQ_DRVMODE; + msg.hdr.channel = 0; + hdrvc_sendmsg(&msg, 0); + ret = hdrvc_recvmsg(&msg, sizeof(msg), USERSM_CMD_ACK_DRVMODE); + if (ret < 0) + return ret; + if (ret < 1) { + errno = EIO; + return -1; + } + if (bufsz < ret) + ret = bufsz; + strncpy(buf, msg.data.by, ret); + buf[ret-1] = 0; + return 0; +} + +/* ---------------------------------------------------------------------- */ diff --git a/hdlcutil/hdrvcomm.h b/hdlcutil/hdrvcomm.h new file mode 100644 index 0000000..ec4be73 --- /dev/null +++ b/hdlcutil/hdrvcomm.h @@ -0,0 +1,109 @@ +/*****************************************************************************/ + +/* + * hdrvcomm.h -- HDLC driver communications. + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + */ + +/*****************************************************************************/ + +#ifndef _HDRVCOMM_H +#define _HDRVCOMM_H + +/* ---------------------------------------------------------------------- */ + +#undef HDRVC_KERNEL 1 + +/* ---------------------------------------------------------------------- */ + +#ifdef HDRVC_KERNEL +#include +#include +#include +#endif /* HDRVC_KERNEL */ + +/* ---------------------------------------------------------------------- */ + +struct hdrvc_channel_params { + int tx_delay; /* the transmitter keyup delay in 10ms units */ + int tx_tail; /* the transmitter keyoff delay in 10ms units */ + int slottime; /* the slottime in 10ms; usually 10 = 100ms */ + int ppersist; /* the p-persistence 0..255 */ + int fulldup; /* some driver do not support full duplex, setting */ + /* this just makes them send even if DCD is on */ +}; + +struct hdrvc_channel_state { + int ptt; + int dcd; + int ptt_keyed; + unsigned long tx_packets; + unsigned long tx_errors; + unsigned long rx_packets; + unsigned long rx_errors; +}; + +/* ---------------------------------------------------------------------- */ + +/* + * diagnose modes + */ +#define HDRVC_DIAGMODE_OFF 0 +#define HDRVC_DIAGMODE_INPUT 1 +#define HDRVC_DIAGMODE_DEMOD 2 +#define HDRVC_DIAGMODE_CONSTELLATION 3 + +/* + * diagnose flags + */ +#define HDRVC_DIAGFLAG_DCDGATE (1<<0) + + +/* ---------------------------------------------------------------------- */ + +extern int hdrvc_recvpacket(char *pkt, int maxlen); +extern int hdrvc_getfd(void); +extern char *hdrvc_ifname(void); +extern void hdrvc_args(int *argc, char *argv[], char *def_if); +extern void hdrvc_init(void); +extern int hdrvc_get_samples(void); +extern int hdrvc_get_bits(void); +extern int hdrvc_get_channel_access_param(struct hdrvc_channel_params *par); +extern int hdrvc_set_channel_access_param(struct hdrvc_channel_params par); +extern int hdrvc_calibrate(int calib); +extern int hdrvc_get_channel_state(struct hdrvc_channel_state *st); +extern unsigned int hdrvc_get_ifflags(void); +extern int hdrvc_diag2(unsigned int mode, unsigned int flags, short *data, unsigned int maxdatalen, + unsigned int *samplesperbit); +extern int hdrvc_get_driver_name(char *buf, int bufsz); +extern int hdrvc_get_mode_name(char *buf, int bufsz); + +#ifdef HDRVC_KERNEL +extern int hdrvc_hdlcdrv_ioctl(int cmd, struct hdlcdrv_ioctl *par); +extern int hdrvc_sm_ioctl(int cmd, struct sm_ioctl *par); +extern int hdrvc_baycom_ioctl(int cmd, struct baycom_ioctl *par); +extern int hdrvc_diag(struct sm_diag_data *diag); +#endif /* HDRVC_KERNEL */ + +/* ---------------------------------------------------------------------- */ +#endif /* _HDRVCOMM_H */ diff --git a/hdlcutil/setcrystal.c b/hdlcutil/setcrystal.c new file mode 100644 index 0000000..f5181f3 --- /dev/null +++ b/hdlcutil/setcrystal.c @@ -0,0 +1,136 @@ +/*****************************************************************************/ + +/* + * setcrystal.c -- crystal soundcard configuration utility + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + */ + +/* --------------------------------------------------------------------- */ + +#include +#include +#include +#include + +/* --------------------------------------------------------------------- */ + +static const unsigned char crystal_key[32] = { + 0x96, 0x35, 0x9a, 0xcd, 0xe6, 0xf3, 0x79, 0xbc, + 0x5e, 0xaf, 0x57, 0x2b, 0x15, 0x8a, 0xc5, 0xe2, + 0xf1, 0xf8, 0x7c, 0x3e, 0x9f, 0x4f, 0x27, 0x13, + 0x09, 0x84, 0x42, 0xa1, 0xd0, 0x68, 0x34, 0x1a +}; + +#define KEY_PORT 0x279 +#define CSN 1 /* card select number */ + +/* --------------------------------------------------------------------- */ + +int main(int argc, char *argv[]) +{ + int wssbase = 0x534; + int synbase = 0x388; + int sbbase = 0x220; + int irq = 5; + int dma = 1; + int dma2 = 3; + + int i; + + printf("Crystal PnP Soundcard enabler\n" + "(C) 1996 by Thomas Sailer, HB9JNX/AE4WA\n" + "WARNING: This utility is incompatible with OS PnP support!\n" + " Remove it as soon as Linux supports PnP!\n"); + while ((i = getopt(argc, argv, "i:d:c:s:w:f:h")) != EOF) { + switch (i) { + case 'i': + irq = strtoul(optarg, NULL, 0); + break; + case 'd': + dma = strtoul(optarg, NULL, 0); + break; + case 'c': + dma2 = strtoul(optarg, NULL, 0); + break; + case 's': + sbbase = strtoul(optarg, NULL, 0); + break; + case 'w': + wssbase = strtoul(optarg, NULL, 0); + break; + case 'f': + synbase = strtoul(optarg, NULL, 0); + break; + + default: + case ':': + case '?': + case 'h': + fprintf(stderr, "usage: [-w wssio] [-s sbio] " + "[-f synthio] [-i irq] [-d dma] [-c dma2]\n"); + exit(1); + } + } + + if ((i = ioperm(KEY_PORT, 1, 1))) { + perror("ioperm"); + exit(1); + } + /* + * send crystal key + */ + for (i = 0; i < 32; i++) + outb(crystal_key[i], KEY_PORT); + /* + * send config data + */ + outb(0x6, KEY_PORT); + outb(CSN, KEY_PORT); + outb(0x15, KEY_PORT); + outb(0x0, KEY_PORT); /* logical device 0 */ + outb(0x47, KEY_PORT); + outb(wssbase >> 8, KEY_PORT); + outb(wssbase & 0xff, KEY_PORT); + outb(0x48, KEY_PORT); + outb(synbase >> 8, KEY_PORT); + outb(synbase & 0xff, KEY_PORT); + outb(0x42, KEY_PORT); + outb(sbbase >> 8, KEY_PORT); + outb(sbbase & 0xff, KEY_PORT); + outb(0x22, KEY_PORT); + outb(irq, KEY_PORT); + outb(0x2a, KEY_PORT); + outb(dma, KEY_PORT); + outb(0x25, KEY_PORT); + outb(dma2, KEY_PORT); + outb(0x33, KEY_PORT); + outb(0x1, KEY_PORT); /* activate logical device */ + outb(0x79, KEY_PORT); /* activate part */ + + printf("Crystal CS423[26] set to: WSS iobase 0x%x, Synth iobase 0x%x," + " SB iobase 0x%x,\n IRQ %u, DMA %u, DMA2 %u\n", wssbase, + synbase, sbbase, irq, dma, dma2); + exit(0); +} + +/* --------------------------------------------------------------------- */ diff --git a/hdlcutil/sethdlc.c b/hdlcutil/sethdlc.c new file mode 100644 index 0000000..b07c0de --- /dev/null +++ b/hdlcutil/sethdlc.c @@ -0,0 +1,598 @@ +/*****************************************************************************/ + +/* + * sethdlc.c -- kernel HDLC radio modem driver setup utility. + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + * + * History: + * 0.1 16.10.96 Adapted from setbaycom.c and setsm.c + * 0.2 20.11.96 New mode set/query code + * 0.5 11.05.97 introduced hdrvcomm.h + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +/*#include */ +#include +#include "hdrvcomm.h" + +#include +#include + +/* ---------------------------------------------------------------------- */ + +static unsigned char trace_stat = 0; +static char *progname; + +/* ---------------------------------------------------------------------- */ + +static void display_packet(unsigned char *bp, unsigned int len) +{ + unsigned char v1=1,cmd=0; + unsigned char i,j; + + if (!bp || !len) + return; + if (len < 8) + return; + if (bp[1] & 1) { + /* + * FlexNet Header Compression + */ + v1 = 0; + cmd = (bp[1] & 2) != 0; + printf("fm ? to "); + i = (bp[2] >> 2) & 0x3f; + if (i) + printf("%c",i+0x20); + i = ((bp[2] << 4) | ((bp[3] >> 4) & 0xf)) & 0x3f; + if (i) + printf("%c",i+0x20); + i = ((bp[3] << 2) | ((bp[4] >> 6) & 3)) & 0x3f; + if (i) + printf("%c",i+0x20); + i = bp[4] & 0x3f; + if (i) + printf("%c",i+0x20); + i = (bp[5] >> 2) & 0x3f; + if (i) + printf("%c",i+0x20); + i = ((bp[5] << 4) | ((bp[6] >> 4) & 0xf)) & 0x3f; + if (i) + printf("%c",i+0x20); + printf("-%u QSO Nr %u", bp[6] & 0xf, (bp[0] << 6) | + (bp[1] >> 2)); + bp += 7; + len -= 7; + } else { + /* + * normal header + */ + if (len < 15) + return; + if ((bp[6] & 0x80) != (bp[13] & 0x80)) { + v1 = 0; + cmd = (bp[6] & 0x80); + } + printf("fm "); + for(i = 7; i < 13; i++) + if ((bp[i] &0xfe) != 0x40) + printf("%c",bp[i] >> 1); + printf("-%u to ",(bp[13] >> 1) & 0xf); + for(i = 0; i < 6; i++) + if ((bp[i] &0xfe) != 0x40) + printf("%c", bp[i] >> 1); + printf("-%u", (bp[6] >> 1) & 0xf); + bp += 14; + len -= 14; + if ((!(bp[-1] & 1)) && (len >= 7)) + printf(" via "); + while ((!(bp[-1] & 1)) && (len >= 7)) { + for(i = 0; i < 6; i++) + if ((bp[i] &0xfe) != 0x40) + printf("%c",bp[i] >> 1); + printf("-%u",(bp[6] >> 1) & 0xf); + bp += 7; + len -= 7; + if ((!(bp[-1] & 1)) && (len >= 7)) + printf(","); + } + } + if(!len) + return; + i = *bp++; + len--; + j = v1 ? ((i & 0x10) ? '!' : ' ') : + ((i & 0x10) ? (cmd ? '+' : '-') : (cmd ? '^' : 'v')); + if (!(i & 1)) { + /* + * Info frame + */ + printf(" I%u%u%c",(i >> 5) & 7,(i >> 1) & 7,j); + } else if (i & 2) { + /* + * U frame + */ + switch (i & (~0x10)) { + case 0x03: + printf(" UI%c",j); + break; + case 0x2f: + printf(" SABM%c",j); + break; + case 0x43: + printf(" DISC%c",j); + break; + case 0x0f: + printf(" DM%c",j); + break; + case 0x63: + printf(" UA%c",j); + break; + case 0x87: + printf(" FRMR%c",j); + break; + default: + printf(" unknown U (0x%x)%c",i & (~0x10),j); + break; + } + } else { + /* + * supervisory + */ + switch (i & 0xf) { + case 0x1: + printf(" RR%u%c",(i >> 5) & 7,j); + break; + case 0x5: + printf(" RNR%u%c",(i >> 5) & 7,j); + break; + case 0x9: + printf(" REJ%u%c",(i >> 5) & 7,j); + break; + default: + printf(" unknown S (0x%x)%u%c", i & 0xf, + (i >> 5) & 7, j); + break; + } + } + if (!len) { + printf("\n"); + return; + } + printf(" pid=%02X\n", *bp++); + len--; + j = 0; + while (len) { + i = *bp++; + if ((i >= 32) && (i < 128)) + printf("%c",i); + else if (i == 13) { + if (j) + printf("\n"); + j = 0; + } else + printf("."); + if (i >= 32) + j = 1; + len--; + } + if (j) + printf("\n"); +} + +/* ---------------------------------------------------------------------- */ + +static void print_bits(int (*bitproc)(void)) +{ + int ret; + int i; + char str[9]; + char *cp; + + for(;;) { + ret = bitproc(); + if (ret < 0) { + if (errno == EAGAIN) + return; + fprintf(stderr, "%s: Error %s (%i), cannot ioctl\n", + progname, strerror(errno), errno); + return; + } + strcpy(cp = str, "00000000"); + for(i = 0; i < 8; i++, cp++, ret >>= 1) + *cp += (ret & 1); + printf("%s", str); + } +} + +/* ---------------------------------------------------------------------- */ + +#ifdef HDRVC_KERNEL + +static void do_set_params(int argc, char **argv) +{ + struct hdlcdrv_ioctl drvname, curm, newm, mlist, curp, newp, mpmask; + char set = 0; + int ret; + int mask; + + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_DRIVERNAME, &drvname); + if (ret < 0) { + perror("ioctl (HDLCDRVCTL_DRIVERNAME)"); + exit(1); + } + printf("driver name: %s\n", drvname.data.drivername); + + mask = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_MODEMPARMASK, &mpmask); + if (mask < 0) + mask = ~0; + + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETMODEMPAR, &curp); + if (ret < 0) { + perror("ioctl (HDLCDRVCTL_GETMODEMPAR)"); + exit(1); + } + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_GETMODE, &curm); + if (ret < 0) { + perror("ioctl (HDLCDRVCTL_GETMODE)"); + exit(1); + } + newm = curm; + newp = curp; + while (argc >= 2) { + if (!strcasecmp(argv[0], "mode")) { + strncpy(newm.data.modename, argv[1], + sizeof(newm.data.modename)); + set |= 1; + } else if (!strcasecmp(argv[0], "io") && mask & HDLCDRV_PARMASK_IOBASE) { + newp.data.mp.iobase = strtoul(argv[1], NULL, 0); + set |= 2; + } else if (!strcasecmp(argv[0], "irq") && mask & HDLCDRV_PARMASK_IRQ) { + newp.data.mp.irq = strtoul(argv[1], NULL, 0); + set |= 2; + } else if (!strcasecmp(argv[0], "dma") && mask & HDLCDRV_PARMASK_DMA) { + newp.data.mp.dma = strtoul(argv[1], NULL, 0); + set |= 2; + } else if (!strcasecmp(argv[0], "dma2") && mask & HDLCDRV_PARMASK_DMA2) { + newp.data.mp.dma2 = strtoul(argv[1], NULL, 0); + set |= 2; + } else if (!strcasecmp(argv[0], "serio") && mask & HDLCDRV_PARMASK_SERIOBASE) { + newp.data.mp.seriobase = strtol(argv[1], NULL, 0); + set |= 2; + } else if (!strcasecmp(argv[0], "pario") && mask & HDLCDRV_PARMASK_PARIOBASE) { + newp.data.mp.pariobase = strtol(argv[1], NULL, 0); + set |= 2; + } else if (!strcasecmp(argv[0], "midiio") && mask & HDLCDRV_PARMASK_MIDIIOBASE) { + newp.data.mp.midiiobase = strtol(argv[1], NULL, 0); + set |= 2; + } else { + fprintf(stderr, "%s: invalid parameter type '%s', " + "valid: mode%s%s%s%s%s%s%s\n", + progname, argv[0], + (mask & HDLCDRV_PARMASK_IOBASE) ? " io" : "", + (mask & HDLCDRV_PARMASK_IRQ) ? " irq" : "", + (mask & HDLCDRV_PARMASK_DMA) ? " dma" : "", + (mask & HDLCDRV_PARMASK_DMA2) ? " dma2" : "", + (mask & HDLCDRV_PARMASK_SERIOBASE) ? " serio" : "", + (mask & HDLCDRV_PARMASK_PARIOBASE) ? " pario" : "", + (mask & HDLCDRV_PARMASK_MIDIIOBASE) ? " midiio" : ""); + } + argv += 2; + argc -= 2; + } + if (argc >= 1) + fprintf(stderr, "%s: orphaned parameter type '%s', no data\n", + progname, argv[0]); + printf("current parameters: mode %s", curm.data.modename); + if (mask & HDLCDRV_PARMASK_IOBASE) + printf(" io 0x%x", curp.data.mp.iobase); + if (mask & HDLCDRV_PARMASK_IRQ) + printf(" irq %u", curp.data.mp.irq); + if (mask & HDLCDRV_PARMASK_DMA) + printf(" dma %u", curp.data.mp.dma); + if (mask & HDLCDRV_PARMASK_DMA2) + printf(" dma2 %u", curp.data.mp.dma2); + if (mask & HDLCDRV_PARMASK_SERIOBASE) + printf(" serio 0x%x", curp.data.mp.seriobase); + if (mask & HDLCDRV_PARMASK_PARIOBASE) + printf(" pario 0x%x", curp.data.mp.pariobase); + if (mask & HDLCDRV_PARMASK_MIDIIOBASE) + printf(" midiio 0x%x", curp.data.mp.midiiobase); + printf("\n"); + + if (set & 1) + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETMODE, &newm); + if (ret < 0) { + perror("ioctl (HDLCDRVCTL_SETMODE)"); + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_MODELIST, &mlist); + if (ret < 0) { + perror("ioctl (HDLCDRVCTL_MODELIST)"); + exit(1); + } + printf("driver supported modes: %s\n", + mlist.data.modename); + exit(1); + } + if (set & 2) { + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETMODEMPAR, &newp); + if (ret < 0) { + perror("ioctl (HDLCDRVCTL_SETMODEMPAR)"); + fprintf(stderr, "%s: trying to restore old " + "parameters\n", progname); + ret = hdrvc_hdlcdrv_ioctl(HDLCDRVCTL_SETMODEMPAR, &curp); + if (ret < 0) + perror("ioctl (HDLCDRVCTL_SETMODEMPAR)"); + exit(1); + } + } + if (set & 3) { + printf("new parameters: mode %s", newm.data.modename); + if (mask & HDLCDRV_PARMASK_IOBASE) + printf(" io 0x%x", newp.data.mp.iobase); + if (mask & HDLCDRV_PARMASK_IRQ) + printf(" irq %u", newp.data.mp.irq); + if (mask & HDLCDRV_PARMASK_DMA) + printf(" dma %u", newp.data.mp.dma); + if (mask & HDLCDRV_PARMASK_DMA2) + printf(" dma2 %u", newp.data.mp.dma2); + if (mask & HDLCDRV_PARMASK_SERIOBASE) + printf(" serio 0x%x", newp.data.mp.seriobase); + if (mask & HDLCDRV_PARMASK_PARIOBASE) + printf(" pario 0x%x", newp.data.mp.pariobase); + if (mask & HDLCDRV_PARMASK_MIDIIOBASE) + printf(" midiio 0x%x", newp.data.mp.midiiobase); + printf("\n"); + } + exit(0); +} + +#endif /* HDRVC_KERNEL */ + +/* ---------------------------------------------------------------------- */ + +static void display_channel_params(const struct hdrvc_channel_params *par) +{ + printf("TX delay %ums, TX tail %ums, slottime %ums, p-persistence " + " %u/256, %s duplex\n", 10*par->tx_delay, 10*par->tx_tail, + 10*par->slottime, par->ppersist, + par->fulldup ? "Full" : "Half"); +} + +/* ---------------------------------------------------------------------- */ + +static void do_set_channel_params(int argc, char **argv) +{ + struct hdrvc_channel_params par1, par2; + char set = 0; + int ret; + + ret = hdrvc_get_channel_access_param(&par1); + if (ret < 0) { + perror("hdrvc_get_channel_access_param"); + exit(1); + } + par2 = par1; + while (argc > 0) { + if (argc >= 2 && !strcasecmp(argv[0], "txd")) { + par2.tx_delay = strtoul(argv[1], NULL, 0) / 10; + set = 1; + argv += 2; + argc -= 2; + } else if (argc >= 2 && !strcasecmp(argv[0], "txtail")) { + par2.tx_tail = strtoul(argv[1], NULL, 0) / 10; + set = 1; + argv += 2; + argc -= 2; + } else if (argc >= 2 && !strcasecmp(argv[0], "slot")) { + par2.slottime = strtoul(argv[1], NULL, 0) / 10; + set = 1; + argv += 2; + argc -= 2; + } else if (argc >= 2 && !strcasecmp(argv[0], "ppersist")) { + par2.ppersist = strtoul(argv[1], NULL, 0); + set = 1; + argv += 2; + argc -= 2; + } else if (!strcasecmp(argv[0], "half")) { + par2.fulldup = 0; + set = 1; + argv += 1; + argc -= 1; + } else if (!strcasecmp(argv[0], "full")) { + par2.fulldup = 1; + set = 1; + argv += 1; + argc -= 1; + } else { + + argv += 1; + argc -= 1; + } + } + printf("current parameters: "); + display_channel_params(&par1); + if (set) { + ret = hdrvc_set_channel_access_param(par2); + if (ret < 0) { + perror("hdrvc_set_channel_access_param"); + exit(1); + } + printf("new parameters: "); + display_channel_params(&par2); + } + exit(0); +} + +/* ---------------------------------------------------------------------- */ + +static const char *usage_str = +"[-b] [-i] [-d] [-i ] [-h] [-c ]\n" +"[-p] [hw ] [type ] [io ] [irq ] [dma ]\n" +" [options ] [serio ] [pario ] [midiio ]\n" +"[-a] [txd ] [txtail ] [slot ]\n" +" [ppersist ] [full] [half]\n" +" -a: set or display channel access parameters\n" +" -b: trace demodulated bits\n" +" -s: trace sampled input from tcm3105 (ser12 only)\n" +" -d: trace dcd and ptt status on stdout\n" +" -i: specify the name of the baycom kernel driver interface\n" +" -c: calibrate (i.e. send calibration pattern) for cal seconds\n" +#ifdef HDRVC_KERNEL +" -p: set or display interface parameters\n" +#endif /* HDRVC_KERNEL */ +" -h: this help\n\n"; + +int main(int argc, char *argv[]) +{ + int ret; + fd_set fds_read; + fd_set fds_write; + struct timeval tm; + char getsetparams = 0; + char cal = 0; + int cal_val = 0; + struct sm_ioctl bsi; + struct baycom_ioctl bbi; + struct hdrvc_channel_state chst; + unsigned char pktbuf[2048]; + + progname = *argv; + printf("%s: Version 0.5; (C) 1996-1997 by Thomas Sailer HB9JNX/AE4WA\n", *argv); + hdrvc_args(&argc, argv, "bc0"); + while ((ret = getopt(argc, argv, "bsdhpc:a")) != -1) { + switch (ret) { + case 'b': + trace_stat = 2; + break; + case 's': + trace_stat = 3; + break; + case 'd': + trace_stat = 1; + break; +#ifdef HDRVC_KERNEL + case 'p': + getsetparams = 1; + break; +#endif /* HDRVC_KERNEL */ + case 'a': + getsetparams = 2; + break; + case 'c': + cal = 1; + cal_val = strtoul(optarg, NULL, 0); + break; + default: + printf("usage: %s %s", *argv, usage_str); + exit(-1); + } + } + hdrvc_init(); + if (getsetparams == 1) { +#ifdef HDRVC_KERNEL + do_set_params(argc - optind, argv+optind); +#endif /* HDRVC_KERNEL */ + exit(0); + } + if (getsetparams == 2) { + do_set_channel_params(argc - optind, argv+optind); + exit(0); + } + if (cal) { + ret = hdrvc_calibrate(cal_val); + if (ret < 0) { + perror("hdrvc_calibrate"); + exit(1); + } + fprintf(stdout, "%s: calibrating for %i seconds\n", *argv, + cal_val); + exit(0); + } + for (;;) { + while ((ret = hdrvc_recvpacket(pktbuf, sizeof(pktbuf))) > 1) + display_packet(pktbuf+1, ret-1); + switch (trace_stat) { + case 1: + ret = hdrvc_get_channel_state(&chst); + if (ret < 0) + perror("hdrvc_get_channel_state"); + printf("%c%c rx: %lu tx: %lu rxerr: %lu txerr: %lu", + chst.dcd ? 'D' : '-', chst.ptt ? 'P' : '-', + chst.rx_packets, chst.tx_packets, chst.rx_errors, + chst.tx_errors); +#ifdef HDRVC_KERNEL + if (hdrvc_sm_ioctl(SMCTL_GETDEBUG, &bsi) >= 0) { + printf(" intrate: %u modcyc: %u " + "demodcyc: %u dmares: %u", + bsi.data.dbg.int_rate, + bsi.data.dbg.mod_cycles, + bsi.data.dbg.demod_cycles, + bsi.data.dbg.dma_residue); + } + if (hdrvc_baycom_ioctl(BAYCOMCTL_GETDEBUG, &bbi) >= 0) { + printf(" dbg1: %lu dbg2: %lu dbg3: %li", + bbi.data.dbg.debug1, bbi.data.dbg.debug2, + bbi.data.dbg.debug3); + } +#endif /* HDRVC_KERNEL */ + printf("\n"); + break; + case 2: + print_bits(hdrvc_get_bits); + printf("\n"); + break; + case 3: + print_bits(hdrvc_get_samples); + printf("\n"); + break; + default: + break; + } + tm.tv_usec = 500000L; + tm.tv_sec = 0L; + if (hdrvc_getfd() >= 0) { + FD_ZERO(&fds_read); + FD_ZERO(&fds_write); + FD_SET(hdrvc_getfd(), &fds_read); + ret = select(hdrvc_getfd()+1, &fds_read, &fds_write, NULL, &tm); + } else + ret = select(0, NULL, NULL, NULL, &tm); + if (ret < 0) { + fprintf(stderr, "%s: Error %s (%i) in select\n", *argv, + strerror(errno), errno); + exit(-2); + } + } +} + +/* ---------------------------------------------------------------------- */ diff --git a/hdlcutil/smdiag.c b/hdlcutil/smdiag.c new file mode 100644 index 0000000..d8a20f8 --- /dev/null +++ b/hdlcutil/smdiag.c @@ -0,0 +1,434 @@ +/*****************************************************************************/ + +/* + * smdiag.c -- kernel soundcard radio modem driver diagnostics utility. + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + * + * History: + * 0.1 26.06.96 Started + * 0.2 11.05.97 introduced hdrvcomm.h + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "hdrvcomm.h" + +#include + +/* ---------------------------------------------------------------------- */ + +static char *progname; +static Display *display = NULL; +static Window window; +static Pixmap pixmap; +static unsigned long col_zeroline; +static unsigned long col_background; +static unsigned long col_trace; +static GC gr_context; +static int xmul; + +/* ---------------------------------------------------------------------- */ + +static int x_error_handler(Display *disp, XErrorEvent *evt) +{ + char err_buf[256], mesg[256], number[256]; + char *mtype = "XlibMessage"; + + XGetErrorText(disp, evt->error_code, err_buf, sizeof(err_buf)); + fprintf(stderr, "X Error: %s\n", err_buf); + XGetErrorDatabaseText(disp, mtype, "MajorCode", "Request Major code %d", + mesg, sizeof(mesg)); + fprintf(stderr, mesg, evt->request_code); + sprintf(number, "%d", evt->request_code); + XGetErrorDatabaseText(disp, "XRequest", number, "", err_buf, + sizeof(err_buf)); + fprintf(stderr, " (%s)\n", err_buf); + abort(); +} + +/* ---------------------------------------------------------------------- */ + +#define WIDTH 512 +#define HEIGHT (constell ? 512 : 256) + +static int openwindow(char *disp, int constell, int samplesperbit) +{ + XSetWindowAttributes attr; + XGCValues gr_values; + XColor color, dummy; + XSizeHints sizehints; + + if (!(display = XOpenDisplay(NULL))) + return -1; + XSetErrorHandler(x_error_handler); + XAllocNamedColor(display, DefaultColormap(display, 0), "red", + &color, &dummy); + col_zeroline = color.pixel; + col_background = WhitePixel(display, 0); + col_trace = BlackPixel(display, 0); + attr.background_pixel = col_background; + if (!(window = XCreateWindow(display, XRootWindow(display, 0), + 200, 200, WIDTH, HEIGHT, 5, + DefaultDepth(display, 0), + InputOutput, DefaultVisual(display, 0), + CWBackPixel, &attr))) { + fprintf(stderr, "smdiag: unable to open X window\n"); + exit(1); + } + if (!(pixmap = XCreatePixmap(display, window, WIDTH, HEIGHT, + DefaultDepth(display, 0)))) { + fprintf(stderr, "smdiag: unable to open offscreen pixmap\n"); + exit(1); + } + xmul = WIDTH / (2*(samplesperbit > 0 ? samplesperbit : 1)); + XSelectInput(display, window, KeyPressMask | StructureNotifyMask + | ExposureMask) ; + XAllocNamedColor(display, DefaultColormap(display, 0), "red", + &color, &dummy); + gr_values.foreground = col_trace; + gr_values.line_width = 1; + gr_values.line_style = LineSolid; + gr_context = XCreateGC(display, window, GCForeground | GCLineWidth | + GCLineStyle, &gr_values); + XStoreName(display, window, "diagnostics"); + /* + * Do not allow the window to be resized + */ + memset(&sizehints, 0, sizeof(sizehints)); + sizehints.min_width = sizehints.max_width = WIDTH; + sizehints.min_height = sizehints.max_height = HEIGHT; + sizehints.flags = PMinSize | PMaxSize; + XSetWMNormalHints(display, window, &sizehints); + XMapWindow(display, window); + XSynchronize(display, 1); + return 0; +} + +#undef WIDTH +#undef HEIGHT + +/* ---------------------------------------------------------------------- */ + +static void closewindow(void) +{ + if (!display) + return; + XDestroyWindow(display, window); + XCloseDisplay(display); + display = NULL; +} + +/* ---------------------------------------------------------------------- */ + +#define XCOORD(x) ((x) * xm) +#define YCOORD(y) ((SHRT_MAX - (int)(y)) * winattrs.height / USHRT_MAX) + +static void drawdata(short *data, int len, int replace, int xm) +{ + int cnt; + GC gc; + XGCValues gcv; + XWindowAttributes winattrs; + + if (!display || !pixmap) + return; + XGetWindowAttributes(display, window, &winattrs); + gcv.line_width = 1; + gcv.line_style = LineSolid; + gc = XCreateGC(display, pixmap, GCLineWidth | GCLineStyle, &gcv); + XSetState(display, gc, col_background, col_background, GXcopy, + AllPlanes); + if (replace) + XFillRectangle(display, pixmap, gc, 0, 0, + winattrs.width, winattrs.height); + else + XCopyArea(display, window, pixmap, gr_context, 0, 0, + winattrs.width, winattrs.height, 0, 0); + XSetForeground(display, gc, col_trace); + for (cnt = 0; cnt < len-1; cnt++) + XDrawLine(display, pixmap, gc, XCOORD(cnt), YCOORD(data[cnt]), + XCOORD(cnt+1), YCOORD(data[cnt+1])); + XSetForeground(display, gc, col_zeroline); + XDrawLine(display, pixmap, gc, 0, YCOORD(0), winattrs.width, + YCOORD(0)); + XCopyArea(display, pixmap, window, gr_context, 0, 0, winattrs.width, + winattrs.height, 0, 0); + XFreeGC(display, gc); + XSync(display, 0); +} + +#undef XCOORD +#undef YCOORD + +/* ---------------------------------------------------------------------- */ + +#define XCOORD(x) ((SHRT_MAX - (int)(x)) * winattrs.width / USHRT_MAX) +#define YCOORD(y) ((SHRT_MAX - (int)(y)) * winattrs.height / USHRT_MAX) + +static void drawconstell(short *data, int len) +{ + int cnt; + GC gc; + XGCValues gcv; + XWindowAttributes winattrs; + + if (!display || !pixmap) + return; + XGetWindowAttributes(display, window, &winattrs); + gcv.line_width = 1; + gcv.line_style = LineSolid; + gc = XCreateGC(display, pixmap, GCLineWidth | GCLineStyle, &gcv); + XSetState(display, gc, col_background, col_background, GXcopy, + AllPlanes); + XCopyArea(display, window, pixmap, gr_context, 0, 0, + winattrs.width, winattrs.height, 0, 0); + XSetForeground(display, gc, col_trace); + for (cnt = 0; cnt < len-1; cnt += 2) + XDrawPoint(display, pixmap, gc, + XCOORD(data[cnt]), YCOORD(data[cnt+1])); + XSetForeground(display, gc, col_zeroline); + XDrawLine(display, pixmap, gc, 0, YCOORD(0), winattrs.width, YCOORD(0)); + XDrawLine(display, pixmap, gc, XCOORD(0), 0, XCOORD(0), winattrs.height); + XCopyArea(display, pixmap, window, gr_context, 0, 0, winattrs.width, + winattrs.height, 0, 0); + XFreeGC(display, gc); + XSync(display, 0); +} + +#undef XCOORD +#undef YCOORD + +/* ---------------------------------------------------------------------- */ + +static void clearwindow(void) +{ + XWindowAttributes winattrs; + GC gc; + XGCValues gcv; + + if (!display || !pixmap) + return; + XGetWindowAttributes(display, window, &winattrs); + gcv.line_width = 1; + gcv.line_style = LineSolid; + gc = XCreateGC(display, pixmap, GCLineWidth | GCLineStyle, &gcv); + XSetState(display, gc, col_background, col_background, GXcopy, + AllPlanes); + XFillRectangle(display, pixmap, gc, 0, 0, + winattrs.width, winattrs.height); + XSetForeground(display, gc, col_zeroline); + XClearArea(display, window, 0, 0, 0, 0, False); + XCopyArea(display, pixmap, window, gr_context, 0, 0, winattrs.width, + winattrs.height, 0, 0); + XFreeGC(display, gc); +} + +/* ---------------------------------------------------------------------- */ + +static Bool predicate(Display *display, XEvent *event, char *arg) +{ + return True; +} + +/* ---------------------------------------------------------------------- */ + +static char *getkey(void) +{ + XWindowAttributes winattrs; + XEvent evt; + static char kbuf[32]; + int i; + + if (!display) + return NULL; + XSync(display, 0); + while (XCheckIfEvent(display, &evt, predicate, NULL)) { + switch (evt.type) { + case KeyPress: + i = XLookupString((XKeyEvent *)&evt, kbuf, sizeof(kbuf)-1, + NULL, NULL); + if (!i) + return NULL; + kbuf[i] = 0; + return kbuf; + case DestroyNotify: + XCloseDisplay(display); + display = NULL; + return NULL; + case Expose: + XGetWindowAttributes(display, window, &winattrs); + XCopyArea(display, pixmap, window, gr_context, 0, 0, + winattrs.width, winattrs.height, 0, 0); + break; + default: + break; + } + } + return NULL; +} + +/* ---------------------------------------------------------------------- */ + +static void printmode(unsigned int mode, unsigned int trigger) +{ + printf("Source: %s%s\n", (mode == SM_DIAGMODE_DEMOD) ? + "demodulator (eye diagram)" : "input (oscilloscope)", + (trigger & SM_DIAGFLAG_DCDGATE) ? " gated with DCD" : ""); +} + +/* ---------------------------------------------------------------------- */ + +static const char *usage_str = +"[-d display] [-i smif] [-c] [-e]\n" +" -d: display host\n" +" -i: specify the name of the baycom kernel driver interface\n" +" -c: toggle carrier trigger\n" +" -e: eye diagram mode\n\n" +" -p: constellation plot\n\n"; + +int main(int argc, char *argv[]) +{ + char *disp = NULL; + unsigned int mode = HDRVC_DIAGMODE_INPUT; + unsigned int trigger = 0; + unsigned int ifflags; + short data[256]; + char *cp; + int ret; + unsigned int samplesperbit; + + progname = *argv; + printf("%s: Version 0.2; (C) 1996-1997 by Thomas Sailer HB9JNX/AE4WA\n", *argv); + hdrvc_args(&argc, argv, "sm0"); + while ((ret = getopt(argc, argv, "d:ecp")) != -1) { + switch (ret) { + case 'd': + disp = optarg; + break; + case 'e': + mode = HDRVC_DIAGMODE_DEMOD; + trigger = HDRVC_DIAGFLAG_DCDGATE; + break; + case 'c': + trigger ^= HDRVC_DIAGFLAG_DCDGATE; + break; + case 'p': + mode = HDRVC_DIAGMODE_CONSTELLATION; + break; + default: + printf("usage: %s %s", *argv, usage_str); + exit(-1); + } + } + hdrvc_init(); +#ifdef HDRVC_KERNEL + ifflags = hdrvc_get_ifflags(); + if (!(ifflags & IFF_UP)) { + fprintf(stderr, "interface %s down\n", hdrvc_ifname()); + exit(1); + } + if (!(ifflags & IFF_RUNNING)) { + fprintf(stderr, "interface %s not running\n", hdrvc_ifname()); + exit(1); + } +#endif /* HDRVC_KERNEL */ + printmode(mode, trigger); + for (;;) { + if ((ret = hdrvc_diag2(mode, trigger, data, sizeof(data) / sizeof(short), + &samplesperbit)) < 0) { + perror("hdrvc_diag2"); + exit(1); + } + if (ret > 0) { + if (!display) { + openwindow(disp, mode == HDRVC_DIAGMODE_CONSTELLATION, + samplesperbit); + clearwindow(); + } + if (mode == SM_DIAGMODE_CONSTELLATION) + drawconstell(data, ret); + else + drawdata(data, ret, mode == HDRVC_DIAGMODE_INPUT, + mode == HDRVC_DIAGMODE_INPUT ? 5:xmul); + } else + usleep(100000L); + if (display) { + if ((cp = getkey())) { + for (; *cp; cp++) { + printf("char pressed: '%c'\n", *cp); + switch (*cp) { + case 'c': + case 'C': + clearwindow(); + printmode(mode, trigger); + break; + case 'q': + case 'Q': + closewindow(); + break; + case 'i': + case 'I': + if (mode == HDRVC_DIAGMODE_CONSTELLATION) + break; + mode = HDRVC_DIAGMODE_INPUT; + clearwindow(); + printmode(mode, trigger); + break; + case 'e': + case 'E': + if (mode == HDRVC_DIAGMODE_CONSTELLATION) + break; + mode = HDRVC_DIAGMODE_DEMOD; + clearwindow(); + printmode(mode, trigger); + break; + case 'd': + case 'D': + trigger ^= HDRVC_DIAGFLAG_DCDGATE; + clearwindow(); + printmode(mode, trigger); + break; + } + } + } + if (!display) + exit(0); + } + } +} + +/* ---------------------------------------------------------------------- */ diff --git a/hdlcutil/smmixer.c b/hdlcutil/smmixer.c new file mode 100644 index 0000000..3cfc7e7 --- /dev/null +++ b/hdlcutil/smmixer.c @@ -0,0 +1,781 @@ +/*****************************************************************************/ + +/* + * smmixer.c -- kernel soundcard radio modem driver mixer utility. + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * Please note that the GPL allows you to use the driver, NOT the radio. + * In order to use the radio, you need a license from the communications + * authority of your country. + * + * + * History: + * 0.1 26.06.96 Started + * 0.2 11.05.97 introduced hdrvcomm.h + */ + +/*****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include "hdrvcomm.h" + +#include +/* ---------------------------------------------------------------------- */ + +static char *progname; +static unsigned int mixdevice; + +/* ---------------------------------------------------------------------- */ + +static int do_mix_ioctl(int cmd, struct sm_mixer_data *mixdat) +{ + struct sm_ioctl par; + int i; + + par.cmd = cmd; + par.data.mix = *mixdat; +#ifdef HDRVC_KERNEL + i = hdrvc_sm_ioctl(cmd, &par); +#endif + *mixdat = par.data.mix; + return i; +} + +/* ---------------------------------------------------------------------- */ + +static unsigned char get_mixer_reg(unsigned char addr) +{ + int i; + struct sm_mixer_data mixdat; + + mixdat.reg = addr; + if ((i = do_mix_ioctl(SMCTL_GETMIXER, &mixdat)) < 0) { + perror("do_mix_ioctl: SMCTL_GETMIXER"); + exit(1); + } + if (!i) + fprintf(stderr, "warning: mixer device %u register %u not " + "accessible for reading!\n", mixdat.mixer_type, + addr); + if (mixdat.mixer_type != mixdevice) { + fprintf(stderr, "error: mixer type changed !?\n"); + exit(2); + } + return mixdat.data; +} + +/* ---------------------------------------------------------------------- */ + +static void set_mixer_reg(unsigned char addr, unsigned char data) +{ + struct sm_mixer_data mixdat; + + mixdat.reg = addr; + mixdat.data = data; + mixdat.mixer_type = mixdevice; + if (do_mix_ioctl(SMCTL_SETMIXER, &mixdat) < 0) { + perror("do_mix_ioctl: SMCTL_SETMIXER"); + exit(1); + } +} + +/* ---------------------------------------------------------------------- */ + +static void display_mixer_ad1848(void) +{ + static const char *src[4] = { "Line", "Aux1", "Mic", "Dac" }; + unsigned char data; + + data = get_mixer_reg(0); + printf("Left input: Source: %-4s Gain: %3ddB\n", src[(data>>6)&3], + (((data & 0xe0) == 0xa0) ? 20 : 0) + (data & 0xf) * 3 / 2); + data = get_mixer_reg(1); + printf("Right input: Source: %-4s Gain: %3ddB\n", src[(data>>6)&3], + (((data & 0xe0) == 0xa0) ? 20 : 0) + (data & 0xf) * 3 / 2); + data = get_mixer_reg(2); + if (!(data & 0x80)) + printf("Left Aux1 mixing: Gain: %3ddB\n", + (8 - (int)(data & 0x1f)) * 3 / 2); + data = get_mixer_reg(3); + if (!(data & 0x80)) + printf("Right Aux1 mixing: Gain: %3ddB\n", + (8 - (int)(data & 0x1f)) * 3 / 2); + data = get_mixer_reg(4); + if (!(data & 0x80)) + printf("Left Aux2 mixing: Gain: %3ddB\n", + (8 - (int)(data & 0x1f)) * 3 / 2); + data = get_mixer_reg(5); + if (!(data & 0x80)) + printf("Right Aux2 mixing: Gain: %3ddB\n", + (8 - (int)(data & 0x1f)) * 3 / 2); + data = get_mixer_reg(6); + if (data & 0x80) + printf("Left output: muted\n"); + else + printf("Left output: Gain: %3ddB\n", + ((int)(data & 0x3f)) * (-3) / 2); + data = get_mixer_reg(7); + if (data & 0x80) + printf("Right output: muted\n"); + else + printf("Right output: Gain: %3ddB\n", + ((int)(data & 0x3f)) * (-3) / 2); + data = get_mixer_reg(13); + if (data & 1) + printf("Digital mix: Gain: %3ddB\n", + ((int)((data >> 2) & 0x3f)) * (-3) / 2); +} + +/* ---------------------------------------------------------------------- */ + +static void display_mixer_cs423x(void) +{ + unsigned char data; + + display_mixer_ad1848(); + data = get_mixer_reg(26); + printf("Mono: %s%s%s Gain: %3ddB\n", + (data & 0x80) ? "input muted, " : "", + (data & 0x40) ? "output muted, " : "", + (data & 0x20) ? "bypass, " : "", + (int)(data & 0xf) * (-3)); + data = get_mixer_reg(27); + if (data & 0x80) + printf("Left output: muted\n"); + else + printf("Left output: Gain: %3ddB\n", + ((int)(data & 0xf)) * (-2)); + data = get_mixer_reg(29); + if (data & 0x80) + printf("Right output: muted\n"); + else + printf("Right output: Gain: %3ddB\n", + ((int)(data & 0xf)) * (-2)); + +} + +/* ---------------------------------------------------------------------- */ + +static void display_mixer_ct1335(void) +{ + unsigned char data; + + data = get_mixer_reg(0x2); + printf("Master volume: %3ddB\n", + (((int)((data >> 1) & 7)) - 7) * 46 / 7); + data = get_mixer_reg(0xa); + printf("Voice volume: %3ddB\n", + (((int)((data >> 1) & 3)) - 3) * 46 / 3); + data = get_mixer_reg(0x6); + printf("MIDI volume: %3ddB\n", + (((int)((data >> 1) & 7)) - 7) * 46 / 7); + data = get_mixer_reg(0x8); + printf("CD volume: %3ddB\n", + (((int)((data >> 1) & 7)) - 7) * 46 / 7); +} + +/* ---------------------------------------------------------------------- */ + +static void display_mixer_ct1345(void) +{ + static const char *src[4] = { "Mic", "CD", "Mic", "Line" }; + unsigned char data, data2; + + data = get_mixer_reg(0xc); + data2 = get_mixer_reg(0xe); + printf("Input source: %s\n", src[(data >> 1) & 3]); + if (!(data & data2 & 0x20)) { + printf("Filter: Low pass %s kHz: ", (data & 0x8) ? + "8.8" : "3.2"); + if (data & 0x20) + printf("output\n"); + else + printf("input%s\n", (data2 & 0x20) ? "" : ", output"); + } + if (data2 & 2) + printf("stereo\n"); + + data = get_mixer_reg(0x22); + printf("Master volume: Left: %3ddB Right: %3ddB\n", + (((int)((data >> 5) & 7)) - 7) * 46 / 7, + (((int)((data >> 1) & 7)) - 7) * 46 / 7); + data = get_mixer_reg(0x4); + printf("Voice volume: Left: %3ddB Right: %3ddB\n", + (((int)((data >> 5) & 7)) - 7) * 46 / 7, + (((int)((data >> 1) & 7)) - 7) * 46 / 7); + data = get_mixer_reg(0x26); + printf("MIDI volume: Left: %3ddB Right: %3ddB\n", + (((int)((data >> 5) & 7)) - 7) * 46 / 7, + (((int)((data >> 1) & 7)) - 7) * 46 / 7); + data = get_mixer_reg(0x28); + printf("CD volume: Left: %3ddB Right: %3ddB\n", + (((int)((data >> 5) & 7)) - 7) * 46 / 7, + (((int)((data >> 1) & 7)) - 7) * 46 / 7); + data = get_mixer_reg(0x2e); + printf("Line volume: Left: %3ddB Right: %3ddB\n", + (((int)((data >> 5) & 7)) - 7) * 46 / 7, + (((int)((data >> 1) & 7)) - 7) * 46 / 7); + data = get_mixer_reg(0x0a); + printf("Mic mixing volume: %3ddB\n", + (((int)((data >> 1) & 3)) - 3) * 46 / 3); +} + +/* ---------------------------------------------------------------------- */ + +static void display_mixer_ct1745(void) +{ + unsigned char data, data2; + + printf("Master volume: Left: %3ddB Right: %3ddB\n", + ((int)((get_mixer_reg(0x30) >> 3) & 0x1f) - 31) * 2, + ((int)((get_mixer_reg(0x31) >> 3) & 0x1f) - 31) * 2); + printf("Voice volume: Left: %3ddB Right: %3ddB\n", + ((int)((get_mixer_reg(0x32) >> 3) & 0x1f) - 31) * 2, + ((int)((get_mixer_reg(0x33) >> 3) & 0x1f) - 31) * 2); + printf("MIDI volume: Left: %3ddB Right: %3ddB\n", + ((int)((get_mixer_reg(0x34) >> 3) & 0x1f) - 31) * 2, + ((int)((get_mixer_reg(0x35) >> 3) & 0x1f) - 31) * 2); + printf("CD volume: Left: %3ddB Right: %3ddB\n", + ((int)((get_mixer_reg(0x36) >> 3) & 0x1f) - 31) * 2, + ((int)((get_mixer_reg(0x37) >> 3) & 0x1f) - 31) * 2); + printf("Line volume: Left: %3ddB Right: %3ddB\n", + ((int)((get_mixer_reg(0x38) >> 3) & 0x1f) - 31) * 2, + ((int)((get_mixer_reg(0x39) >> 3) & 0x1f) - 31) * 2); + printf("Mic volume: %3ddB\n", + ((int)((get_mixer_reg(0x3a) >> 3) & 0x1f) - 31) * 2); + printf("PC speaker volume: %3ddB\n", + ((int)((get_mixer_reg(0x3b) >> 6) & 0x3) - 3) * 6); + printf("Mic gain: %s\n", + (get_mixer_reg(0x43) & 1) ? "fixed 20dB" : "AGC"); + printf("Output gain: Left: %3ddB Right: %3ddB\n", + ((int)((get_mixer_reg(0x41) >> 6) & 3)) * 6, + ((int)((get_mixer_reg(0x42) >> 6) & 3)) * 6); + printf("Input gain: Left: %3ddB Right: %3ddB\n", + ((int)((get_mixer_reg(0x3f) >> 6) & 3)) * 6, + ((int)((get_mixer_reg(0x40) >> 6) & 3)) * 6); + data = (get_mixer_reg(0x44) >> 4) & 0xf; + if (data > 7) + data--; + data2 = (get_mixer_reg(0x45) >> 4) & 0xf; + if (data2 > 7) + data2--; + printf("Treble: Left: %3ddB Right: %3ddB\n", + ((int)data - 7) * 2, ((int)data2 - 7) * 2); + data = (get_mixer_reg(0x46) >> 4) & 0xf; + if (data > 7) + data--; + data2 = (get_mixer_reg(0x47) >> 4) & 0xf; + if (data2 > 7) + data2--; + printf("Bass: Left: %3ddB Right: %3ddB\n", + ((int)data - 7) * 2, ((int)data2 - 7) * 2); + data = get_mixer_reg(0x3c); + printf("Output sources left: PCSpeaker Voice.L%s%s%s\n", + (data & 1) ? " Mic" : "", (data & 4) ? " CD.L" : "", + (data & 0x10) ? " Line.L" : ""); + printf("Output sources right: PCSpeaker Voice.R%s%s%s\n", + (data & 1) ? " Mic" : "", (data & 2) ? " CD.R" : "", + (data & 8) ? " Line.R" : ""); + data = get_mixer_reg(0x3d); + printf("Input sources left: %s%s%s%s%s%s%s\n", + (data & 1) ? " Mic" : "", (data & 2) ? " CD.R" : "", + (data & 4) ? " CD.L" : "", (data & 8) ? " Line.R" : "", + (data & 0x10) ? " Line.L" : "", (data & 0x20) ? " Midi.R" : "", + (data & 0x40) ? " Midi.L" : ""); + data = get_mixer_reg(0x3e); + printf("Input sources right: %s%s%s%s%s%s%s\n", + (data & 1) ? " Mic" : "", (data & 2) ? " CD.R" : "", + (data & 4) ? " CD.L" : "", (data & 8) ? " Line.R" : "", + (data & 0x10) ? " Line.L" : "", (data & 0x20) ? " Midi.R" : "", + (data & 0x40) ? " Midi.L" : ""); +} + +/* ---------------------------------------------------------------------- */ + +static int parse_ad_src(const char *cp) +{ + if (!strcasecmp(cp, "line")) + return 0; + if (!strcasecmp(cp, "aux1")) + return 1; + if (!strcasecmp(cp, "mic")) + return 2; + if (!strcasecmp(cp, "dac")) + return 3; + return -1; +} + +/* ---------------------------------------------------------------------- */ + +static int set_mixer_ad1848(int argc, char *argv[]) +{ + unsigned int mask = 0; + int olvll = 0, olvlr = 0; + int isrcl = 0, isrcr = 0; + int ilvll = 0, ilvlr = 0; + unsigned int data; + + for (; argc >= 1; argc--, argv++) { + if (!strncasecmp(argv[0], "ol=", 3)) { + olvll = strtol(argv[0]+3, NULL, 0); + mask |= 1; + if (olvll < -46 || olvll > 0) { + fprintf(stderr, "output level out of range " + "-100..0dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "or=", 3)) { + olvlr = strtol(argv[0]+3, NULL, 0); + mask |= 2; + if (olvlr < -46 || olvlr > 0) { + fprintf(stderr, "output level out of range " + "-100..0dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "o=", 2)) { + olvll = olvlr = strtol(argv[0]+2, NULL, 0); + mask |= 3; + if (olvll < -46 || olvll > 0) { + fprintf(stderr, "output level out of range " + "-100..0dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "il=", 3)) { + ilvll = strtol(argv[0]+3, NULL, 0); + mask |= 4; + if (ilvll < 0 || ilvll > 43) { + fprintf(stderr, "input gain out of range " + "0..43dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "ir=", 3)) { + ilvlr = strtol(argv[0]+3, NULL, 0); + mask |= 8; + if (ilvll < 0 || ilvll > 43) { + fprintf(stderr, "input gain out of range " + "0..43dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "i=", 2)) { + ilvll = ilvlr = strtol(argv[0]+2, NULL, 0); + mask |= 12; + if (ilvll < 0 || ilvll > 43) { + fprintf(stderr, "input gain out of range " + "0..43dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "sl=", 3)) { + mask |= 16; + if ((isrcl = parse_ad_src(argv[0]+3)) < 0) { + fprintf(stderr, "invalid input source, must " + "be either line, aux1, mic or dac\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "sr=", 3)) { + mask |= 32; + if ((isrcr = parse_ad_src(argv[0]+3)) < 0) { + fprintf(stderr, "invalid input source, must " + "be either line, aux1, mic or dac\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "s=", 2)) { + mask |= 48; + if ((isrcl = isrcr = parse_ad_src(argv[0]+2)) < 0) { + fprintf(stderr, "invalid input source, must " + "be either line, aux1, mic or dac\n"); + return -1; + } + } else { + fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]); + return -1; + } + } + data = get_mixer_reg(0x00); + if (mask & 4) { + data &= 0xc0; + if (ilvll > 23) { + data |= 0x20; + ilvll -= 20; + } + data |= ilvll * 2 / 3; + } + if (mask & 16) + data = (data & 0x3f) | (isrcl << 6); + if ((data & 0xc0) != 0x80) + data &= ~0x20; + set_mixer_reg(0x00, data); + data = get_mixer_reg(0x01); + if (mask & 8) { + data &= 0xc0; + if (ilvlr > 23) { + data |= 0x20; + ilvlr -= 20; + } + data |= ilvlr * 2 / 3; + } + if (mask & 32) + data = (data & 0x3f) | (isrcr << 6); + if ((data & 0xc0) != 0x80) + data &= ~0x20; + set_mixer_reg(0x01, data); + set_mixer_reg(0x02, 0x80); + set_mixer_reg(0x03, 0x80); + set_mixer_reg(0x04, 0x80); + set_mixer_reg(0x05, 0x80); + if (mask & 1) { + if (olvll < -95) + set_mixer_reg(0x06, 0x80); + else + set_mixer_reg(0x06, (olvll * (-2) / 3)); + } + if (mask & 2) { + if (olvlr < -95) + set_mixer_reg(0x07, 0x80); + else + set_mixer_reg(0x07, (olvlr * (-2) / 3)); + } + set_mixer_reg(0x0d, 0x00); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int set_mixer_ct1335(int argc, char *argv[]) +{ + unsigned int mask = 0; + int olvl = 0; + + for (; argc >= 1; argc--, argv++) { + if (!strncasecmp(argv[0], "o=", 2)) { + olvl = strtol(argv[0]+2, NULL, 0); + mask |= 1; + if (olvl < -46 || olvl > 0) { + fprintf(stderr, "output level out of range " + "-46..0dB\n"); + return -1; + } + } else { + fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]); + return -1; + } + } + if (mask & 1) + set_mixer_reg(0x02, (((olvl * 7 / 46) + 7) << 1)); + set_mixer_reg(0x06, 0x00); + set_mixer_reg(0x08, 0x00); + set_mixer_reg(0x0a, 0x06); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int set_mixer_ct1345(int argc, char *argv[]) +{ + unsigned int mask = 0; + int olvll = 0, olvlr = 0; + int isrc = 0; + unsigned int data; + + for (; argc >= 1; argc--, argv++) { + if (!strncasecmp(argv[0], "ol=", 3)) { + olvll = strtol(argv[0]+3, NULL, 0); + mask |= 1; + if (olvll < -46 || olvll > 0) { + fprintf(stderr, "output level out of range " + "-46..0dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "or=", 3)) { + olvlr = strtol(argv[0]+3, NULL, 0); + mask |= 2; + if (olvlr < -46 || olvlr > 0) { + fprintf(stderr, "output level out of range " + "-46..0dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "o=", 2)) { + olvll = olvlr = strtol(argv[0]+2, NULL, 0); + mask |= 3; + if (olvll < -46 || olvll > 0) { + fprintf(stderr, "output level out of range " + "-46..0dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "s=", 2)) { + mask |= 4; + if (!strcasecmp(argv[0]+2, "mic")) + isrc = 0; + else if (!strcasecmp(argv[0]+2, "cd")) + isrc = 1; + else if (!strcasecmp(argv[0]+2, "line")) + isrc = 3; + else { + fprintf(stderr, "invalid input source, must " + "be either mic, cd or line\n"); + return -1; + } + } else { + fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]); + return -1; + } + } + set_mixer_reg(0x04, 0xee); + set_mixer_reg(0x0a, 0x00); + if (mask & 4) + data = (isrc & 3) << 1; + else + data = get_mixer_reg(0x0c) & 0x06; + set_mixer_reg(0x0c, data | 0x20); + set_mixer_reg(0x0e, 0x20); + data = get_mixer_reg(0x22); + if (mask & 1) + data = (data & 0x0f) | (((olvll * 7 / 46) + 7) << 5); + if (mask & 2) + data = (data & 0xf0) | (((olvlr * 7 / 46) + 7) << 1); + set_mixer_reg(0x22, data); + set_mixer_reg(0x26, 0x00); + set_mixer_reg(0x28, 0x00); + set_mixer_reg(0x2e, 0x00); + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static int set_mixer_ct1745(int argc, char *argv[]) +{ + unsigned int mask = 0; + int olvll = 0, olvlr = 0; + int ilvll = 0, ilvlr = 0; + unsigned int insrc = 0; + unsigned int data; + + for (; argc >= 1; argc--, argv++) { + if (!strncasecmp(argv[0], "ol=", 3)) { + olvll = strtol(argv[0]+3, NULL, 0); + mask |= 1; + if (olvll < -62 || olvll > 18) { + fprintf(stderr, "output level out of range " + "-62..18dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "or=", 3)) { + olvlr = strtol(argv[0]+3, NULL, 0); + mask |= 2; + if (olvlr < -62 || olvlr > 18) { + fprintf(stderr, "output level out of range " + "-62..18dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "o=", 2)) { + olvll = olvlr = strtol(argv[0]+2, NULL, 0); + mask |= 3; + if (olvll < -62 || olvll > 18) { + fprintf(stderr, "output level out of range " + "-62..18dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "il=", 3)) { + ilvll = strtol(argv[0]+3, NULL, 0); + mask |= 4; + if (ilvll < -62 || ilvll > 18) { + fprintf(stderr, "input gain out of range " + "-62..18dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "ir=", 3)) { + ilvlr = strtol(argv[0]+3, NULL, 0); + mask |= 8; + if (ilvll < -62 || ilvll > 18) { + fprintf(stderr, "input gain out of range " + "-62..18dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "i=", 2)) { + ilvll = ilvlr = strtol(argv[0]+2, NULL, 0); + mask |= 12; + if (ilvll < -62 || ilvll > 18) { + fprintf(stderr, "input gain out of range " + "-62..18dB\n"); + return -1; + } + } else if (!strncasecmp(argv[0], "s=", 2)) { + mask |= 16; + if (!strcasecmp(argv[0]+2, "mic")) + insrc |= 1; + else if (!strcasecmp(argv[0]+2, "cd.r")) + insrc |= 2; + else if (!strcasecmp(argv[0]+2, "cd.l")) + insrc |= 4; + else if (!strcasecmp(argv[0]+2, "cd")) + insrc |= 6; + else if (!strcasecmp(argv[0]+2, "line.r")) + insrc |= 0x08; + else if (!strcasecmp(argv[0]+2, "line.l")) + insrc |= 0x10; + else if (!strcasecmp(argv[0]+2, "line")) + insrc |= 0x18; + else if (!strcasecmp(argv[0]+2, "midi.r")) + insrc |= 0x20; + else if (!strcasecmp(argv[0]+2, "midi.l")) + insrc |= 0x40; + else if (!strcasecmp(argv[0]+2, "midi")) + insrc |= 0x60; + else { + fprintf(stderr, "invalid input source, must " + "be either line, cd, mic or midi\n"); + return -1; + } + } else { + fprintf(stderr, "invalid parameter \"%s\"\n", argv[0]); + return -1; + } + } + if (mask & 3) { + set_mixer_reg(0x3c, 0); /* output src: only voice and pcspk */ + set_mixer_reg(0x44, 4<<4); /* treble.l: -6dB */ + set_mixer_reg(0x45, 4<<4); /* treble.r: -6dB */ + set_mixer_reg(0x46, 6<<4); /* bass.l: -2dB */ + set_mixer_reg(0x47, 6<<4); /* bass.r: -2dB */ + set_mixer_reg(0x3b, 0); /* PC speaker vol -18dB */ + } + if (mask & 12) + set_mixer_reg(0x43, 1); /* mic: agc off, fixed 20dB gain */ + if (mask & 1) { + data = 0; + while (olvll > 0) { + olvll -= 6; + data += 0x40; + } + set_mixer_reg(0x41, data); /* output gain */ + set_mixer_reg(0x30, 0xf8); /* master vol */ + set_mixer_reg(0x32, (olvll / 2 + 31) << 3); /* voice vol */ + } + if (mask & 2) { + data = 0; + while (olvlr > 0) { + olvlr -= 6; + data += 0x40; + } + set_mixer_reg(0x42, data); /* output gain */ + set_mixer_reg(0x31, 0xf8); /* master vol */ + set_mixer_reg(0x33, (olvlr / 2 + 31) << 3); /* voice vol */ + } + if (mask & 4) { + data = 0; + while (ilvll > 0) { + ilvll -= 6; + data += 0x40; + } + set_mixer_reg(0x3f, data); /* input gain */ + data = (ilvll / 2 + 31) << 3; + set_mixer_reg(0x34, data); /* midi vol */ + set_mixer_reg(0x36, data); /* cd vol */ + set_mixer_reg(0x38, data); /* line vol */ + set_mixer_reg(0x3a, data); /* mic vol */ + } + if (mask & 8) { + data = 0; + while (ilvlr > 0) { + ilvlr -= 6; + data += 0x40; + } + set_mixer_reg(0x40, data); /* input gain */ + data = (ilvlr / 2 + 31) << 3; + set_mixer_reg(0x35, data); /* midi vol */ + set_mixer_reg(0x37, data); /* cd vol */ + set_mixer_reg(0x39, data); /* line vol */ + set_mixer_reg(0x3a, data); /* mic vol */ + } + if (mask & 16) { + set_mixer_reg(0x3d, insrc); /* input sources */ + set_mixer_reg(0x3e, insrc); /* input sources */ + } + return 0; +} + +/* ---------------------------------------------------------------------- */ + +static const char *usage_str = +"[-i smif]\n\n"; + +int main(int argc, char *argv[]) +{ + int c; + struct sm_mixer_data mixdat; + + progname = *argv; + printf("%s: Version 0.2; (C) 1996-1997 by Thomas Sailer HB9JNX/AE4WA\n", *argv); + hdrvc_args(&argc, argv, "sm0"); + while ((c = getopt(argc, argv, "")) != -1) { + switch (c) { + default: + printf("usage: %s %s", *argv, usage_str); + exit(-1); + } + } + hdrvc_init(); + mixdat.reg = 0; + if (do_mix_ioctl(SMCTL_GETMIXER, &mixdat) < 0) { + perror("do_mix_ioctl: SMCTL_GETMIXER"); + exit(1); + } + mixdevice = mixdat.mixer_type; + switch (mixdevice) { + case SM_MIXER_INVALID: + printf("invalid mixer device\n"); + exit(1); + case SM_MIXER_AD1848: + if (optind < argc) + set_mixer_ad1848(argc - optind, argv + optind); + display_mixer_ad1848(); + break; + case SM_MIXER_CRYSTAL: + if (optind < argc) + set_mixer_ad1848(argc - optind, argv + optind); + display_mixer_cs423x(); + break; + case SM_MIXER_CT1335: + if (optind < argc) + set_mixer_ct1335(argc - optind, argv + optind); + display_mixer_ct1335(); + break; + case SM_MIXER_CT1345: + if (optind < argc) + set_mixer_ct1345(argc - optind, argv + optind); + display_mixer_ct1345(); + break; + case SM_MIXER_CT1745: + if (optind < argc) + set_mixer_ct1745(argc - optind, argv + optind); + display_mixer_ct1745(); + break; + default: + printf("unknown mixer device %d\n", mixdevice); + exit(1); + } + exit(0); +} + +/* ---------------------------------------------------------------------- */ diff --git a/hdlcutil/usersmdiag.h b/hdlcutil/usersmdiag.h new file mode 100644 index 0000000..5335002 --- /dev/null +++ b/hdlcutil/usersmdiag.h @@ -0,0 +1,118 @@ +/*****************************************************************************/ + +/* + * usersmdiag.h -- Diagnostics interface. + * + * Copyright (C) 1996 Thomas Sailer (sailer@ife.ee.ethz.ch) + * Swiss Federal Institute of Technology (ETH), Electronics Lab + * + * 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., 675 Mass Ave, Cambridge, MA 02139, USA. + * + * + * This is the Linux realtime sound output driver + */ + +/*****************************************************************************/ + +#ifndef _USERSMDIAG_H +#define _USERSMDIAG_H + +/* --------------------------------------------------------------------- */ + +#define USERSM_KEY_PROJ '0' + +/* --------------------------------------------------------------------- */ + +#define USERSM_CMD_REQ_CHACCESS_PAR 0x00020 +#define USERSM_CMD_ACK_CHACCESS_PAR 0x10021 +#define USERSM_CMD_SET_CHACCESS_PAR 0x00022 + +#define USERSM_CMD_CALIBRATE 0x00030 +#define USERSM_CMD_REQ_CHANNELSTATE 0x00031 +#define USERSM_CMD_ACK_CHANNELSTATE 0x10032 + +#define USERSM_CMD_REQ_DIAG 0x00040 +#define USERSM_CMD_ACK_DIAG 0x10041 + +#define USERSM_CMD_REQ_DRVNAME 0x00050 +#define USERSM_CMD_ACK_DRVNAME 0x10051 +#define USERSM_CMD_REQ_DRVMODE 0x00052 +#define USERSM_CMD_ACK_DRVMODE 0x10053 + +/* + * diagnose modes; same as in + */ +#define USERSM_DIAGMODE_OFF 0 +#define USERSM_DIAGMODE_INPUT 1 +#define USERSM_DIAGMODE_DEMOD 2 +#define USERSM_DIAGMODE_CONSTELLATION 3 + +/* + * diagnose flags; same as in + */ +#define USERSM_DIAGFLAG_DCDGATE (1<<0) +#define USERSM_DIAGFLAG_VALID (1<<1) + +/* --------------------------------------------------------------------- */ + +#define DIAGDATALEN 64 + +/* --------------------------------------------------------------------- */ + +struct usersmmsg { + struct usersm_hdr { + long type; + unsigned int channel; + } hdr; + union { + struct usersm_chaccess_par { + int tx_delay; /* the transmitter keyup delay in 10ms units */ + int tx_tail; /* the transmitter keyoff delay in 10ms units */ + int slottime; /* the slottime in 10ms; usually 10 = 100ms */ + int ppersist; /* the p-persistence 0..255 */ + int fulldup; /* some driver do not support full duplex, setting */ + /* this just makes them send even if DCD is on */ + } cp; + + int calib; + + struct usersm_channel_state { + int ptt; + int dcd; + int ptt_keyed; + unsigned long tx_packets; + unsigned long tx_errors; + unsigned long rx_packets; + unsigned long rx_errors; + } cs; + + struct usersm_diag { + unsigned int mode; + unsigned int flags; + unsigned int samplesperbit; + unsigned int datalen; + } diag; + + struct usersm_diag_out { + struct usersm_diag diag; + short samples[DIAGDATALEN]; + } diag_out; + + unsigned char by[0]; + } data; +}; + +/* --------------------------------------------------------------------- */ +#endif /* _USERSMDIAG_H */ -- cgit v1.2.3