/* Scc modem monitor 
 * Arjan Filius, iafilius@xs4all.nl
 * For getting the DCD status it was needed change scc.c/scc.h in kernel (2.1.132)
 */

#include <stdio.h>
#include <unistd.h>
#include <stdio.h>
#include <fcntl.h>
#include <termios.h>
#include <strings.h>
#include <ctype.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <net/if.h>
#include <errno.h>
#include <linux/scc.h>
#include <string.h>
#include <time.h>


/* From scc.h: 
struct scc_stat {
        long rxints;            / * Receiver interrupts * /
        long txints;            / * Transmitter interrupts * /
        long exints;            / * External/status interrupts * /
        long spints;            / * Special receiver interrupts * /

        long txframes;          / * Packets sent * / 
        long rxframes;          / * Number of Frames Actually Received * /
        long rxerrs;            / * CRC Errors * /
        long txerrs;            / * KISS errors * /

        unsigned int nospace;   / * "Out of buffers" * /
        unsigned int rx_over;   / * Receiver Overruns * /
        unsigned int tx_under;  / * Transmitter Underruns * /

        unsigned int tx_state;  / * Transmitter state * /
        int tx_queued;          / * tx frames enqueued * /

        unsigned int maxqueue;  / * allocated tx_buffers * /
        unsigned int bufsize;   / * used buffersize * /
};
*/

struct ifreq ifr0,ifr1,ifr2,ifr3;
struct scc_stat stat0,stat1,stat2,stat3;


#define SCC0	"scc0"
#define SCC1	"scc1"
#define SCC2	"scc2"
#define SCC3	"scc3"

void print_rx(struct scc_stat* stat);

char oldstatus[256];
char newstatus[256];

int main(void)
{
int fd;
int error;

fd = socket(AF_AX25, SOCK_DGRAM, 0);

strcpy(ifr0.ifr_name,SCC0);
strcpy(ifr1.ifr_name,SCC1);
strcpy(ifr2.ifr_name,SCC2);

ifr0.ifr_data = (caddr_t) &stat0;
ifr1.ifr_data = (caddr_t) &stat1;
ifr2.ifr_data = (caddr_t) &stat2;

printf("-------Date-------------|-msec--|-scc0:tx rx-|-scc1:tx rx-|-scc2:tx rx-\n");

while(1)
{

/* Get status */
ioctl(fd, SIOCSCCGSTAT, &ifr0);
ioctl(fd, SIOCSCCGSTAT, &ifr1);
ioctl(fd, SIOCSCCGSTAT, &ifr2);

/* Print them in a string */
print_rx(&stat0);
print_rx(&stat1);
print_rx(&stat2);

/* Only print changed results */
if(strcmp(newstatus,oldstatus)!=0)
	{
	struct tm* tm;
	time_t t;
	char buffer[256];
	char* p;
	struct timeval tv;
	struct timezone tz;
	    
	t=time(NULL);
	tm=localtime(&t);
	gettimeofday(&tv,&tz);
	
	strcpy(buffer,ctime(&t));
	p=strchr(buffer,'\n'); if (p) *p='\0';
	printf("%s  %03d  %s\n",buffer,tv.tv_usec/1000,newstatus);
	strcpy(oldstatus,newstatus);	/* Save old value */
	}
*newstatus='\0';
usleep(5000);	/* Adjustable, I like it this fast */
}



return(0);
}


/* From scc.h:
enum TX_state {
        TXS_IDLE,       / * Transmitter off, no data pending * /
        TXS_BUSY,       / * waiting for permission to send / tailtime * /
        TXS_ACTIVE,     / * Transmitter on, sending data * /
        TXS_NEWFRAME,   / * reset CRC and send (next) frame * /
        TXS_IDLE2,      / * Transmitter on, no data pending * /
        TXS_WAIT,       / * Waiting for Mintime to expire * /
        TXS_TIMEOUT     / * We had a transmission timeout * /
};

*/


void print_rx(struct scc_stat* stat_current)
{
char* state;
char buffer[256];

        switch(stat_current->tx_state)
        {
                case    TXS_IDLE:
                        state="idle";
                        break;
                case    TXS_BUSY:
                        state="busy";
                        break;
                case    TXS_ACTIVE:
                        state= "active";
                        break;
                case    TXS_NEWFRAME:
                        state= "kick";
                        break;
                case    TXS_IDLE2:
                        state= "keyed";
                        break;
                case    TXS_WAIT:
                        state= "wait";
                        break;
                case    TXS_TIMEOUT:
                        state= "timeout";
        }

sprintf(buffer,"%10s %2d",state,stat_current->rx_state);
strcat(newstatus,buffer);
}
