mirror of
				https://github.com/saitohirga/WSJT-X.git
				synced 2025-10-31 13:10:19 -04:00 
			
		
		
		
	
		
			
	
	
		
			342 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
		
		
			
		
	
	
			342 lines
		
	
	
		
			6.5 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
|  | #include <stdio.h>
 | ||
|  | #include <fcntl.h>
 | ||
|  | #include <unistd.h>
 | ||
|  | #include <stdio.h>
 | ||
|  | #include <stdlib.h>
 | ||
|  | #include <stddef.h>
 | ||
|  | //#include <sys/ioctl.h>
 | ||
|  | //#include <linux/ppdev.h>
 | ||
|  | //#include <linux/parport.h>
 | ||
|  | //#include <dev/ppbus/ppi.h>
 | ||
|  | //#include <dev/ppbus/ppbconf.h>
 | ||
|  | 
 | ||
|  | int lp_reset (int fd); | ||
|  | int lp_ptt (int fd, int onoff); | ||
|  | 
 | ||
|  | #ifdef HAVE_SYS_STAT_H
 | ||
|  | # include <sys/stat.h>
 | ||
|  | #endif
 | ||
|  | #if (defined(__unix__) || defined(unix)) && !defined(USG)
 | ||
|  | # include <sys/param.h>
 | ||
|  | #endif
 | ||
|  | 
 | ||
|  | #include <string.h>
 | ||
|  | /* parport functions */ | ||
|  | 
 | ||
|  | int dev_is_parport(int fd); | ||
|  | int ptt_parallel(int fd, int *ntx, int *iptt); | ||
|  | int ptt_serial(int fd, int *ntx, int *iptt); | ||
|  | 
 | ||
|  | int fd=-1;		/* Used for both serial and parallel */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * ptt_ | ||
|  |  * | ||
|  |  * generic unix PTT routine called from Fortran | ||
|  |  * | ||
|  |  * Inputs	 | ||
|  |  * unused	Unused, to satisfy old windows calling convention | ||
|  |  * ptt_port	device name serial or parallel | ||
|  |  * ntx		pointer to fortran command on or off | ||
|  |  * iptt		pointer to fortran command status on or off | ||
|  |  * Returns	- non 0 if error | ||
|  | */ | ||
|  | 
 | ||
|  | /* Tiny state machine */ | ||
|  | #define STATE_PORT_CLOSED		0
 | ||
|  | #define STATE_PORT_OPEN_PARALLEL	1
 | ||
|  | #define STATE_PORT_OPEN_SERIAL		2
 | ||
|  | 
 | ||
|  | int | ||
|  | ptt_(int *unused, char *ptt_port, int *ntx, int *ndtr, int *iptt) | ||
|  | { | ||
|  |   static int state=0; | ||
|  |   char *p; | ||
|  | 
 | ||
|  |   /* In the very unlikely event of a NULL pointer, just return.
 | ||
|  |    * Yes, I realise this should not be possible in WSJT. | ||
|  |    */ | ||
|  |   if (ptt_port == NULL) { | ||
|  |     *iptt = *ntx; | ||
|  |     return (0); | ||
|  |   } | ||
|  |      | ||
|  |   switch (state) { | ||
|  |   case STATE_PORT_CLOSED: | ||
|  | 
 | ||
|  |      /* Remove trailing ' ' */ | ||
|  |     if ((p = strchr(ptt_port, ' ')) != NULL) | ||
|  |       *p = '\0'; | ||
|  | 
 | ||
|  |     /* If all that is left is a '\0' then also just return */ | ||
|  |     if (*ptt_port == '\0') { | ||
|  |       *iptt = *ntx; | ||
|  |       return(0); | ||
|  |     } | ||
|  | 
 | ||
|  |     if ((fd = open(ptt_port, O_RDWR|O_NONBLOCK)) < 0) { | ||
|  | 	fprintf(stderr, "Can't open %s.\n", ptt_port); | ||
|  | 	return (1); | ||
|  |     } | ||
|  | 
 | ||
|  |     if (dev_is_parport(fd)) { | ||
|  |       state = STATE_PORT_OPEN_PARALLEL; | ||
|  |       lp_reset(fd); | ||
|  |       ptt_parallel(fd, ntx, iptt); | ||
|  |     } else { | ||
|  |       state = STATE_PORT_OPEN_SERIAL; | ||
|  |       ptt_serial(fd, ntx, iptt); | ||
|  |     } | ||
|  |     break; | ||
|  | 
 | ||
|  |   case STATE_PORT_OPEN_PARALLEL: | ||
|  |     ptt_parallel(fd, ntx, iptt); | ||
|  |     break; | ||
|  | 
 | ||
|  |   case STATE_PORT_OPEN_SERIAL: | ||
|  |     ptt_serial(fd, ntx, iptt); | ||
|  |     break; | ||
|  | 
 | ||
|  |   default: | ||
|  |     close(fd); | ||
|  |     fd = -1; | ||
|  |     state = STATE_PORT_CLOSED; | ||
|  |     break; | ||
|  |   } | ||
|  |   return(0); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * ptt_serial | ||
|  |  * | ||
|  |  * generic serial unix PTT routine called indirectly from Fortran | ||
|  |  * | ||
|  |  * fd		- already opened file descriptor | ||
|  |  * ntx		- pointer to fortran command on or off | ||
|  |  * iptt		- pointer to fortran command status on or off | ||
|  |  */ | ||
|  | 
 | ||
|  | int | ||
|  | ptt_serial(int fd, int *ntx, int *iptt) | ||
|  | { | ||
|  |   int control = TIOCM_RTS | TIOCM_DTR; | ||
|  | 
 | ||
|  |   if(*ntx) { | ||
|  |     ioctl(fd, TIOCMBIS, &control);               /* Set DTR and RTS */ | ||
|  |     *iptt = 1; | ||
|  |   } else { | ||
|  |     ioctl(fd, TIOCMBIC, &control); | ||
|  |     *iptt = 0; | ||
|  |   } | ||
|  |   return(0); | ||
|  | } | ||
|  | 
 | ||
|  | 
 | ||
|  | /* parport functions */ | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * dev_is_parport(fd): | ||
|  |  * | ||
|  |  * inputs	- Already open fd | ||
|  |  * output	- 1 if parallel port, 0 if not | ||
|  |  * side effects	- Unfortunately, this is platform specific. | ||
|  |  */ | ||
|  | 
 | ||
|  | #if defined(HAVE_LINUX_PPDEV_H)                /* Linux (ppdev) */
 | ||
|  | 
 | ||
|  | int | ||
|  | dev_is_parport(int fd) | ||
|  | { | ||
|  |        struct stat st; | ||
|  |        int m; | ||
|  | 
 | ||
|  |        if ((fstat(fd, &st) == -1) || | ||
|  | 	   ((st.st_mode & S_IFMT) != S_IFCHR) || | ||
|  | 	   (ioctl(fd, PPGETMODE, &m) == -1)) | ||
|  | 	 return(0); | ||
|  | 
 | ||
|  |        return(1); | ||
|  | } | ||
|  | 
 | ||
|  | #elif defined(HAVE_DEV_PPBUS_PPI_H)    /* FreeBSD (ppbus/ppi) */
 | ||
|  | 
 | ||
|  | int | ||
|  | dev_is_parport(int fd) | ||
|  | { | ||
|  |        struct stat st; | ||
|  |        unsigned char c; | ||
|  | 
 | ||
|  |        if ((fstat(fd, &st) == -1) || | ||
|  | 	   ((st.st_mode & S_IFMT) != S_IFCHR) || | ||
|  | 	   (ioctl(fd, PPISSTATUS, &c) == -1)) | ||
|  | 	 return(0); | ||
|  | 
 | ||
|  |        return(1); | ||
|  | } | ||
|  | 
 | ||
|  | #else                                  /* Fallback (nothing) */
 | ||
|  | 
 | ||
|  | int | ||
|  | dev_is_parport(int fd) | ||
|  | { | ||
|  |        return(0); | ||
|  | } | ||
|  | 
 | ||
|  | #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
 | ||
|  | 
 | ||
|  | /* Initialise a parallel port, given open fd */ | ||
|  | 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); | ||
|  | 		return(-1); | ||
|  | 	} | ||
|  | 
 | ||
|  | 	if (ioctl (fd, PPEXCL, NULL) == -1) | ||
|  | 	{ | ||
|  | 		fprintf(stderr, "Parallel port is already in use.\n"); | ||
|  | 		close (fd); | ||
|  | 		return(-1); | ||
|  | 	} | ||
|  | 	if (ioctl (fd, PPCLAIM, NULL) == -1) | ||
|  | 	{ | ||
|  | 		fprintf(stderr, "Claiming parallel port.\n"); | ||
|  | 		fprintf(stderr, "HINT: did you unload the lp kernel module?"); | ||
|  | 		close (fd); | ||
|  | 		return(-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); | ||
|  | } | ||
|  | 
 | ||
|  | /*
 | ||
|  |  * ptt_parallel | ||
|  |  * | ||
|  |  * generic parallel unix PTT routine called indirectly from Fortran | ||
|  |  * | ||
|  |  * fd		- already opened file descriptor | ||
|  |  * ntx		- pointer to fortran command on or off | ||
|  |  * iptt		- pointer to fortran command status on or off | ||
|  |  */ | ||
|  | 
 | ||
|  | int | ||
|  | ptt_parallel(int fd, int *ntx, int *iptt) | ||
|  | { | ||
|  |   if(*ntx) { | ||
|  |     lp_ptt(fd, 1); | ||
|  |     *iptt=1; | ||
|  |   }  else { | ||
|  |     lp_ptt(fd, 0); | ||
|  |     *iptt=0; | ||
|  |   } | ||
|  |   return(0); | ||
|  | } |