blob: 037fbd81607efed127d5185c08a0de5215737df4 [file] [log] [blame]
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<!-- This is broken by doc revisioning.
-->
<link rel="shortcut icon" href="../../../../img/favicon.ico">
<title>toc - Apache Mynewt</title>
<link href="../../../../css/bootstrap-3.0.3.min.css" rel="stylesheet">
<link rel="stylesheet" href="../../../../css/highlight.css">
<link href="../../../../css/base.css" rel="stylesheet">
<link href="../../../../css/custom.css" rel="stylesheet">
<link href="../../../../css/v2.css" rel="stylesheet">
<link href="https://fonts.googleapis.com/css?family=Lato" rel="stylesheet">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.5.0/css/font-awesome.min.css">
<!-- HTML5 shim and Respond.js IE8 support of HTML5 elements and media queries -->
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script>
(function(i, s, o, g, r, a, m) {
i["GoogleAnalyticsObject"] = r;
(i[r] =
i[r] ||
function() {
(i[r].q = i[r].q || []).push(arguments);
}),
(i[r].l = 1 * new Date());
(a = s.createElement(o)), (m = s.getElementsByTagName(o)[0]);
a.async = 1;
a.src = g;
m.parentNode.insertBefore(a, m);
})(window, document, "script", "//www.google-analytics.com/analytics.js", "ga");
ga("create", "UA-72162311-1", "auto");
ga("send", "pageview");
</script>
</head>
<body class="toc">
<div class="container">
<div class="row v2-main-banner">
<a class="logo-cell" href="/">
<img class="logo" src="/img/logo.png">
</a>
<div class="tagline-cell">
<h4 class="tagline">An OS to build, deploy and securely manage billions of devices</h4>
</div>
<div class="news-cell">
<div class="well">
<h4>Latest News:</h4> <a href="/download">Apache Mynewt 1.12.0, Apache NimBLE 1.7.0 </a> released (April 4, 2024)
</div>
</div>
</div>
</div>
<nav id="navbar" class="navbar navbar-inverse affix-top" data-spy="affix" data-offset-top="150" role="navigation">
<div class="container">
<!-- Collapsed navigation -->
<div class="navbar-header">
<!-- Expander button -->
<button type="button" class="navbar-toggle" data-toggle="collapse" data-target=".navbar-collapse">
<span class="sr-only">Toggle navigation</span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
<span class="icon-bar"></span>
</button>
</div>
<!-- Expanded navigation -->
<div class="navbar-collapse collapse">
<!-- Main navigation -->
<ul class="nav navbar-nav navbar-right">
<li
class=""
>
<a href="/"><i class="fa fa-home" style="font-size: larger;"></i></a>
</li>
<li
class="important"
>
<a href="/quick-start/">Quick Start</a>
</li>
<li
class=""
>
<a href="/about/">About</a>
</li>
<li
class=""
>
<a href="/talks/">Talks</a>
</li>
<li
class="active"
>
<a href="/documentation/">Documentation</a>
</li>
<li
class=""
>
<a href="/download/">Download</a>
</li>
<li
class=""
>
<a href="/community/">Community</a>
</li>
<li
class=""
>
<a href="/events/">Events</a>
</li>
</ul>
</div>
</div>
</nav>
<div class="container">
<div class="row">
<div class="col-md-3 v2-sidebar sidebar-container"><div id="docSidebar" class="hidden-print" role="complementary">
<div class="top">
<div role="search">
<form id="rtd-search-form" class="wy-form" action="../../../../search.html" method="get">
<div class="form-group">
<input type="text" name="q" class="form-control" placeholder="Search documentation" />
</div>
</form>
</div>
</div>
<ul class="toc-nav">
<li class="doc-version"><select class="form-control" onchange="if (this.value) window.location.href=this.value">
<option value="/latest">
Version: master
</option>
<option value="/v1_12_0/" >
Version: 1.12.0
</option>
<option value="/v1_11_0/" >
Version: 1.11.0
</option>
<option value="/v1_10_0/" >
Version: 1.10.0
</option>
<option value="/v1_9_0/" >
Version: 1.9.0
</option>
<option value="/v1_8_0/" >
Version: 1.8.0
</option>
<option value="/v1_7_0/" >
Version: 1.7.0
</option>
<option value="/v1_6_0/" >
Version: 1.6.0
</option>
<option value="/v1_5_0/" >
Version: 1.5.0
</option>
<option value="/v1_4_0/" >
Version: 1.4.0
</option>
<option value="/v1_3_0/os/introduction" selected="selected" >
Version: 1.3.0
</option>
<option value="/v1_2_0/os/introduction" >
Version: 1.2.0
</option>
<option value="/v1_1_0/os/introduction" >
Version: 1.1.0
</option>
<option value="/v1_0_0/os/introduction" >
Version: 1.0.0
</option>
<option value="/v0_9_0/os/introduction" >
Version: 0.9.0
</option>
</select></li>
<li ><a href="../../../introduction/">Mynewt Documentation</a>
<ul>
<li ><a href="../../../get_started/get_started/">Basic Setup</a>
</li>
<li >
<a href="../../../get_started/vocabulary/">Concepts</a>
</li>
<li ><a href="../../../tutorials/tutorials/">Tutorials</a>
</li>
<li ><a href="../../../os_user_guide/">OS User Guide</a>
<ul>
<li ><a href="../../../core_os/mynewt_os/">OS Core</a>
</li>
<li ><a href="../../../core_os/porting/port_os/">Porting to your Platform</a>
</li>
<li class="active"><a href="./">Console</a>
<ul>
<li><a href="
../console_echo/
">Functions</a>
</li>
</ul>
</li>
<li ><a href="../../shell/shell/">Shell</a>
</li>
<li ><a href="../../split/split/">Split Images</a>
</li>
<li ><a href="../../bootloader/bootloader/">Bootloader</a>
</li>
<li><a href="
../../fs/fs/fs/
">File System</a>
</li>
<li ><a href="../../hal/hal/">Hardware Abstraction Layer</a>
</li>
<li ><a href="../../sensor_framework/sensor_framework_overview/">Sensor Framework</a>
</li>
<li ><a href="../../drivers/driver/">Drivers</a>
</li>
<li ><a href="../../testutil/testutil/">Test Utilities</a>
</li>
<li ><a href="../../devmgmt/newtmgr/">Device Management with Newt Manager</a>
</li>
<li ><a href="../../imgmgr/imgmgr/">Image Manager</a>
</li>
<li >
<a href="../../baselibc/">Baselibc library</a>
</li>
<li ><a href="../../json/json/">JSON</a>
</li>
<li ><a href="../../fcb/fcb/">Flash Circular Buffer</a>
</li>
<li ><a href="../../stats/stats/">Stats</a>
</li>
<li ><a href="../../logs/logs/">Logs</a>
</li>
<li ><a href="../../sysinitconfig/sysinitconfig/">System Configuration And Initialization</a>
</li>
</ul>
</li>
<li><a href="
../../../../network/ble/ble_intro/
">BLE User Guide</a>
</li>
<li ><a href="../../../../newt/newt_intro/">Newt Tool Guide</a>
</li>
<li ><a href="../../../../newtmgr/overview/">Newt Manager Guide</a>
</li>
<li >
<a href="../../../../known_issues/">Known Issues</a>
</li>
</ul>
</li>
<li><a href="
../../../../newt/install/prev_releases/
">Appendix</a>
</li>
</ul>
</div></div>
<div class="col-md-9" role="main">
<div class="doc-header">
<div role="navigation" aria-label="breadcrumbs navigation">
<ul class="wy-breadcrumbs">
<li><a href="/documentation/">Docs</a></li>
<li>&raquo; Console</li>
<li>&raquo; <a href="os/os_user_guide/">OS User Guide</a></li>
<li>&raquo; <a href="os/introduction/">Mynewt Documentation</a></li>
<li class="wy-breadcrumbs-aside">
<a href="https://github.com/apache/mynewt-site/blob/master/docs/os/modules/console/console.md"
class="icon icon-github"> Edit on GitHub</a>
</li>
</ul>
</div>
</div>
<div class="alert alert-warning">
<p>
Version 1.3.0 is not the most recent version of the Apache Mynewt
documentation. Click <a href="/latest">here</a> to read the latest
version.
</p>
</div>
<h2 id="console">Console</h2>
<p>The console is an operating system window where users interact with the OS subsystems or a console application. A user typically inputs text from a keyboard and reads the OS output text on a computer monitor. The text is sent as a sequence of characters between the user and the OS. </p>
<p>You can configure the console to communicate via a UART or the SEGGER Real Time Terminal (RTT) . The <code>CONSOLE_UART</code> syscfg setting enables the communication via a UART and is enabled by default. The <code>CONSOLE_RTT</code> setting enables the communication via the RTT and is disabled by default. When the <code>CONSOLE_UART</code> setting is enabled, the following settings apply:</p>
<ul>
<li><code>CONSOLE_UART_DEV</code>: Specifies the UART device to use. The default is <code>uart0</code>. </li>
<li><code>CONSOLE_UART_BAUD</code>: Specifies the UART baud rate. The default is 115200.</li>
<li><code>CONSOLE_UART_FLOW_CONTROL</code>: Specifies the UART flow control. The default is <code>UART_FLOW_CONTROL_NONE</code>.</li>
<li><code>CONSOLE_UART_TX_BUF_SIZE</code>: Specifies the transmit buffer size and must be a power of 2. The default is 32.
<br></li>
</ul>
<p>The <code>CONSOLE_TICKS</code> setting enables the console to print the current OS ticks in each output line. </p>
<p><strong>Notes:</strong> </p>
<ul>
<li>SEGGER RTT support is not available in the Mynewt 1.0 console package.</li>
<li>The console package is initialized during system initialization (sysinit) so you do not need to initialize the console. However, if you use the Mynewt 1.0 console API to read from the console, you will need to call the <code>console_init()</code> function to enable backward compatibility support.</li>
</ul>
<h3 id="description">Description</h3>
<p>In the Mynewt OS, the console library comes in three versions:</p>
<ul>
<li>The <code>sys/console/full</code> package implements the complete console functionality and API.</li>
<li>The <code>sys/console/stub</code> package implements stubs for the API.</li>
<li>The <code>sys/console/minimal</code> package implements minimal console functionality of reading from and writing to console. It implements the <code>console_read()</code> and <code>console_write()</code> functions and stubs for all the other console functions.</li>
</ul>
<p>All the packages export the <code>console</code> API, and any package that uses the console API must list <code>console</code> as a requirement its <code>pkg.yml</code> file: </p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>pkg.name: sys/shell
pkg.deps:
- kernel/os
- encoding/base64
- time/datetime
- util/crc
pkg.req_apis:
- console
</code></pre></div>
<p><br>
The project <code>pkg.yml</code> file also specifies the version of the console package to use.</p>
<p><br></p>
<h4 id="using-the-full-console-package">Using the Full Console Package</h4>
<p>A project that requires the full console capability must list the <code>sys/console/full</code> package as a dependency in its <code>pkg.yml</code> file.</p>
<p>An example is the <code>slinky</code> application. It requires the full console capability and has the following
<code>pkg.yml</code> file: </p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>pkg.name: apps/slinky
pkg.deps:
- test/flash_test
- mgmt/imgmgr
- mgmt/newtmgr
- mgmt/newtmgr/transport/nmgr_shell
- kernel/os
- boot/bootutil
- sys/shell
- sys/console/full
...
- sys/id
</code></pre></div>
<p><br></p>
<h4 id="using-the-stub-console-package">Using the Stub Console Package</h4>
<p>A project that uses console stub API must list the <code>sys/console/stub</code> package as a dependency in its <code>pkg.yml</code> file.</p>
<p>Examples of when a project would use the console stubs might be:</p>
<ul>
<li>A project may not have a physical console (e.g. a UART port to connect a terminal to)
but may have a dependency on a package that has console capability. </li>
<li>A bootloader project where we want to keep the size of the image small. It includes
the <code>kernel/os</code> package that can print out messages on a console (e.g. if there is a hard fault).
However, we do not want to use any console I/O capability in this particular bootloader project to
keep the size small. </li>
</ul>
<p>The project would use the console stub API and has the following <code>pkg.yml</code> file: </p>
<p>Another example would be the bootloader project where we want to keep the size of the image small. It includes the <code>libs/os</code> pkg that can print out messages on a console (e.g. if there is a hard fault) and the <code>libs/util</code> pkg that uses full console (but only if SHELL is present to provide a CLI). However, we do not want to use any console I/O capability in this particular bootloader project to keep the size small. We simply use the console stub instead, and the pkg.yml file for the project boot pkg looks like the following:</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>pkg.name: apps/boot
pkg.deps:
- boot/bootutil
- kernel/os
- sys/console/stub
</code></pre></div>
<p><br></p>
<h4 id="using-the-minimal-console-package">Using the Minimal Console Package</h4>
<p>There might be projects that need to read and write data on a serial connection but do not need the full console capability. An example might be a project that supports serial image upgrade but does not need full newtmgr capability. The project would use the console minimal API and has the following <code>pkg.yml</code> file: </p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code>pkg.name: apps/boot
pkg.type: app
pkg.description: Boot loader application.
pkg.author: &quot;Apache Mynewt &lt;dev@mynewt.apache.org&gt;&quot;
pkg.homepage: &quot;http://mynewt.apache.org/&quot;
pkg.keywords:
- loader
pkg.deps:
- boot/bootutil
- kernel/os
- sys/console/stub
pkg.deps.BOOT_SERIAL.OVERWRITE:
- sys/console/minimal
- boot/boot_serial
</code></pre></div>
<p><br></p>
<h4 id="output-to-the-console">Output to the Console</h4>
<p>You use the <code>console_write()</code> function to write raw output and the <code>console_printf()</code> function to write a C-style formatted string to the console.</p>
<p><br></p>
<h4 id="input-from-the-console">Input from the Console</h4>
<p>The following syscfg settings control input from the console:</p>
<ul>
<li><code>CONSOLE_INPUT</code>: Enables input from the console. The setting is enabled by default.</li>
<li><code>CONSOLE_ECHO</code>: Enables echoing of the received data back to the console. Echoing is enabled by default. Terminal programs expect this, and is a way for the user to know that the console is connected and responsive. You can also use the <code>console_echo()</code> function to set echo on or off programatically. </li>
<li><code>CONSOLE_MAX_INPUT_LEN</code>: Specifies the maximum input line length.</li>
</ul>
<p><br>
The Mynewt 1.1 console package adds a new API for reading input data from the console. The package supports backward compatibility for the Mynewt 1.0 console API. The steps you use to receive data from the console for each API version are provided below.</p>
<p><br></p>
<h5 id="mynewt-10-console-api">Mynewt 1.0 Console API</h5>
<p>To use the Mynewt 1.0 console API for reading input from the console, you perform the follow steps:</p>
<ol>
<li>
<p>Call the <code>console_init()</code> function and pass either a pointer to a callback function or NULL for the argument. The console calls this callback function, if specified, when it receives a full line of data. </p>
</li>
<li>
<p>Call the <code>console_read()</code> function to read the input data. </p>
</li>
</ol>
<p><strong>Note:</strong> The <code>CONSOLE_COMPAT</code> syscfg setting must be set to 1 to enable backward compatibility support. The setting is enabled by default. </p>
<p><br></p>
<h5 id="mynewt-11-console-api">Mynewt 1.1 Console API</h5>
<p>Mynewt 1.1 console API adds the <code>console_set_queues(struct os_eventq *avail_queue, struct os_eventq *lines_queue)</code> function. An application or the package, such as the shell, calls this function to specify two event queues that the console uses to manage input data buffering and to send notification when a full line of data is received. The two event queues are used as follows:</p>
<ul>
<li>
<p><strong>avail_queue</strong>: Each event in this queue indicates that a buffer is available for the console to use for buffering input data. </p>
<p>The caller must initialize the avail_queue and initialize and add an <a href="/os/core_os/event_queue/event_queue.md">os_event</a> to the avail_queue before calling the <code>console_set_queues()</code> function. The fields for the event should be set as follows: </p>
<ul>
<li><strong><code>ev_cb</code></strong>: Pointer to the callback function to call when a full line of data is received.</li>
<li><strong><code>ev_arg</code></strong>: Pointer to a <code>console_input</code> structure. This structure contains a data buffer to store the current input. </li>
</ul>
<p>The console removes an event from this queue and uses the <code>console_input</code> buffer from this event to buffer the received characters until it receives a new line, '/n', character. When the console receives a full line of data, it adds this event to the <strong>lines_queue</strong>.</p>
</li>
<li>
<p><strong>lines_queue</strong>: Each event in this queue indicates a full line of data is received and ready for processing. The console adds an event to this queue when it receives a full line of data. This event is the same event that the console removes from the avail_queue. </p>
<p>The task that manages the lines_queue removes an event from the queue and calls the event callback function to process the input line. The event callback function must add the event back to the avail_queue when it completes processing the current input data, and allows the console to use the <code>console_input</code> buffer set for this event to buffer input data.</p>
<p>We recommend that you use the OS default queue for the lines_queue so that the callback is processed in the context of the OS main task. If you do not use the OS default event queue, you must initialize an event queue and create a task to process events from the queue.</p>
<p><strong>Note</strong>: If the callback function needs to read another line of input from the console while processing the current line, it may use the <code>console_read()</code> function to read the next line of input from the console. The console will need another <code>console_input</code> buffer to store the next input line, so two events, initialized with the pointers to the callback and the <code>console_input</code> buffer, must be added to the avail_queue. </p>
</li>
</ul>
<p><br>
Here is a code excerpt that shows how to use the <code>console_set_queues()</code> function. The example adds one event to the avail_queue and uses the OS default event queue for the lines_queue.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">static</span> <span style="color: #A90D91">void</span> <span style="color: #000000">myapp_process_input</span>(<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_event</span> <span style="color: #000000">*ev</span>);
<span style="color: #A90D91">static</span> <span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_eventq</span> <span style="color: #000000">avail_queue</span>;
<span style="color: #A90D91">static</span> <span style="color: #A90D91">struct</span> <span style="color: #3F6E75">console_input</span> <span style="color: #000000">myapp_console_buf</span>;
<span style="color: #A90D91">static</span> <span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_event</span> <span style="color: #000000">myapp_console_event</span> <span style="color: #000000">=</span> {
.<span style="color: #000000">ev_cb</span> <span style="color: #000000">=</span> <span style="color: #000000">myapp_process_input</span>,
.<span style="color: #000000">ev_arg</span> <span style="color: #000000">=</span> <span style="color: #000000">&amp;myapp_console_buf</span>
};
<span style="color: #177500">/* Event callback to process a line of input from console. */</span>
<span style="color: #A90D91">static</span> <span style="color: #A90D91">void</span>
<span style="color: #000000">myapp_process_input</span>(<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">os_event</span> <span style="color: #000000">*ev</span>)
{
<span style="color: #A90D91">char</span> <span style="color: #000000">*line</span>;
<span style="color: #A90D91">struct</span> <span style="color: #3F6E75">console_input</span> <span style="color: #000000">*input</span>;
<span style="color: #000000">input</span> <span style="color: #000000">=</span> <span style="color: #000000">ev-&gt;ev_arg</span>;
<span style="color: #000000">assert</span> (<span style="color: #000000">input</span> <span style="color: #000000">!=</span> <span style="color: #A90D91">NULL</span>);
<span style="color: #000000">line</span> <span style="color: #000000">=</span> <span style="color: #000000">input-&gt;line</span>;
<span style="color: #177500">/* Do some work with line */</span>
....
<span style="color: #177500">/* Done processing line. Add the event back to the avail_queue */</span>
<span style="color: #000000">os_eventq_put</span>(<span style="color: #000000">&amp;avail_queue</span>, <span style="color: #000000">ev</span>);
<span style="color: #A90D91">return</span>;
}
<span style="color: #A90D91">static</span> <span style="color: #A90D91">void</span>
<span style="color: #000000">myapp_init</span>(<span style="color: #A90D91">void</span>)
{
<span style="color: #000000">os_eventq_init</span>(<span style="color: #000000">&amp;avail_queue</span>);
<span style="color: #000000">os_eventq_put</span>(<span style="color: #000000">&amp;avail_queue</span>, <span style="color: #000000">&amp;myapp_console_event</span>);
<span style="color: #000000">console_set_queues</span>(<span style="color: #000000">&amp;avail_queue</span>, <span style="color: #000000">os_eventq_dflt_get</span>());
}
</code></pre></div>
<p><br></p>
<h3 id="data-structures">Data structures</h3>
<p>The <code>struct console_input</code> data structure represents a console input buffer. Each event added to the console avail_queue must have the <code>ev_arg</code> field point to a <code>console_input</code> structure.</p>
<div class="codehilite" style="background: #ffffff"><pre style="line-height: 125%;"><span></span><code><span style="color: #A90D91">struct</span> <span style="color: #3F6E75">console_input</span> {
<span style="color: #A90D91">char</span> <span style="color: #000000">line</span>[<span style="color: #000000">MYNEWT_VAL</span>(<span style="color: #000000">CONSOLE_MAX_INPUT_LEN</span>)];
};
</code></pre></div>
<table>
<thead>
<tr>
<th>Element</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><code>line</code></td>
<td>Data buffer that the console uses to save received characters until a new line is received.</td>
</tr>
</tbody>
</table>
<h3 id="list-of-functions">List of Functions</h3>
<p>The functions available in console are:</p>
<table>
<thead>
<tr>
<th>Function</th>
<th>Description</th>
</tr>
</thead>
<tbody>
<tr>
<td><a href="../console_echo/">console_echo</a></td>
<td>Controls whether echoing is on or off for the console.</td>
</tr>
<tr>
<td><a href="../console_init/">console_init (Mynewt 1.0 API)</a></td>
<td>Initializes the console.</td>
</tr>
<tr>
<td><a href="../console_is_init/">console_is_init</a></td>
<td>Returns a value indicating whether the console has been initialized or not.</td>
</tr>
<tr>
<td><a href="../console_printf/">console_printf</a></td>
<td>Writes a formatted message instead of raw output to the console.</td>
</tr>
<tr>
<td><a href="../console_read/">console_read</a></td>
<td>Copies up the to given number of bytes to the input string.</td>
</tr>
<tr>
<td><a href="../console_set_queues/">console_set_queues</a></td>
<td>Specifies the event queues for the console to use to manage input data.</td>
</tr>
<tr>
<td><a href="../console_write/">console_write</a></td>
<td>Queues characters to console display over serial port.</td>
</tr>
</tbody>
</table>
<div class="row">
<ul class="nav nav-pills" style="margin-bottom: 10px">
<li>
</li>
<li class="pull-right">
</li>
</ul>
</div>
<footer class="row">
<div class="col-xs-12">
<p class="copyright">Apache Mynewt is available under Apache License, version 2.0.</p>
</div>
<div class="col-xs-12">
<div class="logos">
<a href="https://www.apache.org/">
<img src="/img/asf_logo_wide_small.png" alt="Apache" title="Apache">
</a>
<p>
Copyright © 2015-2021 The Apache Software Foundation.<br>
<small class="footnote">
Apache Mynewt, Mynewt, Apache, the Apache feather logo, and the Apache Mynewt
project logo are either registered trademarks or trademarks of the Apache
Software Foundation in the United States and other countries.
</small>
</p>
<a href="">
<img src="https://www.countit.com/images/add_to_slack.png" alt="Slack Icon" title="Join our Slack Community" />
</a>
</div>
</div>
<a href="https://www.apache.org/licenses/">
<button class="button-footer-asf">
License
</button>
</a>
<a href="https://www.apache.org/foundation/sponsorship.html">
<button class="button-footer-asf">
Sponsorship
</button>
</a>
<a href="https://www.apache.org/foundation/thanks.html">
<button class="button-footer-asf">
Thanks
</button>
</a>
<a href="https://www.apache.org/security/">
<button class="button-footer-asf">
Security
</button>
</a>
<a href="https://apache.org/events/current-event">
<button class="button-footer-asf">
ASF Events
</button>
</a>
</footer>
</div>
</div>
</div>
<script src="../../../../js/jquery-1.10.2.min.js"></script>
<script src="../../../../js/bootstrap-3.0.3.min.js"></script>
<script src="../../../../js/highlight.pack.js"></script>
<script src="../../../../js/base.js"></script>
<script src="../../../../js/custom.js"></script>
<script src="search/main.js"></script>
</body>
</html>