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.


Mach10 Serial API

The mach10_serial_api module implements a line protocol. When this protocol is chosen by a line, it interprets data received on the line in terms of Mach10 Serial API command names and parameters. When a full Mach10 Serial API command name (with parameter(s)) is recognized, the command is serviced by the Mach10 module. The response is then written back to the line.

Build it from project Mach10SerialAPIDemo.

Function Details

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

mach10_serial_api_strerror(int rc) {...}

Return either success message or error info.

static void mach10_serial_api_message_write(
    const char *message, size_t length,
    void *pOpaque
) {...}

Use ltrx_output_stream_write_binary() to write binary data to the buffer.

static void mach10_serial_api_message_end(
    enum ltrx_user_message_severity severity,
    void *pOpaque
)  {...}

Use ltrx_output_stream_write_without_ending_line() to write data without a new line, or alternately write data with a new line.

static void mach10_serial_api_message_begin(
    enum ltrx_user_message_severity severity,
    void *pOpaque
)  {...}

Use ltrx_output_stream_write_without_ending_line() to write data without a new line when prefix is present.

static void m10ci_initialize_message(
    struct message_to_output_stream *mtos,
    struct output_stream *os
)  {...}

Set mtos properties.

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

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. Initialize a message.

Use ltrx_line_get_registered_name() to get the registered name of the line and then print a <Protocol> started on Line: <line> message to the trouble log. If not successful, get error message from mach10_serial_api_strerror().

Then use ltrx_thread_yield() to yield control to other threads, allowing other threads to run if they are ready, and then print a <Protocol> stopped on Line: <line> message to the trouble log.

Use ltrx_input_stream_close() to close the input stream and ltrx_output_stream_close() to close the output stream.

static 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.

static void StopLineProtocol(uint16_t zeroBasedIndex) {...}

Use ltrx_preemption_block() to prevent other threads from preempting this one, assign the thread to a serial line, and then use ltrx_preemption_unblock() to allow preemption.


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().