home *** CD-ROM | disk | FTP | other *** search
- /************************************************************************/
- /* EXAMPLE.C Jonathan Naylor G4KLX 13th January 1990*/
- /**/
- /* This program demonstrates the use of the INT 14H interface for*/
- /* applications programs to access the G8BPQ node software.*/
- /* The important routines have comments associated with them.*/
- /* It was compiled using Microsoft C 5.10, it will probably compile*/
- /* under Microsoft QuickC as well.*/
- /**/
- /* Any comments, queries etc about this code, should be directed to me*/
- /* and not to John G8BPQ. He is busy enough supporting the Node s/ware*/
- /* without answering questions about code he hasn't written.*/
- /**/
- /* Packet:G4KLX @ GB7DAD*/
- /* Address:24 Castle View Drive*/
- /*Cromford*/
- /*Matlock*/
- /*Derbyshire DE4 3RL*/
- /* Telephone:0629 822037*/
- /************************************************************************/
-
- #include <stdio.h>
- #include <string.h>
- #include <conio.h>
- #include <time.h>
- #include <dos.h>
-
- #define TRUE 1
- #define FALSE 0
-
- int Check_BPQ(int);
- void Raise_RTS(int);
- void Lower_RTS(int);
- void Send_Break(int);
- int Write_TNC(int, char *, unsigned int);
- void Return_To_Node(int);
- int Connected(char *, int);
- int Read_TNC(int, char *, unsigned int);
- void Set_TNC(int, int);
- void Reset_TNC(int);
- void cru(char *);
- void Print_TNC(int);
- void Delay(int);
-
- int main(int argc, char *argv[])
- {
- char callsign[15];
- char buffer[50];
- int appl_number;
- int port;
- int i;
-
- if (argc != 3)
- {
- fprintf(stderr, "Usage: example port application_number\n");
- exit(1);
- }
-
- /* The INT 14H port number is 1 below the commonly used port*/
- /* numbers. eg COM1: = 0, COM2: = 1 etc.*/
-
- port = atoi(argv[1]) - 1;
-
- appl_number = atoi(argv[2]);
-
- if (!Check_BPQ(port))
- exit(1);
-
- Set_TNC(appl_number, port);
-
- while (!kbhit())
- {
- if (Connected(callsign, port))
- {
- Print_TNC(port);
-
- Send_Break(port);
-
- strcpy(buffer, "CONV\r");
- Write_TNC(port, buffer, strlen(buffer));
- Print_TNC(port);
-
- sprintf(buffer, "Hello %s\r", callsign);
- Write_TNC(port, buffer, strlen(buffer));
- Print_TNC(port);
-
- strcpy(buffer, "Welcome to the G4KLX example program\r");
- Write_TNC(port, buffer, strlen(buffer));
- Print_TNC(port);
-
- strcpy(buffer, "Bye Bye\r");
- Write_TNC(port, buffer, strlen(buffer));
- Print_TNC(port);
-
- /* Returning the user to the Node immediately */
- /* appears to lose the sent data, hence the delay */
-
- Delay(3);
-
- Return_To_Node(port);
-
- Print_TNC(port);
- }
- }
-
- Reset_TNC(port);
-
- return(0);
- }
-
- /************************************************************************/
- /* This checks for the G8BPQ Node signiature of X'AA55' in BOTH AX and*/
- /* BX. COMBIOS and related programs only return it in AX. The version*/
- /* number is also retrieved, this could be checked if using a newly*/
- /* implemented feature of the code.*/
- /************************************************************************/
-
- int Check_BPQ(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 4;
-
- int86(0x14, ®s, ®s);
-
- if (regs.x.ax != 0xAA55 || regs.x.bx != 0xAA55)
- {
- fprintf(stderr, "example: G8BPQ node support not loaded\n");
- return(FALSE);
- }
-
- regs.x.dx = port;
- regs.h.ah = 0x1F;
- regs.h.al = 0;
-
- int86(0x14, ®s, ®s);
-
- printf("Running G8BPQ node support version %d.%d\n",
- regs.h.dh, regs.h.dl);
-
- return(TRUE);
- }
-
- void Raise_RTS(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 6;
-
- int86(0x14, ®s, ®s);
- }
-
- void Lower_RTS(int port)
- {
- union REGS regs;
- regs.x.dx = port;
- regs.h.ah = 5;
-
- int86(0x14, ®s, ®s);
- }
-
- /************************************************************************/
- /* Sending a break to the node software is the sure-fire way of getting*/
- /* back to command mode from converse and transparant mode.*/
- /************************************************************************/
-
- void Send_Break(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 7;
-
- int86(0x14, ®s, ®s);
- }
-
- /************************************************************************/
- /* This function takes the same sort of arguments as the C library*/
- /* function write(). It is a non blocking function that returns when*/
- /* either all of the data has been sent to the node, or when the node*/
- /* cannot accept any more data.*/
- /************************************************************************/
-
- int Write_TNC(int port, char *buffer, unsigned int count)
- {
- union REGS regs;
- int attempts = 0;
- int i;
-
- for (i = 0; i < count; i++)
- {
- regs.x.dx = port;
- regs.h.ah = 3;
-
- do
- {
- attempts++;
-
- int86(0x14, ®s, ®s);
- }
- while (!(regs.h.ah & 0x20) && (attempts < 6));
-
- if (attempts == 6)
- return(i);
-
- attempts = 0;
-
- regs.x.dx = port;
- regs.h.ah = 1;
- regs.h.al = buffer[i];
-
- int86(0x14, ®s, ®s);
- }
-
- return(i);
- }
-
- /************************************************************************/
- /* This is the gracefull way of getting rid of users, until recently the*/
- /* only available option was to disconnect them from the node, this puts*/
- /* them back to the node software.*/
- /************************************************************************/
-
- void Return_To_Node(int port)
- {
- union REGS regs;
-
- regs.x.dx = port;
- regs.h.ah = 0x1F;
- regs.h.al = 0x10;
-
- int86(0x14, ®s, ®s);
- }
-
- /************************************************************************/
- /* This function serves two purposes, it indicates whether the*/
- /* application is connected to a user, and if so, what their callsign*/
- /* is. At present it does not return the users ssid, but it is available*/
- /* if needed. The code gets the users callsign from the INT 14H and not*/
- /* from parsing the "*** CONNECTED to ..." line. This piece of the code*/
- /* makes use of a far pointer to the callsign within the Node software.*/
- /* It then has to be converted to ASCII from AX25 format, which is*/
- /* essentially shifting the characters right by one bit.*/
- /************************************************************************/
-
- int Connected(char *buffer, int port)
- {
- union REGS regs;
- struct SREGS segregs;
- unsigned char far *callsign;
- int ssid;
- int i;
-
- regs.x.dx = port;
- regs.h.ah = 0x1F;
- regs.h.al = 1;
-
- int86x(0x14, ®s, ®s, &segregs);
-
- if (regs.x.si == 0)
- return(FALSE);
-
- FP_SEG(callsign) = segregs.es;
- FP_OFF(callsign) = regs.x.si;
-
- for (i = 0; (callsign[i] >> 1) != ' ' && i < 6; i++)
- buffer[i] = callsign[i] >> 1;
-
- buffer[i] = '\0';
-
- ssid = (callsign[6] >> 1) & 0x0F;
-
- return(TRUE);
- }
-
- /************************************************************************/
- /* This routine is a non-blocking read of the port input stream.*/
- /************************************************************************/
-
- int Read_TNC(int port, char *buffer, unsigned int count)
- {
- union REGS regs;
- int i = 0;
-
- regs.x.dx = port;
- regs.h.ah = 3;
-
- int86(0x14, ®s, ®s);
-
- while ((regs.h.ah & 0x01) && (i < count))
- {
- regs.x.dx = port;
- regs.h.ah = 2;
-
- int86(0x14, ®s, ®s);
-
- buffer[i++] = regs.h.al;
-
- regs.x.dx = port;
- regs.h.ah = 3;
-
- int86(0x14, ®s, ®s);
- }
-
- buffer[i] = '\0';
-
- return(i);
- }
-
- void Set_TNC(int appl_number, int port)
- {
- char *command;
- char buffer[15];
-
- Raise_RTS(port);
-
- Send_Break(port);
-
- command = "ECHO ON\r";
- Write_TNC(port, command, strlen(command));
- Print_TNC(port);
-
- sprintf(buffer, "APPL $%02X\r", appl_number);
- Write_TNC(port, buffer, strlen(buffer));
- Print_TNC(port);
-
- command = "MONITOR OFF\r";
- Write_TNC(port, command, strlen(command));
- Print_TNC(port);
-
- command = "CONOK ON\r";
- Write_TNC(port, command, strlen(command));
- Print_TNC(port);
- }
-
- void Reset_TNC(int port)
- {
- char *command;
-
- Send_Break(port);
-
- command = "APPL $00\r";
- Write_TNC(port, command, strlen(command));
- Print_TNC(port);
-
- command = "CONOK OFF\r";
- Write_TNC(port, command, strlen(command));
- Print_TNC(port);
-
- command = "ECHO OFF\r";
- Write_TNC(port, command, strlen(command));
- Print_TNC(port);
-
- Lower_RTS(port);
- }
-
- /************************************************************************/
- /* This function takes its name from a UNIX utility at Nottingham Uni*/
- /* called Carriage Return Utility. It converts between the carriage*/
- /* returns standards found on packet radio to the standards used in DOS*/
- /************************************************************************/
-
- void cru(char *string)
- {
- int i;
-
- for (i = 0; string[i] != '\0'; i++)
- {
- switch (string[i])
- {
- case '\n':
- string[i] = '\r';
- break;
- case '\r':
- string[i] = '\n';
- break;
- }
- }
- }
-
- void Print_TNC(int port)
- {
- char buffer[100];
-
- Read_TNC(port, buffer, 99);
- cru(buffer);
- printf("%s", buffer);
- }
-
- /************************************************************************/
- /* Delay for n seconds. In a "real" piece of software, it would be wise*/
- /* to give time slices to DESQview at the point. The same can also be*/
- /* said of the loop in main() where it is waiting for a user.*/
- /************************************************************************/
-
- void Delay(int delay)
- {
- time_t start_time;
- time_t current_time;
-
- time(&start_time);
-
- do
- {
- time(¤t_time);
- }
- while ((current_time - start_time) < delay);
- }