Sample Applications

These sample applications are included with the SDK. Modules are in custom/module and projects are in custom/project. Once you have built a project, find the ROM and other project files in xPortEdge/work.


Custom Data

The custom_data module demonstrates how to define and access custom configurables, how to embed files in a module, and how to overlay files using embedded files.

Build it from project customDataDemo.

When this project is loaded onto the XPort EDGE device, a new Custom Data tab appears in Web Manager. Click the tab to go to the Custom Device Configuration page. Bring up the trouble log on a line to watch what is happening. Change Name, Rank, and Serial Number, click Submit, and observe the changes on the trouble Log.

Function Details

The following is an overview of the functions used in the custom_data module.

static bool getXmlValue(
    const struct xml_emit_value_specification *xevs,
    char *buffer,
    size_t size
) {...}

Use ltrx_output_stream_init_to_buffer() to set up an output stream and write the data to the buffer and ltrx_xml_emit_value() to emit the XML value onto the buffer.

static bool getItem(
    const char *desiredItemName,
    char *buffer,
    size_t size
) {...}

Find the desired custom item and write it to the buffer. Use snprintf() to write up to size bytes to str under the control of a format string.

static void customConfigMonitorThread(void *opaque) {...}

Find any new config values and print them out to the trouble log.


XML Access

The xml_access module demonstrates how to read device status and configuration values via XML.

Build it from project xmlAccessDemo.

Function Details

The following is an overview of the functions used in the xml_access module.

static bool getXmlValue(
    const struct xml_emit_value_specification *xevs,
    char *buffer,
    size_t size
) {...}

Use ltrx_output_stream_init_to_buffer() to set up an output stream to buffer and ltrx_xml_emit_value() to emit an XML value onto the buffer.

static void xmlAccessThread(void *opaque) {...}

Use ltrx_ip_address_state() to check if the IP interfaces are up, and while there is no connection, use ltrx_thread_sleep() to pause the thread. While there is a connection, get firmware version, MAC address, current WLAN0 IP address, and configured dynamic power mode and print related information to the trouble log, and then pause the thread.


Secure Tunnel

The secure_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via TLS out on the line. It sends data received on the line out via TLS when it receives Enter or fills its 80 character buffer.

The module listens for a TLS connection on the eth0 interface addressed to LOCAL_PORT 10001. When the connection is established, it sends Connected to the line. Subsequently, it listens to the line for data to send out via TLS. #define REMOTE_ADDRESS must be commented out to operate in this listening mode.

Note

You must add TLS Credential called secure_tunnel. Log in to Web Manager and click TLS Credentials. For more information, see "Creating a TLS Credential" in the XPort EDGE User Guide.

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set the #define REMOTE_PORT. When the connection is established, it sends Connected to the line.

Build it from project secureTunnelDemo.

Function Details

The following is an overview of the functions used in the secure_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

If there is data, use ltrx_output_stream_write_binary() to write binary data to the buffer. If there is not, use ltrx_tcp_socket_is_eof() to check if all receive data has been read and a FIN has been received. If so, use ltrx_output_stream_write_line() to write "Disconnected" ending with a new line. Then use ltrx_tcp_socket_close() to close the socket.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, send the data and then use ltrx_tcp_socket_close() to close the socket and then close the connection.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

Use ltrx_network_lookup_network_protocol() to get the protocol structure for "TLS".

If REMOTE_ADDRESS is defined and there is no socket open for the thread, use ltrx_tcp_listener_begin() to initialize the listener and start listening.

If REMOTE_ADDRESS is defined and there is a socket open for the thread, use ltrx_output_stream_write_line() to print "Connected" with a new line.

If REMOTE_ADDRESS is not defined and there is no socket open and no listener in use, use ltrx_tcp_listener_begin() to initialize listener and begin listening.

If REMOTE_ADDRESS is not defined and there is no socket open but a listener is in use, use ltrx_tcp_accept() to accept a connection request and then ltrx_ip_socket_get_peer_information() to get peer information (IP address and port of the remote device). Then use ltrx_ip_and_port_display() to print the IP address and port. Use ltrx_output_stream_write_without_ending_line() to writes "Accepted from" (no new line) followed by ltrx_output_stream_write_line() to the remote address and port, with a new line. Finally, use ltrx_tcp_listener_end() to stop listening.

If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

If REMOTE_ADDRESS is not defined and there is a listener in use, use ltrx_tcp_listener_end() to stop listening.

Close the socket with ltrx_tcp_socket_close().

static void lineThread(void *opaque) {...}

Attempt to create trigger using ltrx_trigger_create(). If it returns false (failed), return. Otherwise keep going. While the thread is running, use ltrx_line_open() to open a line. If it returns false (failed), wait 1000 ms and try again.

If the line is running, print to trouble log and then use ltrx_line_set_dtr() to set the DTR value.

Use ltrx_line_close() tp relinquish the line and then ltrx_trigger_destroy() to destroy the trigger.

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

If a thread is already running, print message to the trouble log. Otherwise, use ltrx_thread_create() to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Pause the thread with ltrx_thread_sleep().


Configurable Pins

The config_pin module implements an output role, which can be assigned to any configurable pin (CP).

Build it from project configurablePinDemo.

Use either Web Manager or Command Line Interface to set up configuration in group configurable pin manager (CPM). Under Roles, find your role of Blinker. Assign it a CP of your choice and set State to Enabled.

Tip

If using the evaluation board, you must jumper your selected configurable pin to one of the LEDs -- if some other role is enabled using your selected CP, this will fail. Observe the blinking LED.

Function Details

The following is an overview of the functions used in the config_pin module.

static void blinkerThread(void *opaque) {...}

Look up role index using ltrx_cp_role_index_get() and print the role name and roll index to trouble log. While there is a thread, use ltrx_cp_write() to write to a configurable pin and then pause the thread with ltrx_thread_sleep().

void config_pin_module_startup(void) {...}

Notice use of the macro STACK_SIZE_GREEN_FROM_MAX_OBSERVED_STACK_USED when calling ltrx_thread_create() in the startup function. It was originally built with 2000 bytes of stack. Then the module was built and run. The actual stack was observed either via the Web Manager or the Command Line Interface under Diagnostics Threads. Find the Blinker thread, and the Stack used is shown. That value was plugged into the macro in the sample code.


UDP Tunnel

The udp_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via UDP out on the line. It sends data received on the line out via UDP when it receives Enter or fills its 80 character buffer.

The module listens for UDP packets on the eth0 interface addressed to the LOCAL_PORT 10001. When the first packet is received, it sends Connected to the line. Subsequently, it listens to the line for data to send out via UDP. #define REMOTE_ADDRESS may be eth0.

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set the #define REMOTE_PORT. When the interface is established and resolves the name or address, it sends Connected to the line.

Build it from project udpTunnelDemo.

Function Details

The following is an overview of the functions used in the udp_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

Receive data from the socket using ltrx_ip_socket_receive(). If the length of the received data is greater than zero, use ltrx_output_stream_write_binary() to write the binary data to the buffer.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, use ltrx_ip_socket_send() to send the data and then ltrx_tcp_socket_close() to close the socket.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

While the thread is running, there is no socket open, and ltrx_udp_socket_open_with_options() to open a socket returns false (failed), wait and try again. Otherwise, call networkReadAndSerialWrite() and then, if ltrx_udp_socket_is_active() returns true, and the thread is not connected, use ltrx_output_stream_write_line() to write "" and a new line, follwed by "Connected" and a new line. If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

static void lineThread(void *opaque) {...}

Attempt to create trigger using ltrx_trigger_create(). If it returns false (failed), return. Otherwise keep going. While the thread is running, use ltrx_line_open() to open a line. If it returns false (failed), wait 1000 ms and try again.

If the line is running, print to trouble log and then use ltrx_line_set_dtr() to set the DTR value.

Use ltrx_line_close() tp relinquish the line and then ltrx_trigger_destroy() to destroy the trigger.

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

Check to see if a thread is already running on the line and print the message to trouble log if so.

Use ltrx_thread_create() to to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Pause the thread with ltrx_thread_sleep().


TCP Tunnel

The tcp_tunnel module implements a line protocol. When this protocol is chosen by a line, it sends data received via TCP out on the line. It sends data received on the line out via TCP when it receives Enter or fills its 80 character buffer.

The module listens for a TCP connection on the eth0 interface addressed to LOCAL_PORT 10001. When the connection is established, it sends Connected to the line. Subsequently, it listens to the line for data to send out via TCP. #define REMOTE_ADDRESS must be commented out to operate in this listening mode.

Alternately, you can change #define REMOTE_ADDRESS to either an IP address or a host name to operate in a connect mode. In this case you must also set #define REMOTE_PORT. When the connection is established, it sends Connected to the line.

Build it from project tcpTunnelDemo.

For connecting out, fill in REMOTE_ADDRESS with either an IP address or a host name. For listening, comment out the definition of REMOTE_ADDRESS. The REMOTE_PORT is only used if "connecting out" according to REMOTE_ADDRESS.

#define REMOTE_ADDRESS "remote_host_goes_here"

Function Details

The following is an overview of the functions used in the tcp_tunnel module.

static void networkReadAndSerialWrite(struct thread_info *ti) {...}

Receive data from the socket using ltrx_ip_socket_receive(). If there is data, use ltrx_output_stream_write_binary() to write binary data to the buffer. If there is not, use ltrx_tcp_socket_is_eof() to check if all receive data has been read and a FIN has been received. If so, use ltrx_output_stream_write_line() to write "" ending with a new line and then "Disconnected" ending with a new line. Then use ltrx_tcp_socket_close() to close the socket.

static void serialReadEchoAndNetworkWrite(struct thread_info *ti) {...}

Use ltrx_input_stream_peek() to perform non-blocking peek. When there are characters in the stream, use ltrx_input_stream_read() to read the next character in the stream. If the next character is carriage return (\r), use ltrx_output_stream_write_line() to write "", ending with a new line. Otherwise, use ltrx_output_stream_write_binary() to write the next character.

If SendNow is true, use ltrx_ip_socket_send() to send the data and then ltrx_tcp_socket_close() to close the socket.

static void lineLoop(struct thread_info *ti) {...}

Use ltrx_input_stream_init_from_uart() to set up an input stream from a serial line and ltrx_output_stream_init_to_uart() to set up an output stream to a serial line. Then use ltrx_output_stream_write_line() to write "" ending with a new line and then the protocol name and end with a new line.

While the thread is running, REMOTE_ADDRESS is defined, and there is no socket, use ltrx_tcp_connect() to connect. If there is a socket, print "Connected".

While the thread is running, REMOTE_ADDRESS is not defined, and there is no socket and no listener, use ltrx_tcp_listener_begin() to initialize a listener and start listening.

If REMOTE_ADDRESS is not defined and there is no socket open but a listener is in use, use ltrx_tcp_accept() to accept a connection request and then ltrx_ip_socket_get_peer_information() to get peer information (IP address and port of the remote device). Then use ltrx_ip_and_port_display() to print the IP address and port. Use ltrx_output_stream_write_without_ending_line() to writes "Accepted from" (no new line) followed by ltrx_output_stream_write_line() to the remote address and port, with a new line. Finally, use ltrx_tcp_listener_end() to stop listening.

If there is a socket open for the thread, use ltrx_line_read_bytes_available() to find out how many bytes are available and signal the trigger when data is available.

Wait for a trigger with LTRX_TRIGGER_WAIT() and clear the trigger with ltrx_trigger_clear().

bool StartLineProtocol(uint16_t zeroBasedIndex) {...}

Check to see if a thread is already running on the line and print the message to trouble log if so.

Use ltrx_thread_create() to to create a thread and start it.

void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to block other threads from preempting this one. If the thread is running, then signal a trigger with ltrx_trigger_signal(). Then use ltrx_preemption_unblock() to allow other threads to preempt this one.

If wasRunning is true, use ltrx_timemark() to get time mark. While the thread exists and is not the current thread returned by ltrx_thread_id(), and the time since time mark, returned by ltrx_elapsed_time_current_ms() is less that 2000 ms, but greater or equal to 500 ms, then purge the data from the serial line with ltrx_line_purge(). Otherwise, pause the thread for 100ms with ltrx_thread_sleep().