mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-31 13:10:19 -04:00 
			
		
		
		
	git-svn-id: svn+ssh://svn.code.sf.net/p/wsjt/wsjt/trunk@167 ab8295b8-cf94-4d9e-aec4-7959e3be5d79
		
			
				
	
	
		
			388 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			388 lines
		
	
	
		
			8.3 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /*
 | |
|  * WSJT is Copyright (c) 2001-2006 by Joseph H. Taylor, Jr., K1JT, 
 | |
|  * and is licensed under the GNU General Public License (GPL).
 | |
|  *
 | |
|  * Code used from cwdaemon for parallel port ptt only.
 | |
|  *
 | |
|  * cwdaemon - morse sounding daemon for the parallel or serial port
 | |
|  * Copyright (C) 2002 -2005 Joop Stakenborg <pg4i@amsat.org>
 | |
|  *                       and many authors, see the AUTHORS file.
 | |
|  *
 | |
|  * 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 Library 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
 | |
|  */
 | |
| # if HAVE_STDIO_H
 | |
| # include <stdio.h>
 | |
| #endif
 | |
| #if STDC_HEADERS
 | |
| # include <stdlib.h>
 | |
| # include <stddef.h>
 | |
| #else
 | |
| # if HAVE_STDLIB_H
 | |
| #  include <stdlib.h>
 | |
| # endif
 | |
| #endif
 | |
| #if HAVE_UNISTD_H
 | |
| # include <unistd.h>
 | |
| #endif
 | |
| #if HAVE_SYS_IOCTL_H
 | |
| # include <sys/ioctl.h>
 | |
| #endif
 | |
| #if HAVE_FCNTL_H
 | |
| # include <fcntl.h>
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_SYS_STAT_H
 | |
| # include <sys/stat.h>
 | |
| #endif
 | |
| #if (defined(__unix__) || defined(unix)) && !defined(USG)
 | |
| # include <sys/param.h>
 | |
| #endif
 | |
| 
 | |
| int fd;			/* Used for both serial and parallel */
 | |
| 
 | |
| #ifdef USE_SERIAL
 | |
| 
 | |
| /* First cut, note that this only distinguishes Linux from BSDs,
 | |
|  * it will be done better later on using configure. N.B. that OSX
 | |
|  * will come up as BSD but I think this is also the right serial port
 | |
|  * for OSX. -db
 | |
|  */
 | |
| #if defined(BSD)
 | |
| #define TTYNAME "/dev/cuad%d"	/* Use non blocking form */
 | |
| #else
 | |
| #include <sys/io.h>
 | |
| #define TTYNAME	"/dev/ttyUSB%d"
 | |
| #endif
 | |
| 
 | |
| /* Not quite right for size but '%d + 1' should be plenty enough -db */
 | |
| /* As TTYNAME is a string, just at 20 chars do udevd is happier. */
 | |
| /* E.g. USB serial ports appear as /dev/ttyUSB0 */
 | |
| #define TTYNAME_SIZE	sizeof(TTYNAME)+20
 | |
| 
 | |
| int
 | |
| ptt_(int *nport, int *ntx, int *iptt)
 | |
| {
 | |
|   /* Fixme, nport should be a sting and not a number */
 | |
|   static int nopen=0;
 | |
|   int control = TIOCM_RTS | TIOCM_DTR;
 | |
| 
 | |
|   char s[TTYNAME_SIZE];	
 | |
| 
 | |
|   if(*nport < 0) {
 | |
|     *iptt=*ntx;
 | |
|     return(0);
 | |
|   }
 | |
| 
 | |
|   if(*ntx && (!nopen)) {
 | |
|     snprintf(s, TTYNAME_SIZE, TTYNAME, (*nport) - 1);	/* Comport 1 == dev 0 */
 | |
|     s[TTYNAME_SIZE] = '\0';
 | |
| 
 | |
|     /* open the device */
 | |
|     printf("Opening %s\n", s);
 | |
|     if ((fd = open(s, O_RDWR | O_NDELAY)) < 0) {
 | |
|       fprintf(stderr, "Can't open %s.\n", s);
 | |
|       return(1);
 | |
|     }
 | |
| 
 | |
|     nopen=1;
 | |
|     return(0);
 | |
|   }
 | |
| 
 | |
|   if(*ntx && nopen) {
 | |
|     ioctl(fd, TIOCMBIS, &control);               // Set DTR and RTS
 | |
|     *iptt=1;
 | |
|   }
 | |
| 
 | |
|   else {
 | |
|     ioctl(fd, TIOCMBIC, &control);
 | |
|     close(fd);
 | |
|     *iptt=0;
 | |
|     nopen=0;
 | |
|   }
 | |
|   return(0);
 | |
| }
 | |
| #endif
 | |
| 
 | |
| #ifdef USE_PARALLEL
 | |
| 
 | |
| #ifdef HAVE_LINUX_PPDEV_H
 | |
| # include <linux/ppdev.h>
 | |
| # include <linux/parport.h>
 | |
| #endif
 | |
| #ifdef HAVE_DEV_PPBUS_PPI_H
 | |
| # include <dev/ppbus/ppi.h>
 | |
| # include <dev/ppbus/ppbconf.h>
 | |
| #endif
 | |
| #ifdef HAVE_SYS_STAT_H
 | |
| # include <sys/stat.h>
 | |
| #endif
 | |
| #if (defined(__unix__) || defined(unix)) && !defined(USG)
 | |
| # include <sys/param.h>
 | |
| #endif
 | |
| 
 | |
| /* parport functions */
 | |
| 
 | |
| int lp_reset (int fd);
 | |
| int lp_ptt (int fd, int onoff);
 | |
| 
 | |
| /*
 | |
|  * dev_is_parport(name): check to see whether 'name' is a parallel
 | |
|  *     port type character device.  Returns non-zero if the device is
 | |
|  *     capable of use for a parallel port based keyer, and zero if it
 | |
|  *     is not.  Unfortunately, this is platform specific.
 | |
|  */
 | |
| 
 | |
| #if defined(HAVE_LINUX_PPDEV_H)                /* Linux (ppdev) */
 | |
| 
 | |
| int
 | |
| dev_is_parport(const char *fname)
 | |
| {
 | |
|        char nm[MAXPATHLEN];
 | |
|        struct stat st;
 | |
|        int fd, m;
 | |
| 
 | |
|        m = snprintf(nm, sizeof(nm), "/dev/%s", fname);
 | |
|        if (m >= sizeof(nm))
 | |
|                return (-1);
 | |
|        if ((fd = open(nm, O_RDWR | O_NONBLOCK)) == -1)
 | |
|                return (-1);
 | |
|        if (fstat(fd, &st) == -1)
 | |
|                goto out;
 | |
|        if ((st.st_mode & S_IFMT) != S_IFCHR)
 | |
|                goto out;
 | |
|        if (ioctl(fd, PPGETMODE, &m) == -1)
 | |
|                goto out;
 | |
|        return (fd);
 | |
| out:
 | |
|        close(fd);
 | |
|        return (-1);
 | |
| }
 | |
| 
 | |
| #elif defined(HAVE_DEV_PPBUS_PPI_H)    /* FreeBSD (ppbus/ppi) */
 | |
| 
 | |
| int
 | |
| dev_is_parport(const char *fname)
 | |
| {
 | |
|        char nm[MAXPATHLEN];
 | |
|        struct stat st;
 | |
|        unsigned char c;
 | |
|        int fd, m;
 | |
| 
 | |
|        m = snprintf(nm, sizeof(nm), "/dev/%s", fname);
 | |
|        if (m >= sizeof(nm))
 | |
|                return (-1);
 | |
|        if ((fd = open(nm, O_RDWR | O_NONBLOCK)) == -1)
 | |
|                return (-1);
 | |
|        if (fstat(fd, &st) == -1)
 | |
|                goto out;
 | |
|        if ((st.st_mode & S_IFMT) != S_IFCHR)
 | |
|                goto out;
 | |
|        if (ioctl(fd, PPISSTATUS, &c) == -1)
 | |
|                goto out;
 | |
|        return (fd);
 | |
| out:
 | |
|        close(fd);
 | |
|        return (-1);
 | |
| }
 | |
| 
 | |
| #else                                  /* Fallback (nothing) */
 | |
| 
 | |
| int
 | |
| dev_is_parport(const char *fname)
 | |
| {
 | |
|        return (-1);
 | |
| }
 | |
| 
 | |
| #endif
 | |
| /* Linux wrapper around PPFCONTROL */
 | |
| #ifdef HAVE_LINUX_PPDEV_H
 | |
| static void
 | |
| parport_control (int fd, unsigned char controlbits, int values)
 | |
| {
 | |
| 	struct ppdev_frob_struct frob;
 | |
| 	frob.mask = controlbits;
 | |
| 	frob.val = values;
 | |
| 
 | |
| 	if (ioctl (fd, PPFCONTROL, &frob) == -1)
 | |
| 	{
 | |
| 		fprintf(stderr, "Parallel port PPFCONTROL");
 | |
| 		exit (1);
 | |
| 	}
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* FreeBSD wrapper around PPISCTRL */
 | |
| #ifdef HAVE_DEV_PPBUS_PPI_H
 | |
| static void
 | |
| parport_control (int fd, unsigned char controlbits, int values)
 | |
| {
 | |
| 	unsigned char val;
 | |
| 
 | |
| 	if (ioctl (fd, PPIGCTRL, &val) == -1)
 | |
| 	{
 | |
| 		fprintf(stderr, "Parallel port PPIGCTRL");
 | |
| 		exit (1);
 | |
| 	}
 | |
| 
 | |
| 	val &= ~controlbits;
 | |
| 	val |= values;
 | |
| 
 | |
| 	if (ioctl (fd, PPISCTRL, &val) == -1)
 | |
| 	{
 | |
| 		fprintf(stderr, "Parallel port PPISCTRL");
 | |
| 		exit (1);
 | |
| 	}
 | |
| }
 | |
| #endif
 | |
| 
 | |
| /* open port and setup ppdev */
 | |
| int
 | |
| lp_init (int fd)
 | |
| {
 | |
| #ifdef HAVE_LINUX_PPDEV_H
 | |
| 	int mode;
 | |
| #endif
 | |
| 
 | |
| #ifdef HAVE_LINUX_PPDEV_H
 | |
| 	mode = PARPORT_MODE_PCSPP;
 | |
| 
 | |
| 	if (ioctl (fd, PPSETMODE, &mode) == -1)
 | |
| 	{
 | |
| 		fprintf(stderr, "Setting parallel port mode");
 | |
| 		close (fd);
 | |
| 		exit (1);
 | |
| 	}
 | |
| 
 | |
| 	if (ioctl (fd, PPEXCL, NULL) == -1)
 | |
| 	{
 | |
| 		fprintf(stderr, "Parallel port %s is already in use", dev->desc);
 | |
| 		close (fd);
 | |
| 		exit (1);
 | |
| 	}
 | |
| 	if (ioctl (fd, PPCLAIM, NULL) == -1)
 | |
| 	{
 | |
| 		fprintf(stderr, "Claiming parallel port %s", dev->desc);
 | |
| 		debug ("HINT: did you unload the lp kernel module?");
 | |
| 		debug ("HINT: perhaps there is another cwdaemon running?");
 | |
| 		close (fd);
 | |
| 		exit (1);
 | |
| 	}
 | |
| 
 | |
| 	/* Enable CW & PTT - /STROBE bit (pin 1) */
 | |
| 	parport_control (fd, PARPORT_CONTROL_STROBE, PARPORT_CONTROL_STROBE);
 | |
| #endif
 | |
| #ifdef HAVE_DEV_PPBUS_PPI_H
 | |
| 	parport_control (fd, STROBE, STROBE);
 | |
| #endif
 | |
| 	lp_reset (fd);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* release ppdev and close port */
 | |
| int
 | |
| lp_free (int fd)
 | |
| {
 | |
| #ifdef HAVE_LINUX_PPDEV_H
 | |
| 	lp_reset (fd);
 | |
| 
 | |
| 	/* Disable CW & PTT - /STROBE bit (pin 1) */
 | |
| 	parport_control (fd, PARPORT_CONTROL_STROBE, 0);
 | |
| 
 | |
| 	ioctl (fd, PPRELEASE);
 | |
| #endif
 | |
| #ifdef HAVE_DEV_PPBUS_PPI_H
 | |
| 	/* Disable CW & PTT - /STROBE bit (pin 1) */
 | |
| 	parport_control (fd, STROBE, 0);
 | |
| #endif
 | |
| 	close (fd);
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* set to a known state */
 | |
| int
 | |
| lp_reset (int fd)
 | |
| {
 | |
| #if defined (HAVE_LINUX_PPDEV_H) || defined (HAVE_DEV_PPBUS_PPI_H)
 | |
| 	lp_ptt (fd, 0);
 | |
| #endif
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* SSB PTT keying - /INIT bit (pin 16) (inverted) */
 | |
| int
 | |
| lp_ptt (int fd, int onoff)
 | |
| {
 | |
| #ifdef HAVE_LINUX_PPDEV_H
 | |
| 	if (onoff == 1)
 | |
| 		parport_control (fd, PARPORT_CONTROL_INIT,
 | |
| 				PARPORT_CONTROL_INIT);
 | |
| 	else
 | |
| 		parport_control (fd, PARPORT_CONTROL_INIT, 0);
 | |
| #endif
 | |
| #ifdef HAVE_DEV_PPBUS_PPI_H
 | |
| 	if (onoff == 1)
 | |
| 		parport_control (fd, nINIT,
 | |
| 				nINIT);
 | |
| 	else
 | |
| 		parport_control (fd, nINIT, 0);
 | |
| #endif
 | |
| 	return 0;
 | |
| }
 | |
| 
 | |
| /* XXX I am totally unsure of this, LPNAME should come from
 | |
|  * the WSJT.INI instead but for now this should work -- db
 | |
|  */
 | |
| #ifdef BSD
 | |
| #define LPNAME "lpt%d"
 | |
| #else
 | |
| #define LPNAME "lp%d"
 | |
| #endif
 | |
| #define LPNAME_SIZE (sizeof(LPNAME))
 | |
| 
 | |
| int
 | |
| ptt_(int *nport, int *ntx, int *iptt)
 | |
| {
 | |
|   static int nopen=0;
 | |
|   int fd;
 | |
|   char s[LPNAME_SIZE];	
 | |
| 
 | |
|   if(*nport < 0) {
 | |
|     *iptt=*ntx;
 | |
|     return(0);
 | |
|   }
 | |
| 
 | |
|   if(*ntx && (!nopen)) {
 | |
|     snprintf(s, LPNAME_SIZE, LPNAME, (*nport) - 1);	/* Comport 1 == dev 0 */
 | |
|     s[LPNAME_SIZE] = '\0';
 | |
| 
 | |
|     if ((fd = dev_is_parport(s)) < 0) {
 | |
|       fprintf(stderr, "Can't use %s.", s);
 | |
|       return(1);
 | |
|     }
 | |
| 
 | |
|     if(*ntx && nopen) {
 | |
|       lp_ptt(fd, 1);
 | |
|       *iptt=1;
 | |
|     }  else {
 | |
|       lp_ptt(fd, 0);
 | |
|       close(fd);
 | |
|       *iptt=0;
 | |
|       nopen=0;
 | |
|     }
 | |
|   }
 | |
|   return(0);
 | |
| }
 | |
| #endif
 |