LinPac - Packet Radio Terminal for Linux


Version 0.28

(c) Martin Cooper KD6YAM 2020
(c) David Ranch KI6ZHD (linpac@trinnet.net) 2002 - 2020
(c) 1998 - 2001 by Radek Burget OK2JBG

External Application Programming Guide

Contents

1 Introduction

2 What is an external program?

3 Basic concepts of the API

4 How applications communicate with LinPac

5 Using the application library
5.1 The simplest application

6 Application programming
6.1 Events
6.2 Sending and receiving events
6.3 Synchronization
6.4 Shared variables and configuration
6.5 Connection status
6.6 Event usage examples
6.6.1 Connecting to a remote station
6.6.2 Using LinPac commands in programs

7 The application library interface
7.1 Constants
7.2 Data structures
7.3 Functions
7.3.1 Uninterruptable versions of some system calls
7.3.2 Basic communication functions
7.3.3 Automatic event handling functions
7.3.4 Environment functions
7.3.5 User functions
7.3.6 Tool functions
7.3.7 Application information functions

8 The shell interface
8.1 Writing the script
8.1.1 Ensuring that LinPac is running
8.1.2 Accessing configuration and state
8.1.3 Executing commands
8.1.4 Simple shell example
8.2 Creating the command

1 Introduction

This guide is written for programmers who want to add some new functions to LinPac. In the following text, basic knowledge of Linux programming is assumed. Reading the LinPac User Manual before proceeding is also recommended.

2 What is an external program?

An external program is a standard Linux application which uses LinPac to communicate with remote stations. There are basically two types of LinPac external programs: No special knowledge of LinPac is needed for creating the first type of programs, because no LinPac functions are used. The remainder of this guide is dedicated to the second type of applications.

3 Basic concepts of the API

The LinPac application interface is based on events. Every action in LinPac, such as pressing a key, receiving data, executing a command, etc., is represented by a data structure called an event, which describes exactly what happened. LinPac's internal structure consists of separate objects which communicate with each other using these events. Each object provides its own functionality, and often generates events. For example, the object Keyscan produces an event each time any key is pressed.

All the events generated by any object are put into the common event queue. The LinPac kernel simply takes the events from the queue one by one and sends them to all the objects (including the one that generated the event). Thus each event generated by any part of LinPac is forwarded to all of the objects. The reaction of each object fully depends on its functionality, but of course it can include generation of other events.

The list of LinPac internal objects and their names can be found in the file objects.txt.

An additional feature of the API is a shared variable environment. This is a set of variables that is shared with LinPac; the values are automatically synchronized with all the external programs. These variables are accessed using special functions of the API as described below.

4 How applications communicate with LinPac

LinPac uses TCP/IP sockets for communication with external programs (applications). The connection is always initiated by the application after it starts. There are basically two ways that an application may be started: In both cases, the start of an application causes the creation of a new object in LinPac called an event gate. This object represents the application within LinPac. Bearing in mind the previous chapter, this means that the application is forwarded all of the events generated by any LinPac object, and all of the events generated by the application are forwarded to all LinPac objects.

NOTE: All of the communication via TCP/IP sockets is provided by the LinPac application library. The user application should not attempt to access the sockets directly.

5 Using the application library

During LinPac installation, the application library liblinpac is created and installed by default to /usr/local/lib. The interface to this library is contained in the file lpapp.h, which is installed by default to /usr/local/include/linpac. The next chapter illustrates how to use the library within a user application.

5.1 The simplest application

The following application example just tries to contact LinPac, and prints the result.

#include <stdio.h> #include <unistd.h> #include <linpac/lpapp.h> int main() { if (lp_start_appl()) { printf("Application started\n"); sleep(10); printf("Application finished\n"); lp_end_appl(); } else { printf("LinPac is not running\n"); return 1; } return 0; }

The function lp_start_appl() tries to contact LinPac and returns 1 in case of success or 0 when a connection to LinPac cannot be made (probably because it's not running). This function should precede the usage of any other application library functions.

The function lp_end_appl() closes the connection to LinPac.

To compile this example, use:

$ gcc -o test1 test1.c -llinpac

This example just detects if LinPac is running, and it can be executed directly from the shell. When running from the shell, no streams are redirected to LinPac, and the application appears to run on channel 0 of LinPac. This is useful for some applications that are used to control LinPac from outside. However this is not a typical use case.

For most applications, it is better to copy the executable to the $LINPACDIR/bin directory and then add it to the file $LINPACDIR/bin/commands as described in the User Manual. After this, the application can be executed as a LinPac command. In this scenario, the streams are properly redirected and the application output is visible in the LinPac QSO window. It is also possible to select the channel on which to run the application.

NOTE: The LinPac application library (liblinpac) can be linked without problems with both C and C++ code.

6 Application programming

6.1 Events

LinPac is completely driven by events. Each part of LinPac, including applications, can generate events to inform other parts (internal modules or applications) that something has happened. Each event is sent to all LinPac components and applications. For example when some station connects to some LinPac channel, the internal AX.25 interface generates an event reporting that the station has connected and includes its callsign. All components and applications now know who has connected, and they can take some actions. For example, the output window prints information about the connection, the macro processor executes the cinit.mac macro, and so on. Each application can handle all of the events too, and can generate events which are handled by other components.

An event is represented by the following structure:


struct Event
{
    int type;
    int chn;
    int x,y;
    char ch;
    void *data;
};

The meaning of each field is as follows: