Chapter 154. Using PPP

Before going into detail, let's look at a simple example of how the eCos PPP package is used. Consider the following example:

static void ppp_up(void)
{
    cyg_ppp_options_t options;
    cyg_ppp_handle_t ppp_handle;

    // Bring up the TCP/IP network
    init_all_network_interfaces();

    // Initialize the options
    cyg_ppp_options_init( &options );

    // Start up PPP
    ppp_handle = cyg_ppp_up( "/dev/ser0", &options );

    // Wait for it to get running
    if( cyg_ppp_wait_up( ppp_handle ) == 0 )
    {
        // Make use of PPP
        use_ppp();

        // Bring PPP link down
        cyg_ppp_down( ppp_handle );

        // Wait for connection to go down.
        cyg_ppp_wait_down( ppp_handle );
    }
}

This is a simple example of how to bring up a simple PPP connection to another computer over a directly connected serial line. The other end is assumed to already be running PPP on the line and waiting for a connection.

The first thing this code does is to call init_all_network_interfaces() to bring up the TCP/IP stack and initialize any other network interfaces. It then calls cyg_ppp_options_init() to initialize the PPP options structure to the defaults. As it happens, the default options are exactly what we want for this example, so we don't need to make any further changes. We go straight on to bring the PPP interface up by calling cyg_ppp_up(). The arguments to this function give the name of the serial device to use, in this case "/dev/ser0", and a pointer to the options.

When cyg_ppp_up() returns, it passes back a handle to the PPP connection which is to be used in other calls. The PPP link will not necessarily have been fully initialized at this time. There is a certain amount of negotiation that goes on between the ends of a PPP link before it is ready to pass packets. An application can wait until the link is ready by calling cyg_ppp_wait_up(), which returns zero if the link is up and running, or -1 if it has gone down or failed to come up.

After a successful return from cyg_ppp_wait_up(), the application may make use of the PPP connection. This is represented here by the call to use_ppp() but it may, of course, be accessed by any thread. While the connection is up the application may use the standard socket calls to make or accept network connections and transfer data in the normal way.

Once the application has finished with the PPP link, it can bring it down by calling cyg_ppp_down(). As with bringing the connection up, this call is asynchronous, it simply informs the PPP subsystem to start bringing the link down. The application can wait for the link to go down fully by calling cyg_ppp_wait_down().

That example showed how to use PPP to connect to a local peer. PPP is more often used to connect via a modem to a remote server, such as an ISP. The following example shows how this works:

static char *isp_script[] =
{
    "ABORT"             ,       "BUSY"                                  ,
    "ABORT"             ,       "NO CARRIER"                            ,
    "ABORT"             ,       "ERROR"                                 ,
    ""                  ,       "ATZ"                                   ,
    "OK"                ,       "AT S7=45 S0=0 L1 V1 X4 &C1 E1 Q0"      ,
    "OK"                ,       "ATD" CYGPKG_PPP_DEFAULT_DIALUP_NUMBER  ,
    "ogin:--ogin:"      ,       CYGPKG_PPP_AUTH_DEFAULT_USER            ,
    "assword:"          ,       CYGPKG_PPP_AUTH_DEFAULT_PASSWD          ,
    "otocol:"           ,       "ppp"                                   ,
    "HELLO"             ,       "\\c"                                   ,
    0
};

static void ppp_up(void)
{
    cyg_ppp_options_t options;
    cyg_ppp_handle_t ppp_handle;

    // Bring up the TCP/IP network
    init_all_network_interfaces();

    // Initialize the options
    cyg_ppp_options_init( &options );

    options.script = isp_script;
    options.modem  = 1;

    // Start up PPP
    ppp_handle = cyg_ppp_up( "/dev/ser0", &options );

    // Wait for it to get running
    if( cyg_ppp_wait_up( ppp_handle ) == 0 )
    {
        // Make use of PPP
        use_ppp();

        // Bring PPP link down
        cyg_ppp_down( ppp_handle );

        // Wait for connection to go down.
        cyg_ppp_wait_down( ppp_handle );
    }
}

The majority of this code is exactly the same as the previous example. The main difference is in the setting of a couple of options before calling cyg_ppp_up(). The script option is set to point to a CHAT script to manage the setup of the connection. The modem option is set to cause the PPP system to make use of the modem control lines.

During the PPP bring-up a call will be made to cyg_ppp_chat() to run the CHAT script (see Chapter 157, CHAT Scripts). In the example this script sets up various modem options and then dials a number supplied as part of the PPP package configuration (see Chapter 156, Installing and Configuring PPP). When the connection has been established, the script log on to the server, using a name and password also supplied by the configuration, and then starts PPP on the remote end. If this script succeeds the PPP connection will be brought up and will then function as expected.

The modem option causes the PPP system to make use of the modem control lines. In particular it waits for Carrier Detect to be asserted, and will bring the link down if it is lost. See cyg_ppp_options_init() for more details.