diff --git a/.travis.yml b/.travis.yml index bb3900287..386829b5d 100644 --- a/.travis.yml +++ b/.travis.yml @@ -115,6 +115,6 @@ env: - BUILD_TYPE='compile-8051-ports' BUILD_CATEGORY='compile' BUILD_ARCH='8051' - BUILD_TYPE='compile-arm-apcs-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm-apcs' - BUILD_TYPE='compile-6502-ports' BUILD_CATEGORY='compile' BUILD_ARCH='6502' -# - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm' + - BUILD_TYPE='compile-arm-ports' BUILD_CATEGORY='compile' BUILD_ARCH='arm' - BUILD_TYPE='slip-radio' MAKE_TARGETS='cooja' - BUILD_TYPE='llsec' MAKE_TARGETS='cooja' diff --git a/apps/mqtt/Makefile.mqtt b/apps/mqtt/Makefile.mqtt new file mode 100644 index 000000000..06d7bd5ab --- /dev/null +++ b/apps/mqtt/Makefile.mqtt @@ -0,0 +1 @@ +mqtt_src = mqtt.c diff --git a/apps/mqtt/mqtt.c b/apps/mqtt/mqtt.c new file mode 100644 index 000000000..112c584cb --- /dev/null +++ b/apps/mqtt/mqtt.c @@ -0,0 +1,1484 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup mqtt-engine + * @{ + */ +/** + * \file + * Implementation of the Contiki MQTT engine + * + * \author + * Texas Instruments + */ +/*---------------------------------------------------------------------------*/ +#include "mqtt.h" +#include "contiki.h" +#include "contiki-net.h" +#include "contiki-lib.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "sys/etimer.h" +#include "sys/pt.h" +#include "net/rpl/rpl.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "dev/leds.h" + +#include "tcp-socket.h" + +#include "lib/assert.h" +#include "lib/list.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +#define MIN(a, b) ((a) < (b) ? (a) : (b)) +/*---------------------------------------------------------------------------*/ +#define DEBUG 0 +#if DEBUG +#define PRINTF(...) PRINTF(__VA_ARGS__) +#else +#define PRINTF(...) +#endif +/*---------------------------------------------------------------------------*/ +typedef enum { + MQTT_FHDR_MSG_TYPE_CONNECT = 0x10, + MQTT_FHDR_MSG_TYPE_CONNACK = 0x20, + MQTT_FHDR_MSG_TYPE_PUBLISH = 0x30, + MQTT_FHDR_MSG_TYPE_PUBACK = 0x40, + MQTT_FHDR_MSG_TYPE_PUBREC = 0x50, + MQTT_FHDR_MSG_TYPE_PUBREL = 0x60, + MQTT_FHDR_MSG_TYPE_PUBCOMP = 0x70, + MQTT_FHDR_MSG_TYPE_SUBSCRIBE = 0x80, + MQTT_FHDR_MSG_TYPE_SUBACK = 0x90, + MQTT_FHDR_MSG_TYPE_UNSUBSCRIBE = 0xA0, + MQTT_FHDR_MSG_TYPE_UNSUBACK = 0xB0, + MQTT_FHDR_MSG_TYPE_PINGREQ = 0xC0, + MQTT_FHDR_MSG_TYPE_PINGRESP = 0xD0, + MQTT_FHDR_MSG_TYPE_DISCONNECT = 0xE0, + + MQTT_FHDR_DUP_FLAG = 0x08, + + MQTT_FHDR_QOS_LEVEL_0 = 0x00, + MQTT_FHDR_QOS_LEVEL_1 = 0x02, + MQTT_FHDR_QOS_LEVEL_2 = 0x04, + + MQTT_FHDR_RETAIN_FLAG = 0x01, +} mqtt_fhdr_fields_t; +/*---------------------------------------------------------------------------*/ +typedef enum { + MQTT_VHDR_USERNAME_FLAG = 0x80, + MQTT_VHDR_PASSWORD_FLAG = 0x40, + + MQTT_VHDR_WILL_RETAIN_FLAG = 0x20, + MQTT_VHDR_WILL_QOS_LEVEL_0 = 0x00, + MQTT_VHDR_WILL_QOS_LEVEL_1 = 0x08, + MQTT_VHDR_WILL_QOS_LEVEL_2 = 0x10, + + MQTT_VHDR_WILL_FLAG = 0x04, + MQTT_VHDR_CLEAN_SESSION_FLAG = 0x02, +} mqtt_vhdr_conn_fields_t; +/*---------------------------------------------------------------------------*/ +typedef enum { + MQTT_VHDR_CONN_ACCEPTED, + MQTT_VHDR_CONN_REJECTED_PROTOCOL, + MQTT_VHDR_CONN_REJECTED_IDENTIFIER, + MQTT_VHDR_CONN_REJECTED_UNAVAILABLE, + MQTT_VHDR_CONN_REJECTED_BAD_USER_PASS, + MQTT_VHDR_CONN_REJECTED_UNAUTHORIZED, +} mqtt_vhdr_connack_fields_t; +/*---------------------------------------------------------------------------*/ +#define MQTT_CONNECT_VHDR_FLAGS_SIZE 12 + +#define MQTT_STRING_LEN_SIZE 2 +#define MQTT_MID_SIZE 2 +#define MQTT_QOS_SIZE 1 +/*---------------------------------------------------------------------------*/ +#define RESPONSE_WAIT_TIMEOUT (CLOCK_SECOND * 10) +/*---------------------------------------------------------------------------*/ +#define INCREMENT_MID(conn) (conn)->mid_counter += 2 +#define MQTT_STRING_LENGTH(s) (((s)->length) == 0 ? 0 : (MQTT_STRING_LEN_SIZE + (s)->length)) +/*---------------------------------------------------------------------------*/ +/* Protothread send macros */ +#define PT_MQTT_WRITE_BYTES(conn, data, len) \ + while(write_bytes(conn, data, len)) { \ + PT_WAIT_UNTIL(pt, (conn)->out_buffer_sent); \ + } + +#define PT_MQTT_WRITE_BYTE(conn, data) \ + while(write_byte(conn, data)) { \ + PT_WAIT_UNTIL(pt, (conn)->out_buffer_sent); \ + } +/*---------------------------------------------------------------------------*/ +/* + * Sends the continue send event and wait for that event. + * + * The reason we cannot use PROCESS_PAUSE() is since we would risk loosing any + * events posted during the sending process. + */ +#define PT_MQTT_WAIT_SEND() \ + do { \ + process_post(PROCESS_CURRENT(), mqtt_continue_send_event, NULL); \ + PROCESS_WAIT_EVENT(); \ + if(ev == mqtt_abort_now_event) { \ + conn->state = MQTT_CONN_STATE_ABORT_IMMEDIATE; \ + PT_EXIT(&conn->out_proto_thread); \ + process_post(PROCESS_CURRENT(), ev, data); \ + } else if(ev >= mqtt_event_min && ev <= mqtt_event_max) { \ + process_post(PROCESS_CURRENT(), ev, data); \ + } \ + } while(0) +/*---------------------------------------------------------------------------*/ +static process_event_t mqtt_do_connect_tcp_event; +static process_event_t mqtt_do_connect_mqtt_event; +static process_event_t mqtt_do_disconnect_mqtt_event; +static process_event_t mqtt_do_subscribe_event; +static process_event_t mqtt_do_unsubscribe_event; +static process_event_t mqtt_do_publish_event; +static process_event_t mqtt_do_pingreq_event; +static process_event_t mqtt_continue_send_event; +static process_event_t mqtt_abort_now_event; +process_event_t mqtt_update_event; + +/* + * Min and Max event numbers we want to acknowledge while we're in the process + * of doing something else. continue_send does not count, therefore must be + * allocated last + */ +static process_event_t mqtt_event_min; +static process_event_t mqtt_event_max; +/*---------------------------------------------------------------------------*/ +/* Prototypes */ +static int +tcp_input(struct tcp_socket *s, void *ptr, const uint8_t *input_data_ptr, + int input_data_len); + +static void tcp_event(struct tcp_socket *s, void *ptr, + tcp_socket_event_t event); + +static void reset_packet(struct mqtt_in_packet *packet); +/*---------------------------------------------------------------------------*/ +LIST(mqtt_conn_list); +/*---------------------------------------------------------------------------*/ +PROCESS(mqtt_process, "MQTT process"); +/*---------------------------------------------------------------------------*/ +static void +call_event(struct mqtt_connection *conn, + mqtt_event_t event, + void *data) +{ + conn->event_callback(conn, event, data); + process_post(conn->app_process, mqtt_update_event, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +reset_defaults(struct mqtt_connection *conn) +{ + conn->mid_counter = 1; + PT_INIT(&conn->out_proto_thread); + conn->waiting_for_pingresp = 0; + + reset_packet(&conn->in_packet); + conn->out_buffer_sent = 0; +} +/*---------------------------------------------------------------------------*/ +static void +abort_connection(struct mqtt_connection *conn) +{ + conn->out_buffer_ptr = conn->out_buffer; + conn->out_queue_full = 0; + + /* Reset outgoing packet */ + memset(&conn->out_packet, 0, sizeof(conn->out_packet)); + + tcp_socket_close(&conn->socket); + tcp_socket_unregister(&conn->socket); + + memset(&conn->socket, 0, sizeof(conn->socket)); + + conn->state = MQTT_CONN_STATE_NOT_CONNECTED; +} +/*---------------------------------------------------------------------------*/ +static void +connect_tcp(struct mqtt_connection *conn) +{ + conn->state = MQTT_CONN_STATE_TCP_CONNECTING; + + reset_defaults(conn); + tcp_socket_register(&(conn->socket), + conn, + conn->in_buffer, + MQTT_TCP_INPUT_BUFF_SIZE, + conn->out_buffer, + MQTT_TCP_OUTPUT_BUFF_SIZE, + tcp_input, + tcp_event); + tcp_socket_connect(&(conn->socket), &(conn->server_ip), conn->server_port); +} +/*---------------------------------------------------------------------------*/ +static void +disconnect_tcp(struct mqtt_connection *conn) +{ + conn->state = MQTT_CONN_STATE_DISCONNECTING; + tcp_socket_close(&(conn->socket)); + tcp_socket_unregister(&conn->socket); + + memset(&conn->socket, 0, sizeof(conn->socket)); +} +/*---------------------------------------------------------------------------*/ +static void +send_out_buffer(struct mqtt_connection *conn) +{ + if(conn->out_buffer_ptr - conn->out_buffer == 0) { + conn->out_buffer_sent = 1; + return; + } + conn->out_buffer_sent = 0; + + DBG("MQTT - (send_out_buffer) Space used in buffer: %i\n", + conn->out_buffer_ptr - conn->out_buffer); + + tcp_socket_send(&conn->socket, conn->out_buffer, + conn->out_buffer_ptr - conn->out_buffer); +} +/*---------------------------------------------------------------------------*/ +static void +string_to_mqtt_string(struct mqtt_string *mqtt_string, char *string) +{ + if(mqtt_string == NULL) { + return; + } + mqtt_string->string = string; + + if(string != NULL) { + mqtt_string->length = strlen(string); + } else { + mqtt_string->length = 0; + } +} +/*---------------------------------------------------------------------------*/ +static int +write_byte(struct mqtt_connection *conn, uint8_t data) +{ + DBG("MQTT - (write_byte) buff_size: %i write: '%02X'\n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr, + data); + + if(&conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr == 0) { + send_out_buffer(conn); + return 1; + } + + *conn->out_buffer_ptr = data; + conn->out_buffer_ptr++; + return 0; +} +/*---------------------------------------------------------------------------*/ +static int +write_bytes(struct mqtt_connection *conn, uint8_t *data, uint16_t len) +{ + uint16_t write_bytes; + write_bytes = + MIN(&conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr, + len - conn->out_write_pos); + + memcpy(conn->out_buffer_ptr, &data[conn->out_write_pos], write_bytes); + conn->out_write_pos += write_bytes; + conn->out_buffer_ptr += write_bytes; + + DBG("MQTT - (write_bytes) len: %u write_pos: %lu\n", len, + conn->out_write_pos); + + if(len - conn->out_write_pos == 0) { + conn->out_write_pos = 0; + return 0; + } else { + send_out_buffer(conn); + return len - conn->out_write_pos; + } +} +/*---------------------------------------------------------------------------*/ +static void +encode_remaining_length(uint8_t *remaining_length, + uint8_t *remaining_length_bytes, + uint32_t length) +{ + uint8_t digit; + + DBG("MQTT - Encoding length %lu\n", length); + + *remaining_length_bytes = 0; + do { + digit = length % 128; + length = length / 128; + if(length > 0) { + digit = digit | 0x80; + } + + remaining_length[*remaining_length_bytes] = digit; + (*remaining_length_bytes)++; + DBG("MQTT - Encode len digit '%u' length '%lu'\n", digit, length); + } while(length > 0 && *remaining_length_bytes < 5); + DBG("MQTT - remaining_length_bytes %u\n", *remaining_length_bytes); +} +/*---------------------------------------------------------------------------*/ +static void +keep_alive_callback(void *ptr) +{ + struct mqtt_connection *conn = ptr; + + DBG("MQTT - (keep_alive_callback) Called!\n"); + + /* The flag is set when the PINGREQ has been sent */ + if(conn->waiting_for_pingresp) { + PRINTF("MQTT - Disconnect due to no PINGRESP from broker.\n"); + disconnect_tcp(conn); + return; + } + + process_post(&mqtt_process, mqtt_do_pingreq_event, conn); +} +/*---------------------------------------------------------------------------*/ +static void +reset_packet(struct mqtt_in_packet *packet) +{ + memset(packet, 0, sizeof(struct mqtt_in_packet)); + packet->remaining_multiplier = 1; +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(connect_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending CONNECT message...\n"); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_CONNECT; + conn->out_packet.remaining_length = 0; + conn->out_packet.remaining_length += MQTT_CONNECT_VHDR_FLAGS_SIZE; + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->client_id); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.username); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->credentials.password); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.topic); + conn->out_packet.remaining_length += MQTT_STRING_LENGTH(&conn->will.message); + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, + conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + PT_MQTT_WRITE_BYTE(conn, 0); + PT_MQTT_WRITE_BYTE(conn, 6); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)MQTT_PROTOCOL_NAME, 6); + PT_MQTT_WRITE_BYTE(conn, MQTT_PROTOCOL_VERSION); + PT_MQTT_WRITE_BYTE(conn, conn->connect_vhdr_flags); + PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->keep_alive & 0x00FF)); + PT_MQTT_WRITE_BYTE(conn, conn->client_id.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->client_id.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->client_id.string, + conn->client_id.length); + if(conn->connect_vhdr_flags & MQTT_VHDR_WILL_FLAG) { + PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->will.topic.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.topic.string, + conn->will.topic.length); + PT_MQTT_WRITE_BYTE(conn, conn->will.message.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->will.message.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->will.message.string, + conn->will.message.length); + DBG("MQTT - Setting will topic to '%s' %u bytes and message to '%s' %u bytes\n", + conn->will.topic.string, + conn->will.topic.length, + conn->will.message.string, + conn->will.message.length); + } + if(conn->connect_vhdr_flags & MQTT_VHDR_USERNAME_FLAG) { + PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->credentials.username.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, + (uint8_t *)conn->credentials.username.string, + conn->credentials.username.length); + } + if(conn->connect_vhdr_flags & MQTT_VHDR_PASSWORD_FLAG) { + PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length << 8); + PT_MQTT_WRITE_BYTE(conn, conn->credentials.password.length & 0x00FF); + PT_MQTT_WRITE_BYTES(conn, + (uint8_t *)conn->credentials.password.string, + conn->credentials.password.length); + } + + /* Send out buffer */ + send_out_buffer(conn); + conn->state = MQTT_CONN_STATE_CONNECTING_TO_BROKER; + + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* Wait for CONNACK */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for CONNACK\n"); + /* We stick to the letter of the spec here: Tear the connection down */ + mqtt_disconnect(conn); + } + reset_packet(&conn->in_packet); + + DBG("MQTT - Done sending CONNECT\n"); + +#if DEBUG_MQTT == 1 + DBG("MQTT - CONNECT message sent: \n"); + uint16_t i; + for(i = 0; i < (conn->out_buffer_ptr - conn->out_buffer); i++) { + DBG("%02X ", conn->out_buffer[i]); + } + DBG("\n"); +#endif + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(disconnect_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_DISCONNECT); + PT_MQTT_WRITE_BYTE(conn, 0); + + send_out_buffer(conn); + + /* + * Wait a couple of seconds for a TCP ACK. We don't really need the ACK, + * we do want the TCP/IP stack to actually send this disconnect before we + * tear down the session. + */ + timer_set(&conn->t, (CLOCK_SECOND * 2)); + PT_WAIT_UNTIL(pt, conn->out_buffer_sent || timer_expired(&conn->t)); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(subscribe_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending subscribe message! topic %s topic_length %i\n", + conn->out_packet.topic, + conn->out_packet.topic_length); + DBG("MQTT - Buffer space is %i \n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_SUBSCRIBE | MQTT_FHDR_QOS_LEVEL_1; + conn->out_packet.remaining_length = MQTT_MID_SIZE + + MQTT_STRING_LEN_SIZE + + conn->out_packet.topic_length + + MQTT_QOS_SIZE; + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, + conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + /* Write Variable Header */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); + /* Write Payload */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, + conn->out_packet.topic_length); + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.qos); + + /* Send out buffer */ + send_out_buffer(conn); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* Wait for SUBACK. */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for SUBACK\n"); + } + reset_packet(&conn->in_packet); + + /* This is clear after the entire transaction is complete */ + conn->out_queue_full = 0; + + DBG("MQTT - Done in send_subscribe!\n"); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(unsubscribe_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending unsubscribe message on topic %s topic_length %i\n", + conn->out_packet.topic, + conn->out_packet.topic_length); + DBG("MQTT - Buffer space is %i \n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_UNSUBSCRIBE | + MQTT_FHDR_QOS_LEVEL_1; + conn->out_packet.remaining_length = MQTT_MID_SIZE + + MQTT_STRING_LEN_SIZE + + conn->out_packet.topic_length; + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + /* Write Variable Header */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); + /* Write Payload */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, + conn->out_packet.topic_length); + + /* Send out buffer */ + send_out_buffer(conn); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* Wait for UNSUBACK */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for UNSUBACK\n"); + } + + reset_packet(&conn->in_packet); + + /* This is clear after the entire transaction is complete */ + conn->out_queue_full = 0; + + DBG("MQTT - Done writing subscribe message to out buffer!\n"); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(publish_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending publish message! topic %s topic_length %i\n", + conn->out_packet.topic, + conn->out_packet.topic_length); + DBG("MQTT - Buffer space is %i \n", + &conn->out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE] - conn->out_buffer_ptr); + + /* Set up FHDR */ + conn->out_packet.fhdr = MQTT_FHDR_MSG_TYPE_PUBLISH | + conn->out_packet.qos << 1; + if(conn->out_packet.retain == MQTT_RETAIN_ON) { + conn->out_packet.fhdr |= MQTT_FHDR_RETAIN_FLAG; + } + conn->out_packet.remaining_length = MQTT_STRING_LEN_SIZE + + conn->out_packet.topic_length + + conn->out_packet.payload_size; + if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { + conn->out_packet.remaining_length += MQTT_MID_SIZE; + } + encode_remaining_length(conn->out_packet.remaining_length_enc, + &conn->out_packet.remaining_length_enc_bytes, + conn->out_packet.remaining_length); + if(conn->out_packet.remaining_length_enc_bytes > 4) { + call_event(conn, MQTT_EVENT_PROTOCOL_ERROR, NULL); + PRINTF("MQTT - Error, remaining length > 4 bytes\n"); + PT_EXIT(pt); + } + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, conn->out_packet.fhdr); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.remaining_length_enc, + conn->out_packet.remaining_length_enc_bytes); + /* Write Variable Header */ + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length >> 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.topic_length & 0x00FF)); + PT_MQTT_WRITE_BYTES(conn, (uint8_t *)conn->out_packet.topic, + conn->out_packet.topic_length); + if(conn->out_packet.qos > MQTT_QOS_LEVEL_0) { + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid << 8)); + PT_MQTT_WRITE_BYTE(conn, (conn->out_packet.mid & 0x00FF)); + } + /* Write Payload */ + PT_MQTT_WRITE_BYTES(conn, + conn->out_packet.payload, + conn->out_packet.payload_size); + + send_out_buffer(conn); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + /* + * If QoS is zero then wait until the message has been sent, since there is + * no ACK to wait for. + * + * Also notify the app will not be notified via PUBACK or PUBCOMP + */ + if(conn->out_packet.qos == 0) { + process_post(conn->app_process, mqtt_update_event, NULL); + } else if(conn->out_packet.qos == 1) { + /* Wait for PUBACK */ + reset_packet(&conn->in_packet); + PT_WAIT_UNTIL(pt, conn->out_packet.qos_state == MQTT_QOS_STATE_GOT_ACK || + timer_expired(&conn->t)); + if(timer_expired(&conn->t)) { + DBG("Timeout waiting for PUBACK\n"); + } + if(conn->in_packet.mid != conn->out_packet.mid) { + DBG("MQTT - Warning, got PUBACK with none matching MID. Currently there " + "is no support for several concurrent PUBLISH messages.\n"); + } + } else if(conn->out_packet.qos == 2) { + DBG("MQTT - QoS not implemented yet.\n"); + /* Should wait for PUBREC, send PUBREL and then wait for PUBCOMP */ + } + + reset_packet(&conn->in_packet); + + /* This is clear after the entire transaction is complete */ + conn->out_queue_full = 0; + + DBG("MQTT - Publish Enqueued\n"); + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static +PT_THREAD(pingreq_pt(struct pt *pt, struct mqtt_connection *conn)) +{ + PT_BEGIN(pt); + + DBG("MQTT - Sending PINGREQ\n"); + + /* Write Fixed Header */ + PT_MQTT_WRITE_BYTE(conn, MQTT_FHDR_MSG_TYPE_PINGREQ); + PT_MQTT_WRITE_BYTE(conn, 0); + + send_out_buffer(conn); + + /* Start timeout for reply. */ + conn->waiting_for_pingresp = 1; + + /* Wait for PINGRESP or timeout */ + reset_packet(&conn->in_packet); + timer_set(&conn->t, RESPONSE_WAIT_TIMEOUT); + + PT_WAIT_UNTIL(pt, conn->in_packet.packet_received || timer_expired(&conn->t)); + + reset_packet(&conn->in_packet); + + conn->waiting_for_pingresp = 0; + + PT_END(pt); +} +/*---------------------------------------------------------------------------*/ +static void +handle_connack(struct mqtt_connection *conn) +{ + DBG("MQTT - Got CONNACK\n"); + + if(conn->in_packet.payload[1] != 0) { + PRINTF("MQTT - Connection refused with Return Code %i\n", + conn->in_packet.payload[1]); + call_event(conn, + MQTT_EVENT_CONNECTION_REFUSED_ERROR, + &conn->in_packet.payload[1]); + } + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + + ctimer_set(&conn->keep_alive_timer, conn->keep_alive * CLOCK_SECOND, + keep_alive_callback, conn); + + /* Always reset packet before callback since it might be used directly */ + conn->state = MQTT_CONN_STATE_CONNECTED_TO_BROKER; + call_event(conn, MQTT_EVENT_CONNECTED, NULL); +} +/*---------------------------------------------------------------------------*/ +static void +handle_pingresp(struct mqtt_connection *conn) +{ + DBG("MQTT - Got RINGRESP\n"); +} +/*---------------------------------------------------------------------------*/ +static void +handle_suback(struct mqtt_connection *conn) +{ + struct mqtt_suback_event suback_event; + + DBG("MQTT - Got SUBACK\n"); + + /* Only accept SUBACKS with X topic QoS response, assume 1 */ + if(conn->in_packet.remaining_length > MQTT_MID_SIZE + + MQTT_MAX_TOPICS_PER_SUBSCRIBE * MQTT_QOS_SIZE) { + DBG("MQTT - Error, SUBACK with > 1 topic, not supported.\n"); + } + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + + suback_event.mid = (conn->in_packet.payload[0] << 8) | + (conn->in_packet.payload[1]); + suback_event.qos_level = conn->in_packet.payload[2]; + conn->in_packet.mid = suback_event.mid; + + if(conn->in_packet.mid != conn->out_packet.mid) { + DBG("MQTT - Warning, got SUBACK with none matching MID. Currently there is" + "no support for several concurrent SUBSCRIBE messages.\n"); + } + + /* Always reset packet before callback since it might be used directly */ + call_event(conn, MQTT_EVENT_SUBACK, &suback_event); +} +/*---------------------------------------------------------------------------*/ +static void +handle_unsuback(struct mqtt_connection *conn) +{ + DBG("MQTT - Got UNSUBACK\n"); + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + conn->in_packet.mid = (conn->in_packet.payload[0] << 8) | + (conn->in_packet.payload[1]); + + if(conn->in_packet.mid != conn->out_packet.mid) { + DBG("MQTT - Warning, got UNSUBACK with none matching MID. Currently there is" + "no support for several concurrent UNSUBSCRIBE messages.\n"); + } + + call_event(conn, MQTT_EVENT_UNSUBACK, &conn->in_packet.mid); +} +/*---------------------------------------------------------------------------*/ +static void +handle_puback(struct mqtt_connection *conn) +{ + DBG("MQTT - Got PUBACK\n"); + + conn->out_packet.qos_state = MQTT_QOS_STATE_GOT_ACK; + conn->in_packet.mid = (conn->in_packet.payload[0] << 8) | + (conn->in_packet.payload[1]); + + call_event(conn, MQTT_EVENT_PUBACK, &conn->in_packet.mid); +} +/*---------------------------------------------------------------------------*/ +static void +handle_publish(struct mqtt_connection *conn) +{ + DBG("MQTT - Got PUBLISH, called once per manageable chunk of message.\n"); + DBG("MQTT - Handling publish on topic '%s'\n", conn->in_publish_msg.topic); + + DBG("MQTT - This chunk is %i bytes\n", conn->in_packet.payload_pos); + + if(((conn->in_packet.fhdr & 0x09) >> 1) > 0) { + PRINTF("MQTT - Error, got incoming PUBLISH with QoS > 0, not supported atm!\n"); + } + + call_event(conn, MQTT_EVENT_PUBLISH, &conn->in_publish_msg); + + if(conn->in_publish_msg.first_chunk == 1) { + conn->in_publish_msg.first_chunk = 0; + } + + /* If this is the last time handle_publish will be called, reset packet. */ + if(conn->in_publish_msg.payload_left == 0) { + + /* Check for QoS and initiate the reply, do not rely on the data in the + * in_packet being untouched. */ + + DBG("MQTT - (handle_publish) resetting packet.\n"); + reset_packet(&conn->in_packet); + } +} +/*---------------------------------------------------------------------------*/ +static void +parse_publish_vhdr(struct mqtt_connection *conn, + uint32_t *pos, + const uint8_t *input_data_ptr, + int input_data_len) +{ + uint16_t copy_bytes; + + /* Read out topic length */ + if(conn->in_packet.topic_len_received == 0) { + conn->in_packet.topic_len = (input_data_ptr[(*pos)++] << 8); + conn->in_packet.byte_counter++; + if(*pos >= input_data_len) { + return; + } + conn->in_packet.topic_len |= input_data_ptr[(*pos)++]; + conn->in_packet.byte_counter++; + conn->in_packet.topic_len_received = 1; + + DBG("MQTT - Read PUBLISH topic len %i\n", conn->in_packet.topic_len); + /* WARNING: Check here if TOPIC fits in payload area, otherwise error */ + } + + /* Read out topic */ + if(conn->in_packet.topic_len_received == 1 && + conn->in_packet.topic_received == 0) { + copy_bytes = MIN(conn->in_packet.topic_len - conn->in_packet.topic_pos, + input_data_len - *pos); + DBG("MQTT - topic_pos: %i copy_bytes: %i", conn->in_packet.topic_pos, + copy_bytes); + memcpy(&conn->in_publish_msg.topic[conn->in_packet.topic_pos], + &input_data_ptr[*pos], + copy_bytes); + (*pos) += copy_bytes; + conn->in_packet.byte_counter += copy_bytes; + conn->in_packet.topic_pos += copy_bytes; + + if(conn->in_packet.topic_len - conn->in_packet.topic_pos == 0) { + DBG("MQTT - Got topic '%s'", conn->in_publish_msg.topic); + conn->in_packet.topic_received = 1; + conn->in_publish_msg.topic[conn->in_packet.topic_pos] = '\0'; + conn->in_publish_msg.payload_length = + conn->in_packet.remaining_length - conn->in_packet.topic_len - 2; + conn->in_publish_msg.payload_left = conn->in_publish_msg.payload_length; + } + + /* Set this once per incomming publish message */ + conn->in_publish_msg.first_chunk = 1; + } +} +/*---------------------------------------------------------------------------*/ +static int +tcp_input(struct tcp_socket *s, + void *ptr, + const uint8_t *input_data_ptr, + int input_data_len) +{ + struct mqtt_connection *conn = ptr; + uint32_t pos = 0; + uint32_t copy_bytes = 0; + uint8_t byte; + + if(input_data_len == 0) { + return 0; + } + + if(conn->in_packet.packet_received) { + reset_packet(&conn->in_packet); + } + + DBG("tcp_input with %i bytes of data:\n", input_data_len); + + /* Read the fixed header field, if we do not have it */ + if(!conn->in_packet.fhdr) { + conn->in_packet.fhdr = input_data_ptr[pos++]; + conn->in_packet.byte_counter++; + + DBG("MQTT - Read VHDR '%02X'\n", conn->in_packet.fhdr); + + if(pos >= input_data_len) { + return 0; + } + } + + /* Read the Remaining Length field, if we do not have it */ + if(!conn->in_packet.has_remaining_length) { + do { + if(pos >= input_data_len) { + return 0; + } + + byte = input_data_ptr[pos++]; + conn->in_packet.byte_counter++; + conn->in_packet.remaining_length_bytes++; + DBG("MQTT - Read Remaining Length byte\n"); + + if(conn->in_packet.byte_counter > 5) { + call_event(conn, MQTT_EVENT_ERROR, NULL); + DBG("Received more then 4 byte 'remaining lenght'."); + return 0; + } + + conn->in_packet.remaining_length += + (byte & 127) * conn->in_packet.remaining_multiplier; + conn->in_packet.remaining_multiplier *= 128; + } while((byte & 128) != 0); + + DBG("MQTT - Finished reading remaining length byte\n"); + conn->in_packet.has_remaining_length = 1; + } + + /* + * Check for unsupported payload length. Will read all incoming data from the + * server in any case and then reset the packet. + * + * TODO: Decide if we, for example, want to disconnect instead. + */ + if((conn->in_packet.remaining_length > MQTT_INPUT_BUFF_SIZE) && + (conn->in_packet.fhdr & 0xF0) != MQTT_FHDR_MSG_TYPE_PUBLISH) { + + PRINTF("MQTT - Error, unsupported payload size for non-PUBLISH message\n"); + + conn->in_packet.byte_counter += input_data_len; + if(conn->in_packet.byte_counter >= + (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { + conn->in_packet.packet_received = 1; + } + return 0; + } + + /* + * Supported payload, reads out both VHDR and Payload of all packets. + * + * Note: There will always be at least one byte left to read when we enter + * this loop. + */ + while(conn->in_packet.byte_counter < + (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)) { + + if((conn->in_packet.fhdr & 0xF0) == MQTT_FHDR_MSG_TYPE_PUBLISH && + conn->in_packet.topic_received == 0) { + parse_publish_vhdr(conn, &pos, input_data_ptr, input_data_len); + } + + /* Read in as much as we can into the packet payload */ + copy_bytes = MIN(input_data_len - pos, + MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos); + DBG("- Copied %lu payload bytes\n", copy_bytes); + memcpy(&conn->in_packet.payload[conn->in_packet.payload_pos], + &input_data_ptr[pos], + copy_bytes); + conn->in_packet.byte_counter += copy_bytes; + conn->in_packet.payload_pos += copy_bytes; + pos += copy_bytes; + + uint8_t i; + DBG("MQTT - Copied bytes: \n"); + for(i = 0; i < copy_bytes; i++) { + DBG("%02X ", conn->in_packet.payload[i]); + } + DBG("\n"); + + /* Full buffer, shall only happen to PUBLISH messages. */ + if(MQTT_INPUT_BUFF_SIZE - conn->in_packet.payload_pos == 0) { + conn->in_publish_msg.payload_chunk = conn->in_packet.payload; + conn->in_publish_msg.payload_chunk_length = MQTT_INPUT_BUFF_SIZE; + conn->in_publish_msg.payload_left -= MQTT_INPUT_BUFF_SIZE; + + handle_publish(conn); + + conn->in_publish_msg.payload_chunk = conn->in_packet.payload; + conn->in_packet.payload_pos = 0; + } + + if(pos >= input_data_len && + (conn->in_packet.byte_counter < (MQTT_FHDR_SIZE + conn->in_packet.remaining_length))) { + return 0; + } + } + + /* Debug information */ + DBG("\n"); + /* Take care of input */ + DBG("MQTT - Finished reading packet!\n"); + /* What to return? */ + DBG("MQTT - total data was %i bytes of data. \n", + (MQTT_FHDR_SIZE + conn->in_packet.remaining_length)); + + /* Handle packet here. */ + switch(conn->in_packet.fhdr & 0xF0) { + case MQTT_FHDR_MSG_TYPE_CONNACK: + handle_connack(conn); + break; + case MQTT_FHDR_MSG_TYPE_PUBLISH: + /* This is the only or the last chunk of publish payload */ + conn->in_publish_msg.payload_chunk = conn->in_packet.payload; + conn->in_publish_msg.payload_chunk_length = conn->in_packet.payload_pos; + conn->in_publish_msg.payload_left = 0; + handle_publish(conn); + break; + case MQTT_FHDR_MSG_TYPE_PUBACK: + handle_puback(conn); + break; + case MQTT_FHDR_MSG_TYPE_SUBACK: + handle_suback(conn); + break; + case MQTT_FHDR_MSG_TYPE_UNSUBACK: + handle_unsuback(conn); + break; + case MQTT_FHDR_MSG_TYPE_PINGRESP: + handle_pingresp(conn); + break; + + /* QoS 2 not implemented yet */ + case MQTT_FHDR_MSG_TYPE_PUBREC: + case MQTT_FHDR_MSG_TYPE_PUBREL: + case MQTT_FHDR_MSG_TYPE_PUBCOMP: + call_event(conn, MQTT_EVENT_NOT_IMPLEMENTED_ERROR, NULL); + PRINTF("MQTT - Got unhandled MQTT Message Type '%i'", + (conn->in_packet.fhdr & 0xF0)); + break; + + default: + /* All server-only message */ + PRINTF("MQTT - Got MQTT Message Type '%i'", (conn->in_packet.fhdr & 0xF0)); + break; + } + + conn->in_packet.packet_received = 1; + + return 0; +} +/*---------------------------------------------------------------------------*/ +/* + * Handles TCP events from Simple TCP + */ +static void +tcp_event(struct tcp_socket *s, void *ptr, tcp_socket_event_t event) +{ + struct mqtt_connection *conn = ptr; + + /* Take care of event */ + switch(event) { + + /* Fall through to manage different disconnect event the same way. */ + case TCP_SOCKET_CLOSED: + case TCP_SOCKET_TIMEDOUT: + case TCP_SOCKET_ABORTED: { + + DBG("MQTT - Disconnected by tcp event %d\n", event); + process_post(&mqtt_process, mqtt_abort_now_event, conn); + conn->state = MQTT_CONN_STATE_NOT_CONNECTED; + ctimer_stop(&conn->keep_alive_timer); + call_event(conn, MQTT_EVENT_DISCONNECTED, &event); + abort_connection(conn); + + /* If connecting retry */ + if(conn->auto_reconnect == 1) { + connect_tcp(conn); + } + break; + } + case TCP_SOCKET_CONNECTED: { + conn->state = MQTT_CONN_STATE_TCP_CONNECTED; + conn->out_buffer_sent = 1; + + process_post(&mqtt_process, mqtt_do_connect_mqtt_event, conn); + break; + } + case TCP_SOCKET_DATA_SENT: { + DBG("MQTT - Got TCP_DATA_SENT\n"); + + if(conn->socket.output_data_len == 0) { + conn->out_buffer_sent = 1; + conn->out_buffer_ptr = conn->out_buffer; + } + + ctimer_restart(&conn->keep_alive_timer); + break; + } + + default: { + DBG("MQTT - TCP Event %d is currently not managed by the tcp event callback\n", + event); + } + } +} +/*---------------------------------------------------------------------------*/ +PROCESS_THREAD(mqtt_process, ev, data) +{ + static struct mqtt_connection *conn; + + PROCESS_BEGIN(); + + while(1) { + PROCESS_WAIT_EVENT(); + + if(ev == mqtt_abort_now_event) { + DBG("MQTT - Abort\n"); + conn = data; + conn->state = MQTT_CONN_STATE_ABORT_IMMEDIATE; + + abort_connection(conn); + } + if(ev == mqtt_do_connect_tcp_event) { + conn = data; + DBG("MQTT - Got mqtt_do_connect_tcp_event!\n"); + connect_tcp(conn); + } + if(ev == mqtt_do_connect_mqtt_event) { + conn = data; + conn->socket.output_data_max_seg = conn->max_segment_size; + DBG("MQTT - Got mqtt_do_connect_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1) { + PT_INIT(&conn->out_proto_thread); + while(connect_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_disconnect_mqtt_event) { + conn = data; + DBG("MQTT - Got mqtt_do_disconnect_mqtt_event!\n"); + + /* Send MQTT Disconnect if we are connected */ + if(conn->state == MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT) { + if(conn->out_buffer_sent == 1) { + PT_INIT(&conn->out_proto_thread); + while(disconnect_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state != MQTT_CONN_STATE_ABORT_IMMEDIATE) { + PT_MQTT_WAIT_SEND(); + } + abort_connection(conn); + call_event(conn, MQTT_EVENT_DISCONNECTED, &ev); + } else { + process_post(&mqtt_process, mqtt_do_disconnect_mqtt_event, conn); + } + } + } + if(ev == mqtt_do_pingreq_event) { + conn = data; + DBG("MQTT - Got mqtt_do_pingreq_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(pingreq_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_subscribe_event) { + conn = data; + DBG("MQTT - Got mqtt_do_subscribe_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(subscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_unsubscribe_event) { + conn = data; + DBG("MQTT - Got mqtt_do_unsubscribe_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(unsubscribe_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + if(ev == mqtt_do_publish_event) { + conn = data; + DBG("MQTT - Got mqtt_do_publish_mqtt_event!\n"); + + if(conn->out_buffer_sent == 1 && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_INIT(&conn->out_proto_thread); + while(publish_pt(&conn->out_proto_thread, conn) < PT_EXITED && + conn->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + PT_MQTT_WAIT_SEND(); + } + } + } + } + PROCESS_END(); +} +/*---------------------------------------------------------------------------*/ +void +mqtt_init(void) +{ + static uint8_t inited = 0; + if(!inited) { + mqtt_do_connect_tcp_event = process_alloc_event(); + mqtt_event_min = mqtt_do_connect_tcp_event; + + mqtt_do_connect_mqtt_event = process_alloc_event(); + mqtt_do_disconnect_mqtt_event = process_alloc_event(); + mqtt_do_subscribe_event = process_alloc_event(); + mqtt_do_unsubscribe_event = process_alloc_event(); + mqtt_do_publish_event = process_alloc_event(); + mqtt_do_pingreq_event = process_alloc_event(); + mqtt_update_event = process_alloc_event(); + mqtt_abort_now_event = process_alloc_event(); + mqtt_event_max = mqtt_abort_now_event; + + mqtt_continue_send_event = process_alloc_event(); + + list_init(mqtt_conn_list); + process_start(&mqtt_process, NULL); + inited = 1; + } +} +/*---------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_register(struct mqtt_connection *conn, struct process *app_process, + char *client_id, mqtt_event_callback_t event_callback, + uint16_t max_segment_size) +{ + if(strlen(client_id) < 1) { + return MQTT_STATUS_INVALID_ARGS_ERROR; + } + + /* Set defaults - Set all to zero to begin with */ + memset(conn, 0, sizeof(struct mqtt_connection)); + string_to_mqtt_string(&conn->client_id, client_id); + conn->event_callback = event_callback; + conn->app_process = app_process; + conn->auto_reconnect = 1; + conn->max_segment_size = max_segment_size; + reset_defaults(conn); + + mqtt_init(); + list_add(mqtt_conn_list, conn); + + DBG("MQTT - Registered successfully\n"); + + return MQTT_STATUS_OK; +} +/*---------------------------------------------------------------------------*/ +/* + * Connect to MQTT broker. + * + * N.B. Non-blocking call. + */ +mqtt_status_t +mqtt_connect(struct mqtt_connection *conn, char *host, uint16_t port, + uint16_t keep_alive) +{ + uip_ip6addr_t ip6addr; + uip_ipaddr_t *ipaddr; + ipaddr = &ip6addr; + + /* Check if we are already trying to connect */ + if(conn->state > MQTT_CONN_STATE_NOT_CONNECTED) { + return MQTT_STATUS_OK; + } + + conn->server_host = host; + conn->keep_alive = keep_alive; + conn->server_port = port; + conn->out_buffer_ptr = conn->out_buffer; + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + conn->connect_vhdr_flags |= MQTT_VHDR_CLEAN_SESSION_FLAG; + + /* convert the string IPv6 address to a numeric IPv6 address */ + uiplib_ip6addrconv(host, &ip6addr); + + uip_ipaddr_copy(&(conn->server_ip), ipaddr); + + /* + * Initiate the connection if the IP could be resolved. Otherwise the + * connection will be initiated when the DNS lookup is finished, in the main + * event loop. + */ + process_post(&mqtt_process, mqtt_do_connect_tcp_event, conn); + + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +void +mqtt_disconnect(struct mqtt_connection *conn) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return; + } + + conn->state = MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT; + + process_post(&mqtt_process, mqtt_do_disconnect_mqtt_event, conn); +} +/*----------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_subscribe(struct mqtt_connection *conn, uint16_t *mid, char *topic, + mqtt_qos_level_t qos_level) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return MQTT_STATUS_NOT_CONNECTED_ERROR; + } + + DBG("MQTT - Call to mqtt_subscribe...\n"); + + /* Currently don't have a queue, so only one item at a time */ + if(conn->out_queue_full) { + DBG("MQTT - Not accepted!\n"); + return MQTT_STATUS_OUT_QUEUE_FULL; + } + conn->out_queue_full = 1; + DBG("MQTT - Accepted!\n"); + + conn->out_packet.mid = INCREMENT_MID(conn); + conn->out_packet.topic = topic; + conn->out_packet.topic_length = strlen(topic); + conn->out_packet.qos = qos_level; + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + + process_post(&mqtt_process, mqtt_do_subscribe_event, conn); + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_unsubscribe(struct mqtt_connection *conn, uint16_t *mid, char *topic) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return MQTT_STATUS_NOT_CONNECTED_ERROR; + } + + DBG("MQTT - Call to mqtt_unsubscribe...\n"); + /* Currently don't have a queue, so only one item at a time */ + if(conn->out_queue_full) { + DBG("MQTT - Not accepted!\n"); + return MQTT_STATUS_OUT_QUEUE_FULL; + } + conn->out_queue_full = 1; + DBG("MQTT - Accepted!\n"); + + conn->out_packet.mid = INCREMENT_MID(conn); + conn->out_packet.topic = topic; + conn->out_packet.topic_length = strlen(topic); + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + + process_post(&mqtt_process, mqtt_do_unsubscribe_event, conn); + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +mqtt_status_t +mqtt_publish(struct mqtt_connection *conn, uint16_t *mid, char *topic, + uint8_t *payload, uint32_t payload_size, + mqtt_qos_level_t qos_level, mqtt_retain_t retain) +{ + if(conn->state != MQTT_CONN_STATE_CONNECTED_TO_BROKER) { + return MQTT_STATUS_NOT_CONNECTED_ERROR; + } + + DBG("MQTT - Call to mqtt_publish...\n"); + + /* Currently don't have a queue, so only one item at a time */ + if(conn->out_queue_full) { + DBG("MQTT - Not accepted!\n"); + return MQTT_STATUS_OUT_QUEUE_FULL; + } + conn->out_queue_full = 1; + DBG("MQTT - Accepted!\n"); + + conn->out_packet.mid = INCREMENT_MID(conn); + conn->out_packet.retain = retain; + conn->out_packet.topic = topic; + conn->out_packet.topic_length = strlen(topic); + conn->out_packet.payload = payload; + conn->out_packet.payload_size = payload_size; + conn->out_packet.qos = qos_level; + conn->out_packet.qos_state = MQTT_QOS_STATE_NO_ACK; + + process_post(&mqtt_process, mqtt_do_publish_event, conn); + return MQTT_STATUS_OK; +} +/*----------------------------------------------------------------------------*/ +void +mqtt_set_username_password(struct mqtt_connection *conn, char *username, + char *password) +{ + /* Set strings, NULL string will simply set length to zero */ + string_to_mqtt_string(&conn->credentials.username, username); + string_to_mqtt_string(&conn->credentials.password, password); + + /* Set CONNECT VHDR flags */ + if(username != NULL) { + conn->connect_vhdr_flags |= MQTT_VHDR_USERNAME_FLAG; + } else { + conn->connect_vhdr_flags &= ~MQTT_VHDR_USERNAME_FLAG; + } + if(password != NULL) { + conn->connect_vhdr_flags |= MQTT_VHDR_PASSWORD_FLAG; + } else { + conn->connect_vhdr_flags &= ~MQTT_VHDR_PASSWORD_FLAG; + } +} +/*----------------------------------------------------------------------------*/ +void +mqtt_set_last_will(struct mqtt_connection *conn, char *topic, char *message, + mqtt_qos_level_t qos) +{ + /* Set strings, NULL string will simply set length to zero */ + string_to_mqtt_string(&conn->will.topic, topic); + string_to_mqtt_string(&conn->will.message, message); + + /* Currently not used! */ + conn->will.qos = qos; + + if(topic != NULL) { + conn->connect_vhdr_flags |= MQTT_VHDR_WILL_FLAG | + MQTT_VHDR_WILL_RETAIN_FLAG; + } +} +/*----------------------------------------------------------------------------*/ +/** @} */ diff --git a/apps/mqtt/mqtt.h b/apps/mqtt/mqtt.h new file mode 100644 index 000000000..4b27fa30c --- /dev/null +++ b/apps/mqtt/mqtt.h @@ -0,0 +1,509 @@ +/* + * Copyright (c) 2015, Texas Instruments Incorporated - http://www.ti.com/ + * All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in the + * documentation and/or other materials provided with the distribution. + * 3. Neither the name of the copyright holder nor the names of its + * contributors may be used to endorse or promote products derived + * from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS + * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT + * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS + * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE + * COPYRIGHT HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, + * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES + * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) + * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, + * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) + * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED + * OF THE POSSIBILITY OF SUCH DAMAGE. + */ +/*---------------------------------------------------------------------------*/ +/** + * \addtogroup apps + * @{ + * + * \defgroup mqtt-engine An implementation of MQTT v3.1 + * @{ + * + * This application is an engine for MQTT v3.1. It supports QoS Levels 0 and 1. + * + * MQTT is a Client Server publish/subscribe messaging transport protocol. + * It is light weight, open, simple, and designed so as to be easy to implement. + * These characteristics make it ideal for use in many situations, including + * constrained environments such as for communication in Machine to Machine + * (M2M) and Internet of Things (IoT) contexts where a small code footprint is + * required and/or network bandwidth is at a premium. + * + * The protocol runs over TCP/IP, more specifically tcp_socket. + * Its features include: + * + * - Use of the publish/subscribe message pattern which provides + * one-to-many message distribution and decoupling of applications. + * - A messaging transport that is agnostic to the content of the payload. + * Three qualities of service for message delivery: + * -- "At most once" (0), where messages are delivered according to the best + * efforts of the operating environment. Message loss can occur. + * This level could be used, for example, with ambient sensor data where it + * does not matter if an individual reading is lost as the next one will be + * published soon after. + * --"At least once" (1), where messages are assured to arrive but duplicates + * can occur. + * -- "Exactly once" (2), where message are assured to arrive exactly once. + * This level could be used, for example, with billing systems where duplicate + * or lost messages could lead to incorrect charges being applied. This QoS + * level is currently not supported in this implementation. + * + * - A small transport overhead and protocol exchanges minimized to reduce + * network traffic. + * - A mechanism, Last Will, to notify interested parties when an abnormal + * disconnection occurs. + * + * The protocol specification and other useful information can be found + * here: http://mqtt.org + * + */ +/** + * \file + * Header file for the Contiki MQTT engine + * + * \author + * Texas Instruments + */ +/*---------------------------------------------------------------------------*/ +#ifndef MQTT_H_ +#define MQTT_H_ +/*---------------------------------------------------------------------------*/ +#include "contiki.h" +#include "contiki-net.h" +#include "contiki-lib.h" +#include "lib/random.h" +#include "sys/ctimer.h" +#include "sys/etimer.h" +#include "net/rpl/rpl.h" +#include "net/ip/uip.h" +#include "net/ipv6/uip-ds6.h" +#include "dev/leds.h" + +#include "tcp-socket.h" +#include "udp-socket.h" + +#include +#include +#include +/*---------------------------------------------------------------------------*/ +/* Protocol constants */ +#define MQTT_CLIENT_ID_MAX_LEN 23 + +/* Size of the underlying TCP buffers */ +#define MQTT_TCP_INPUT_BUFF_SIZE 512 +#define MQTT_TCP_OUTPUT_BUFF_SIZE 512 + +#define MQTT_INPUT_BUFF_SIZE 512 +#define MQTT_MAX_TOPIC_LENGTH 64 +#define MQTT_MAX_TOPICS_PER_SUBSCRIBE 1 + +#define MQTT_FHDR_SIZE 1 +#define MQTT_MAX_REMAINING_LENGTH_BYTES 4 +#define MQTT_PROTOCOL_VERSION 3 +#define MQTT_PROTOCOL_NAME "MQIsdp" +#define MQTT_TOPIC_MAX_LENGTH 128 +/*---------------------------------------------------------------------------*/ +/* + * Debug configuration, this is similar but not exactly like the Debugging + * System discussion at https://github.com/contiki-os/contiki/wiki. + */ +#define DEBUG_MQTT 0 + +#if DEBUG_MQTT == 1 +#define DBG(...) printf(__VA_ARGS__) +#else +#define DBG(...) +#endif /* DEBUG */ +/*---------------------------------------------------------------------------*/ +extern process_event_t mqtt_update_event; + +/* Forward declaration */ +struct mqtt_connection; + +typedef enum { + MQTT_RETAIN_OFF, + MQTT_RETAIN_ON, +} mqtt_retain_t; + +/** + * \brief MQTT engine events + */ +typedef enum { + MQTT_EVENT_CONNECTED, + MQTT_EVENT_DISCONNECTED, + + MQTT_EVENT_SUBACK, + MQTT_EVENT_UNSUBACK, + MQTT_EVENT_PUBLISH, + MQTT_EVENT_PUBACK, + + /* Errors */ + MQTT_EVENT_ERROR = 0x80, + MQTT_EVENT_PROTOCOL_ERROR, + MQTT_EVENT_CONNECTION_REFUSED_ERROR, + MQTT_EVENT_DNS_ERROR, + MQTT_EVENT_NOT_IMPLEMENTED_ERROR, + /* Add more */ +} mqtt_event_t; + +typedef enum { + MQTT_STATUS_OK, + + MQTT_STATUS_OUT_QUEUE_FULL, + + /* Errors */ + MQTT_STATUS_ERROR = 0x80, + MQTT_STATUS_NOT_CONNECTED_ERROR, + MQTT_STATUS_INVALID_ARGS_ERROR, + MQTT_STATUS_DNS_ERROR, +} mqtt_status_t; + +typedef enum { + MQTT_QOS_LEVEL_0, + MQTT_QOS_LEVEL_1, + MQTT_QOS_LEVEL_2, +} mqtt_qos_level_t; + +typedef enum { + MQTT_QOS_STATE_NO_ACK, + MQTT_QOS_STATE_GOT_ACK, + + /* Expand for QoS 2 */ +} mqtt_qos_state_t; +/*---------------------------------------------------------------------------*/ +/* + * This is the state of the connection itself. + * + * N.B. The order is important because of runtime checks on how far the + * connection has proceeded. + */ +typedef enum { + MQTT_CONN_STATE_ERROR, + MQTT_CONN_STATE_DNS_ERROR, + MQTT_CONN_STATE_DISCONNECTING, + + MQTT_CONN_STATE_NOT_CONNECTED, + MQTT_CONN_STATE_DNS_LOOKUP, + MQTT_CONN_STATE_TCP_CONNECTING, + MQTT_CONN_STATE_TCP_CONNECTED, + MQTT_CONN_STATE_CONNECTING_TO_BROKER, + MQTT_CONN_STATE_CONNECTED_TO_BROKER, + MQTT_CONN_STATE_SENDING_MQTT_DISCONNECT, + MQTT_CONN_STATE_ABORT_IMMEDIATE, +} mqtt_conn_state_t; +/*---------------------------------------------------------------------------*/ +struct mqtt_string { + char *string; + uint16_t length; +}; + +/* + * Note that the pairing mid <-> QoS level only applies one-to-one if we only + * allow the subscription of one topic at a time. Otherwise we will have an + * ordered list of QoS levels corresponding to the order of topics. + * + * This could be part of a union of event data structures. + */ +struct mqtt_suback_event { + uint16_t mid; + mqtt_qos_level_t qos_level; +}; + +/* This is the MQTT message that is exposed to the end user. */ +struct mqtt_message { + uint32_t mid; + char topic[MQTT_MAX_TOPIC_LENGTH + 1]; /* +1 for string termination */ + + uint8_t *payload_chunk; + uint16_t payload_chunk_length; + + uint8_t first_chunk; + uint16_t payload_length; + uint16_t payload_left; +}; + +/* This struct represents a packet received from the MQTT server. */ +struct mqtt_in_packet { + /* Used by the list interface, must be first in the struct. */ + struct mqtt_connection *next; + + /* Total bytes read so far. Compared to the remaining length to to decide when + * we've read the payload. */ + uint32_t byte_counter; + uint8_t packet_received; + + uint8_t fhdr; + uint16_t remaining_length; + uint16_t mid; + + /* Helper variables needed to decode the remaining_length */ + uint8_t remaining_multiplier; + uint8_t has_remaining_length; + uint8_t remaining_length_bytes; + + /* Not the same as payload in the MQTT sense, it also contains the variable + * header. + */ + uint8_t payload_pos; + uint8_t payload[MQTT_INPUT_BUFF_SIZE]; + + /* Message specific data */ + uint16_t topic_len; + uint16_t topic_pos; + uint8_t topic_len_received; + uint8_t topic_received; +}; + +/* This struct represents a packet sent to the MQTT server. */ +struct mqtt_out_packet { + uint8_t fhdr; + uint32_t remaining_length; + uint8_t remaining_length_enc[MQTT_MAX_REMAINING_LENGTH_BYTES]; + uint8_t remaining_length_enc_bytes; + uint16_t mid; + char *topic; + uint16_t topic_length; + uint8_t *payload; + uint32_t payload_size; + mqtt_qos_level_t qos; + mqtt_qos_state_t qos_state; + mqtt_retain_t retain; +}; +/*---------------------------------------------------------------------------*/ +/** + * \brief MQTT event callback function + * \param m A pointer to a MQTT connection + * \param event The event number + * \param data A user-defined pointer + * + * The MQTT socket event callback function gets called whenever there is an + * event on a MQTT connection, such as the connection getting connected + * or closed. + */ +typedef void (*mqtt_event_callback_t)(struct mqtt_connection *m, + mqtt_event_t event, + void *data); + +typedef void (*mqtt_topic_callback_t)(struct mqtt_connection *m, + struct mqtt_message *msg); +/*---------------------------------------------------------------------------*/ +struct mqtt_will { + struct mqtt_string topic; + struct mqtt_string message; + mqtt_qos_level_t qos; +}; + +struct mqtt_credentials { + struct mqtt_string username; + struct mqtt_string password; +}; + +struct mqtt_connection { + /* Used by the list interface, must be first in the struct */ + struct mqtt_connection *next; + struct timer t; + + struct mqtt_string client_id; + + uint8_t connect_vhdr_flags; + uint8_t auto_reconnect; + + uint16_t keep_alive; + struct ctimer keep_alive_timer; + uint8_t waiting_for_pingresp; + + struct mqtt_will will; + struct mqtt_credentials credentials; + + mqtt_conn_state_t state; + mqtt_event_callback_t event_callback; + + /* Internal data */ + uint16_t mid_counter; + + /* Used for communication between MQTT API and APP */ + uint8_t out_queue_full; + struct process *app_process; + + /* Outgoing data related */ + uint8_t *out_buffer_ptr; + uint8_t out_buffer[MQTT_TCP_OUTPUT_BUFF_SIZE]; + uint8_t out_buffer_sent; + struct mqtt_out_packet out_packet; + struct pt out_proto_thread; + uint32_t out_write_pos; + uint16_t max_segment_size; + + /* Incoming data related */ + uint8_t in_buffer[MQTT_TCP_INPUT_BUFF_SIZE]; + struct mqtt_in_packet in_packet; + struct mqtt_message in_publish_msg; + + /* TCP related information */ + char *server_host; + uip_ipaddr_t server_ip; + uint16_t server_port; + struct tcp_socket socket; +}; +/* This is the API exposed to the user. */ +/*---------------------------------------------------------------------------*/ +/** + * \brief Initializes the MQTT engine. + * \param conn A pointer to the MQTT connection. + * \param app_process A pointer to the application process handling the MQTT + * connection. + * \param client_id A pointer to the MQTT client ID. + * \param event_callback Callback function responsible for handling the + * callback from MQTT engine. + * \param max_segment_size The TCP segment size to use for this MQTT/TCP + * connection. + * \return MQTT_STATUS_OK or MQTT_STATUS_INVALID_ARGS_ERROR + * + * This function initializes the MQTT engine and shall be called before any + * other MQTT function. + */ +mqtt_status_t mqtt_register(struct mqtt_connection *conn, + struct process *app_process, + char *client_id, + mqtt_event_callback_t event_callback, + uint16_t max_segment_size); +/*---------------------------------------------------------------------------*/ +/** + * \brief Connects to a MQTT broker. + * \param conn A pointer to the MQTT connection. + * \param host IP address of the broker to connect to. + * \param port Port of the broker to connect to, default is MQTT port is 1883. + * \param keep_alive Keep alive timer in seconds. Used by broker to handle + * client disc. Defines the maximum time interval between two messages + * from the client. Shall be min 1.5 x report interval. + * \return MQTT_STATUS_OK or an error status + * + * This function connects to a MQTT broker. + */ +mqtt_status_t mqtt_connect(struct mqtt_connection *conn, + char *host, + uint16_t port, + uint16_t keep_alive); +/*---------------------------------------------------------------------------*/ +/** + * \brief Disconnects from a MQTT broker. + * \param conn A pointer to the MQTT connection. + * + * This function disconnects from a MQTT broker. + */ +void mqtt_disconnect(struct mqtt_connection *conn); +/*---------------------------------------------------------------------------*/ +/** + * \brief Subscribes to a MQTT topic. + * \param conn A pointer to the MQTT connection. + * \param mid A pointer to message ID. + * \param topic A pointer to the topic to subscribe to. + * \param qos_level Quality Of Service level to use. Currently supports 0, 1. + * \return MQTT_STATUS_OK or some error status + * + * This function subscribes to a topic on a MQTT broker. + */ +mqtt_status_t mqtt_subscribe(struct mqtt_connection *conn, + uint16_t *mid, + char *topic, + mqtt_qos_level_t qos_level); +/*---------------------------------------------------------------------------*/ +/** + * \brief Unsubscribes from a MQTT topic. + * \param conn A pointer to the MQTT connection. + * \param mid A pointer to message ID. + * \param topic A pointer to the topic to unsubscribe from. + * \return MQTT_STATUS_OK or some error status + * + * This function unsubscribes from a topic on a MQTT broker. + */ +mqtt_status_t mqtt_unsubscribe(struct mqtt_connection *conn, + uint16_t *mid, + char *topic); +/*---------------------------------------------------------------------------*/ +/** + * \brief Publish to a MQTT topic. + * \param conn A pointer to the MQTT connection. + * \param mid A pointer to message ID. + * \param topic A pointer to the topic to subscribe to. + * \param payload A pointer to the topic payload. + * \param payload_size Payload size. + * \param qos_level Quality Of Service level to use. Currently supports 0, 1. + * \param retain If the RETAIN flag is set to 1, in a PUBLISH Packet sent by a + * Client to a Server, the Server MUST store the Application Message + * and its QoS, so that it can be delivered to future subscribers whose + * subscriptions match its topic name + * \return MQTT_STATUS_OK or some error status + * + * This function publishes to a topic on a MQTT broker. + */ +mqtt_status_t mqtt_publish(struct mqtt_connection *conn, + uint16_t *mid, + char *topic, + uint8_t *payload, + uint32_t payload_size, + mqtt_qos_level_t qos_level, + mqtt_retain_t retain); +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the user name and password for a MQTT client. + * \param conn A pointer to the MQTT connection. + * \param username A pointer to the user name. + * \param password A pointer to the password. + * + * This function sets clients user name and password to use when connecting to + * a MQTT broker. + */ +void mqtt_set_username_password(struct mqtt_connection *conn, + char *username, + char *password); +/*---------------------------------------------------------------------------*/ +/** + * \brief Set the last will topic and message for a MQTT client. + * \param conn A pointer to the MQTT connection. + * \param topic A pointer to the Last Will topic. + * \param message A pointer to the Last Will message (payload). + * \param qos The desired QoS level. + * + * This function sets clients Last Will topic and message (payload). + * If the Will Flag is set to 1 (using the function) this indicates that, + * if the Connect request is accepted, a Will Message MUST be stored on the + * Server and associated with the Network Connection. The Will Message MUST + * be published when the Network Connection is subsequently closed. + * + * This functionality can be used to get notified that a device has + * disconnected from the broker. + * + */ +void mqtt_set_last_will(struct mqtt_connection *conn, + char *topic, + char *message, + mqtt_qos_level_t qos); + +#define mqtt_connected(conn) \ + ((conn)->state == MQTT_CONN_STATE_CONNECTED_TO_BROKER ? 1 : 0) + +#define mqtt_ready(conn) \ + (!(conn)->out_queue_full && mqtt_connected((conn))) +/*---------------------------------------------------------------------------*/ +#endif /* MQTT_H_ */ +/*---------------------------------------------------------------------------*/ +/** + * @} + * @} + */ diff --git a/apps/shell/shell-download.c b/apps/shell/shell-download.c index 86ad20207..7c2d419e8 100644 --- a/apps/shell/shell-download.c +++ b/apps/shell/shell-download.c @@ -31,9 +31,11 @@ */ /** - * \file Shell command for downloading files from a remote node. + * \file + * + * Shell command for downloading files from a remote node. * Example usage: - * 'download | write \ | write \'. * * \author Luca Mottola , Fredrik Osterlind */ diff --git a/core/cfs/cfs-coffee.c b/core/cfs/cfs-coffee.c index f4e7a26c1..d7f55a7c2 100644 --- a/core/cfs/cfs-coffee.c +++ b/core/cfs/cfs-coffee.c @@ -35,12 +35,12 @@ * Coffee: A file system for a variety of storage types in * memory-constrained devices. * - * For further information, see "Enabling Large-Scale Storage in - * Sensor Networks with the Coffee File System" in the proceedings + * For further information, see "Enabling Large-Scale Storage in + * Sensor Networks with the Coffee File System" in the proceedings * of ACM/IEEE IPSN 2009. * * \author - * Nicolas Tsiftes + * Nicolas Tsiftes */ #include @@ -62,23 +62,23 @@ /* Micro logs enable modifications on storage types that do not support in-place updates. This applies primarily to flash memories. */ #ifndef COFFEE_MICRO_LOGS -#define COFFEE_MICRO_LOGS 1 +#define COFFEE_MICRO_LOGS 1 #endif -/* If the files are expected to be appended to only, this parameter +/* If the files are expected to be appended to only, this parameter can be set to save some code space. */ #ifndef COFFEE_APPEND_ONLY -#define COFFEE_APPEND_ONLY 0 +#define COFFEE_APPEND_ONLY 0 #endif #if COFFEE_MICRO_LOGS && COFFEE_APPEND_ONLY #error "Cannot have COFFEE_APPEND_ONLY set when COFFEE_MICRO_LOGS is set." #endif -/* I/O semantics can be set on file descriptors in order to optimize +/* I/O semantics can be set on file descriptors in order to optimize file access on certain storage types. */ #ifndef COFFEE_IO_SEMANTICS -#define COFFEE_IO_SEMANTICS 0 +#define COFFEE_IO_SEMANTICS 0 #endif /* @@ -87,72 +87,72 @@ * to longer garbage collection procedures. */ #ifndef COFFEE_EXTENDED_WEAR_LEVELLING -#define COFFEE_EXTENDED_WEAR_LEVELLING 1 +#define COFFEE_EXTENDED_WEAR_LEVELLING 1 #endif #if COFFEE_START & (COFFEE_SECTOR_SIZE - 1) #error COFFEE_START must point to the first byte in a sector. #endif -#define COFFEE_FD_FREE 0x0 -#define COFFEE_FD_READ 0x1 -#define COFFEE_FD_WRITE 0x2 -#define COFFEE_FD_APPEND 0x4 +#define COFFEE_FD_FREE 0x0 +#define COFFEE_FD_READ 0x1 +#define COFFEE_FD_WRITE 0x2 +#define COFFEE_FD_APPEND 0x4 -#define COFFEE_FILE_MODIFIED 0x1 +#define COFFEE_FILE_MODIFIED 0x1 -#define INVALID_PAGE ((coffee_page_t)-1) -#define UNKNOWN_OFFSET ((cfs_offset_t)-1) +#define INVALID_PAGE ((coffee_page_t)-1) +#define UNKNOWN_OFFSET ((cfs_offset_t)-1) -#define REMOVE_LOG 1 -#define CLOSE_FDS 1 -#define ALLOW_GC 1 +#define REMOVE_LOG 1 +#define CLOSE_FDS 1 +#define ALLOW_GC 1 /* "Greedy" garbage collection erases as many sectors as possible. */ -#define GC_GREEDY 0 +#define GC_GREEDY 0 /* "Reluctant" garbage collection stops after erasing one sector. */ -#define GC_RELUCTANT 1 +#define GC_RELUCTANT 1 /* File descriptor macros. */ -#define FD_VALID(fd) \ - ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ - coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) -#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ) -#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE) -#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND) +#define FD_VALID(fd) \ + ((fd) >= 0 && (fd) < COFFEE_FD_SET_SIZE && \ + coffee_fd_set[(fd)].flags != COFFEE_FD_FREE) +#define FD_READABLE(fd) (coffee_fd_set[(fd)].flags & CFS_READ) +#define FD_WRITABLE(fd) (coffee_fd_set[(fd)].flags & CFS_WRITE) +#define FD_APPENDABLE(fd) (coffee_fd_set[(fd)].flags & CFS_APPEND) /* File object macros. */ -#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) -#define FILE_FREE(file) ((file)->max_pages == 0) -#define FILE_UNREFERENCED(file) ((file)->references == 0) +#define FILE_MODIFIED(file) ((file)->flags & COFFEE_FILE_MODIFIED) +#define FILE_FREE(file) ((file)->max_pages == 0) +#define FILE_UNREFERENCED(file) ((file)->references == 0) /* File header flags. */ -#define HDR_FLAG_VALID 0x1 /* Completely written header. */ -#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */ -#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */ -#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */ -#define HDR_FLAG_LOG 0x10 /* Log file. */ -#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ +#define HDR_FLAG_VALID 0x1 /* Completely written header. */ +#define HDR_FLAG_ALLOCATED 0x2 /* Allocated file. */ +#define HDR_FLAG_OBSOLETE 0x4 /* File marked for GC. */ +#define HDR_FLAG_MODIFIED 0x8 /* Modified file, log exists. */ +#define HDR_FLAG_LOG 0x10 /* Log file. */ +#define HDR_FLAG_ISOLATED 0x20 /* Isolated page. */ /* File header macros. */ -#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag)) -#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) -#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) -#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) -#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) -#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) -#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) -#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) -#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ - !HDR_OBSOLETE(hdr) && \ - !HDR_ISOLATED(hdr)) +#define CHECK_FLAG(hdr, flag) ((hdr).flags & (flag)) +#define HDR_VALID(hdr) CHECK_FLAG(hdr, HDR_FLAG_VALID) +#define HDR_ALLOCATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ALLOCATED) +#define HDR_FREE(hdr) !HDR_ALLOCATED(hdr) +#define HDR_LOG(hdr) CHECK_FLAG(hdr, HDR_FLAG_LOG) +#define HDR_MODIFIED(hdr) CHECK_FLAG(hdr, HDR_FLAG_MODIFIED) +#define HDR_ISOLATED(hdr) CHECK_FLAG(hdr, HDR_FLAG_ISOLATED) +#define HDR_OBSOLETE(hdr) CHECK_FLAG(hdr, HDR_FLAG_OBSOLETE) +#define HDR_ACTIVE(hdr) (HDR_ALLOCATED(hdr) && \ + !HDR_OBSOLETE(hdr) && \ + !HDR_ISOLATED(hdr)) /* Shortcuts derived from the hardware-dependent configuration of Coffee. */ -#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) -#define COFFEE_PAGE_COUNT \ - ((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE)) -#define COFFEE_PAGES_PER_SECTOR \ - ((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE)) +#define COFFEE_SECTOR_COUNT (unsigned)(COFFEE_SIZE / COFFEE_SECTOR_SIZE) +#define COFFEE_PAGE_COUNT \ + ((coffee_page_t)(COFFEE_SIZE / COFFEE_PAGE_SIZE)) +#define COFFEE_PAGES_PER_SECTOR \ + ((coffee_page_t)(COFFEE_SECTOR_SIZE / COFFEE_PAGE_SIZE)) /* This structure is used for garbage collection statistics. */ struct sector_status { @@ -181,7 +181,7 @@ struct file_desc { #endif }; -/* The file header structure mimics the representation of file headers +/* The file header structure mimics the representation of file headers in the physical storage medium. */ struct file_header { coffee_page_t log_page; @@ -201,9 +201,9 @@ struct log_param { }; /* - * The protected memory consists of structures that should not be - * overwritten during system checkpointing because they may be used by - * the checkpointing implementation. These structures need not be + * The protected memory consists of structures that should not be + * overwritten during system checkpointing because they may be used by + * the checkpointing implementation. These structures need not be * protected if checkpointing is not used. */ static struct protected_mem_t { @@ -212,10 +212,10 @@ static struct protected_mem_t { coffee_page_t next_free; char gc_wait; } protected_mem; -static struct file * const coffee_files = protected_mem.coffee_files; -static struct file_desc * const coffee_fd_set = protected_mem.coffee_fd_set; -static coffee_page_t * const next_free = &protected_mem.next_free; -static char * const gc_wait = &protected_mem.gc_wait; +static struct file *const coffee_files = protected_mem.coffee_files; +static struct file_desc *const coffee_fd_set = protected_mem.coffee_fd_set; +static coffee_page_t *const next_free = &protected_mem.next_free; +static char *const gc_wait = &protected_mem.gc_wait; /*---------------------------------------------------------------------------*/ static void @@ -256,8 +256,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats) active = obsolete = free = 0; /* - * get_sector_status() is an iterative function using local static - * state. It therefore requires that the caller starts iterating from + * get_sector_status() is an iterative function using local static + * state. It therefore requires that the caller starts iterating from * sector 0 in order to reset the internal state. */ if(sector == 0) { @@ -269,8 +269,8 @@ get_sector_status(uint16_t sector, struct sector_status *stats) sector_end = sector_start + COFFEE_PAGES_PER_SECTOR; /* - * Account for pages belonging to a file starting in a previous - * segment that extends into this segment. If the whole segment is + * Account for pages belonging to a file starting in a previous + * segment that extends into this segment. If the whole segment is * covered, we do not need to continue counting pages in this iteration. */ if(last_pages_are_active) { @@ -289,7 +289,7 @@ get_sector_status(uint16_t sector, struct sector_status *stats) obsolete = skip_pages; } - /* Determine the amount of pages of each type that have not been + /* Determine the amount of pages of each type that have not been accounted for yet in the current sector. */ for(page = sector_start + skip_pages; page < sector_end;) { read_header(&hdr, page); @@ -312,10 +312,10 @@ get_sector_status(uint16_t sector, struct sector_status *stats) /* * Determine the amount of pages in the following sectors that - * should be remembered for the next iteration. This is necessary - * because no page except the first of a file contains information + * should be remembered for the next iteration. This is necessary + * because no page except the first of a file contains information * about what type of page it is. A side effect of remembering this - * amount is that there is no need to read in the headers of each + * amount is that there is no need to read in the headers of each * of these pages from the storage. */ skip_pages = active + obsolete + free - COFFEE_PAGES_PER_SECTOR; @@ -332,14 +332,14 @@ get_sector_status(uint16_t sector, struct sector_status *stats) stats->free = free; /* - * To avoid unnecessary page isolation, we notify the caller that - * "skip_pages" pages should be isolated only if the current file extent - * ends in the next sector. If the file extent ends in a more distant - * sector, however, the garbage collection can free the next sector - * immediately without requiring page isolation. + * To avoid unnecessary page isolation, we notify the caller that + * "skip_pages" pages should be isolated only if the current file extent + * ends in the next sector. If the file extent ends in a more distant + * sector, however, the garbage collection can free the next sector + * immediately without requiring page isolation. */ return (last_pages_are_active || (skip_pages >= COFFEE_PAGES_PER_SECTOR)) ? - 0 : skip_pages; + 0 : skip_pages; } /*---------------------------------------------------------------------------*/ static void @@ -359,7 +359,6 @@ isolate_pages(coffee_page_t start, coffee_page_t skip_pages) } PRINTF("Coffee: Isolated %u pages starting in sector %d\n", (unsigned)skip_pages, (int)start / COFFEE_PAGES_PER_SECTOR); - } /*---------------------------------------------------------------------------*/ static void @@ -370,7 +369,7 @@ collect_garbage(int mode) coffee_page_t first_page, isolation_count; PRINTF("Coffee: Running the file system garbage collector in %s mode\n", - mode == GC_RELUCTANT ? "reluctant" : "greedy"); + mode == GC_RELUCTANT ? "reluctant" : "greedy"); /* * The garbage collector erases as many sectors as possible. A sector is * erasable if there are only free or obsolete pages in it. @@ -378,8 +377,8 @@ collect_garbage(int mode) for(sector = 0; sector < COFFEE_SECTOR_COUNT; sector++) { isolation_count = get_sector_status(sector, &stats); PRINTF("Coffee: Sector %u has %u active, %u obsolete, and %u free pages.\n", - sector, (unsigned)stats.active, - (unsigned)stats.obsolete, (unsigned)stats.free); + sector, (unsigned)stats.active, + (unsigned)stats.obsolete, (unsigned)stats.free); if(stats.active > 0) { continue; @@ -410,13 +409,13 @@ static coffee_page_t next_file(coffee_page_t page, struct file_header *hdr) { /* - * The quick-skip algorithm for finding file extents is the most - * essential part of Coffee. The file allocation rules enables this - * algorithm to quickly jump over free areas and allocated extents + * The quick-skip algorithm for finding file extents is the most + * essential part of Coffee. The file allocation rules enables this + * algorithm to quickly jump over free areas and allocated extents * after reading single headers and determining their status. * - * The worst-case performance occurs when we encounter multiple long - * sequences of isolated pages, but such sequences are uncommon and + * The worst-case performance occurs when we encounter multiple long + * sequences of isolated pages, but such sequences are uncommon and * always shorter than a sector. */ if(HDR_FREE(*hdr)) { @@ -424,7 +423,7 @@ next_file(coffee_page_t page, struct file_header *hdr) } else if(HDR_ISOLATED(*hdr)) { return page + 1; } - return page + hdr->max_pages; + return page + hdr->max_pages; } /*---------------------------------------------------------------------------*/ static struct file * @@ -475,7 +474,7 @@ find_file(const char *name) int i; struct file_header hdr; coffee_page_t page; - + /* First check if the file metadata is cached. */ for(i = 0; i < COFFEE_MAX_OPEN_FILES; i++) { if(FILE_FREE(&coffee_files[i])) { @@ -487,7 +486,7 @@ find_file(const char *name) return &coffee_files[i]; } } - + /* Scan the flash memory sequentially otherwise. */ for(page = 0; page < COFFEE_PAGE_COUNT; page = next_file(page, &hdr)) { read_header(&hdr, page); @@ -521,10 +520,10 @@ file_end(coffee_page_t start) COFFEE_READ(buf, sizeof(buf), (start + page) * COFFEE_PAGE_SIZE); for(i = COFFEE_PAGE_SIZE - 1; i >= 0; i--) { if(buf[i] != 0) { - if(page == 0 && i < sizeof(hdr)) { - return 0; - } - return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr); + if(page == 0 && i < sizeof(hdr)) { + return 0; + } + return 1 + i + (page * COFFEE_PAGE_SIZE) - sizeof(hdr); } } } @@ -544,7 +543,7 @@ find_contiguous_pages(coffee_page_t amount) read_header(&hdr, page); if(HDR_FREE(hdr)) { if(start == INVALID_PAGE) { - start = page; + start = page; if(start + amount >= COFFEE_PAGE_COUNT) { /* We can stop immediately if the remaining pages are not enough. */ break; @@ -557,9 +556,9 @@ find_contiguous_pages(coffee_page_t amount) if(start + amount <= page) { if(start == *next_free) { - *next_free = start + amount; - } - return start; + *next_free = start + amount; + } + return start; } } else { start = INVALID_PAGE; @@ -596,7 +595,7 @@ remove_by_page(coffee_page_t page, int remove_log, int close_fds, if(close_fds) { for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { if(coffee_fd_set[i].file != NULL && coffee_fd_set[i].file->page == page) { - coffee_fd_set[i].flags = COFFEE_FD_FREE; + coffee_fd_set[i].flags = COFFEE_FD_FREE; } } } @@ -622,12 +621,12 @@ static coffee_page_t page_count(cfs_offset_t size) { return (size + sizeof(struct file_header) + COFFEE_PAGE_SIZE - 1) / - COFFEE_PAGE_SIZE; + COFFEE_PAGE_SIZE; } /*---------------------------------------------------------------------------*/ static struct file * reserve(const char *name, coffee_page_t pages, - int allow_duplicates, unsigned flags) + int allow_duplicates, unsigned flags) { struct file_header hdr; coffee_page_t page; @@ -657,7 +656,7 @@ reserve(const char *name, coffee_page_t pages, write_header(&hdr, page); PRINTF("Coffee: Reserved %u pages starting from %u for file %s\n", - pages, page, name); + pages, page, name); file = load_file(page, &hdr); if(file != NULL) { @@ -670,19 +669,19 @@ reserve(const char *name, coffee_page_t pages, #if COFFEE_MICRO_LOGS static void adjust_log_config(struct file_header *hdr, - uint16_t *log_record_size, uint16_t *log_records) + uint16_t *log_record_size, uint16_t *log_records) { *log_record_size = hdr->log_record_size == 0 ? - COFFEE_PAGE_SIZE : hdr->log_record_size; + COFFEE_PAGE_SIZE : hdr->log_record_size; *log_records = hdr->log_records == 0 ? - COFFEE_LOG_SIZE / *log_record_size : hdr->log_records; + COFFEE_LOG_SIZE / *log_record_size : hdr->log_records; } #endif /* COFFEE_MICRO_LOGS */ /*---------------------------------------------------------------------------*/ #if COFFEE_MICRO_LOGS static uint16_t modify_log_buffer(uint16_t log_record_size, - cfs_offset_t *offset, uint16_t *size) + cfs_offset_t *offset, uint16_t *size) { uint16_t region; @@ -700,7 +699,7 @@ modify_log_buffer(uint16_t log_record_size, #if COFFEE_MICRO_LOGS static int get_record_index(coffee_page_t log_page, uint16_t search_records, - uint16_t region) + uint16_t region) { cfs_offset_t base; uint16_t processed; @@ -709,30 +708,30 @@ get_record_index(coffee_page_t log_page, uint16_t search_records, base = absolute_offset(log_page, sizeof(uint16_t) * search_records); batch_size = search_records > COFFEE_LOG_TABLE_LIMIT ? - COFFEE_LOG_TABLE_LIMIT : search_records; + COFFEE_LOG_TABLE_LIMIT : search_records; processed = 0; match_index = -1; { - uint16_t indices[batch_size]; + uint16_t indices[batch_size]; - while(processed < search_records && match_index < 0) { - if(batch_size + processed > search_records) { - batch_size = search_records - processed; - } - - base -= batch_size * sizeof(indices[0]); - COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base); - - for(i = batch_size - 1; i >= 0; i--) { - if(indices[i] - 1 == region) { - match_index = search_records - processed - (batch_size - i); - break; + while(processed < search_records && match_index < 0) { + if(batch_size + processed > search_records) { + batch_size = search_records - processed; } - } - processed += batch_size; - } + base -= batch_size * sizeof(indices[0]); + COFFEE_READ(&indices, sizeof(indices[0]) * batch_size, base); + + for(i = batch_size - 1; i >= 0; i--) { + if(indices[i] - 1 == region) { + match_index = search_records - processed - (batch_size - i); + break; + } + } + + processed += batch_size; + } } return match_index; @@ -839,7 +838,7 @@ merge_log(coffee_page_t file_page, int extend) } while(n != 0); for(i = 0; i < COFFEE_FD_SET_SIZE; i++) { - if(coffee_fd_set[i].flags != COFFEE_FD_FREE && + if(coffee_fd_set[i].flags != COFFEE_FD_FREE && coffee_fd_set[i].file->page == file_page) { coffee_fd_set[i].file = new_file; new_file->references++; @@ -869,7 +868,7 @@ merge_log(coffee_page_t file_page, int extend) #if COFFEE_MICRO_LOGS static int find_next_record(struct file *file, coffee_page_t log_page, - int log_records) + int log_records) { int log_record, preferred_batch_size; @@ -878,7 +877,7 @@ find_next_record(struct file *file, coffee_page_t log_page, } preferred_batch_size = log_records > COFFEE_LOG_TABLE_LIMIT ? - COFFEE_LOG_TABLE_LIMIT : log_records; + COFFEE_LOG_TABLE_LIMIT : log_records; { /* The next log record is unknown at this point; search for it. */ uint16_t indices[preferred_batch_size]; @@ -888,15 +887,15 @@ find_next_record(struct file *file, coffee_page_t log_page, log_record = log_records; for(processed = 0; processed < log_records; processed += batch_size) { batch_size = log_records - processed >= preferred_batch_size ? - preferred_batch_size : log_records - processed; + preferred_batch_size : log_records - processed; COFFEE_READ(&indices, batch_size * sizeof(indices[0]), - absolute_offset(log_page, processed * sizeof(indices[0]))); + absolute_offset(log_page, processed * sizeof(indices[0]))); for(log_record = 0; log_record < batch_size; log_record++) { - if(indices[log_record] == 0) { - log_record += processed; - break; - } + if(indices[log_record] == 0) { + log_record += processed; + break; + } } } } @@ -940,7 +939,7 @@ write_log_page(struct file *file, struct log_param *lp) return -1; } PRINTF("Coffee: Created a log structure for file %s at page %u\n", - hdr.name, (unsigned)log_page); + hdr.name, (unsigned)log_page); hdr.log_page = log_page; log_record = 0; } @@ -953,9 +952,9 @@ write_log_page(struct file *file, struct log_param *lp) lp_out.size = log_record_size; if((lp->offset > 0 || lp->size != log_record_size) && - read_log_page(&hdr, log_record, &lp_out) < 0) { + read_log_page(&hdr, log_record, &lp_out) < 0) { COFFEE_READ(copy_buf, sizeof(copy_buf), - absolute_offset(file->page, offset)); + absolute_offset(file->page, offset)); } memcpy(©_buf[lp->offset], lp->buf, lp->size); @@ -967,11 +966,11 @@ write_log_page(struct file *file, struct log_param *lp) offset = absolute_offset(log_page, 0); ++region; COFFEE_WRITE(®ion, sizeof(region), - offset + log_record * sizeof(region)); + offset + log_record * sizeof(region)); offset += log_records * sizeof(region); COFFEE_WRITE(copy_buf, sizeof(copy_buf), - offset + log_record * log_record_size); + offset + log_record * log_record_size); file->record_count = log_record + 1; } @@ -1171,7 +1170,7 @@ cfs_write(int fd, const void *buf, unsigned size) if(!(fdp->io_flags & CFS_COFFEE_IO_FIRM_SIZE)) { #endif while(size + fdp->offset + sizeof(struct file_header) > - (file->max_pages * COFFEE_PAGE_SIZE)) { + (file->max_pages * COFFEE_PAGE_SIZE)) { if(merge_log(file->page, 1) < 0) { return -1; } @@ -1179,7 +1178,7 @@ cfs_write(int fd, const void *buf, unsigned size) PRINTF("Extended the file at page %u\n", (unsigned)file->page); } #if COFFEE_IO_SEMANTICS - } +} #endif #if COFFEE_MICRO_LOGS @@ -1196,19 +1195,19 @@ cfs_write(int fd, const void *buf, unsigned size) lp.size = bytes_left; i = write_log_page(file, &lp); if(i < 0) { - /* Return -1 if we wrote nothing because the log write failed. */ - if(size == bytes_left) { - return -1; - } - break; + /* Return -1 if we wrote nothing because the log write failed. */ + if(size == bytes_left) { + return -1; + } + break; } else if(i == 0) { /* The file was merged with the log. */ - file = fdp->file; + file = fdp->file; } else { - /* A log record was written. */ - bytes_left -= i; - fdp->offset += i; - buf = (char *)buf + i; + /* A log record was written. */ + bytes_left -= i; + fdp->offset += i; + buf = (char *)buf + i; /* Update the file end for a potential log merge that might occur while writing log records. */ @@ -1231,15 +1230,15 @@ cfs_write(int fd, const void *buf, unsigned size) } else { #endif /* COFFEE_MICRO_LOGS */ #if COFFEE_APPEND_ONLY - if(fdp->offset < file->end) { - return -1; - } + if(fdp->offset < file->end) { + return -1; + } #endif /* COFFEE_APPEND_ONLY */ - COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); - fdp->offset += size; + COFFEE_WRITE(buf, size, absolute_offset(file->page, fdp->offset)); + fdp->offset += size; #if COFFEE_MICRO_LOGS - } +} #endif /* COFFEE_MICRO_LOGS */ if(fdp->offset > file->end) { @@ -1253,7 +1252,7 @@ int cfs_opendir(struct cfs_dir *dir, const char *name) { /* - * Coffee is only guaranteed to support "/" and ".", but it does not + * Coffee is only guaranteed to support "/" and ".", but it does not * currently enforce this. */ memset(dir->dummy_space, 0, sizeof(coffee_page_t)); @@ -1300,7 +1299,7 @@ cfs_coffee_reserve(const char *name, cfs_offset_t size) /*---------------------------------------------------------------------------*/ int cfs_coffee_configure_log(const char *filename, unsigned log_size, - unsigned log_record_size) + unsigned log_record_size) { struct file *file; struct file_header hdr; diff --git a/core/ctk/ctk-draw.h b/core/ctk/ctk-draw.h index 388596cea..2f5cb8816 100644 --- a/core/ctk/ctk-draw.h +++ b/core/ctk/ctk-draw.h @@ -201,6 +201,7 @@ void ctk_draw_clear_window(struct ctk_window *window, * drawn, in screen coordinates (line 1 is the first line below the * menus) * + * \param draw_borders The border style */ void ctk_draw_window(struct ctk_window *window, unsigned char focus, @@ -318,7 +319,7 @@ extern unsigned char ctk_draw_windowborder_width, /** * The character used for the Return/Enter key. * - * \define #define CH_ENTER '\n' + * \#define CH_ENTER '\n' */ /** diff --git a/core/lib/crc16.h b/core/lib/crc16.h index 03aa94ea7..e243f546e 100644 --- a/core/lib/crc16.h +++ b/core/lib/crc16.h @@ -77,7 +77,7 @@ unsigned short crc16_add(unsigned char b, unsigned short crc); * \brief Calculate the CRC16 over a data area * \param data Pointer to the data * \param datalen The length of the data - * \param crc The accumulated CRC that is to be updated (or zero). + * \param acc The accumulated CRC that is to be updated (or zero). * \return The CRC16 checksum. * * This function calculates the CRC16 checksum of a data area. diff --git a/core/net/ip/simple-udp.h b/core/net/ip/simple-udp.h index ad4ac53ac..c28ce3e2c 100644 --- a/core/net/ip/simple-udp.h +++ b/core/net/ip/simple-udp.h @@ -142,7 +142,7 @@ int simple_udp_sendto(struct simple_udp_connection *c, * \param data A pointer to the data to be sent * \param datalen The length of the data * \param to The IP address of the receiver - * \param port The UDP port of the receiver, in host byte order + * \param to_port The UDP port of the receiver, in host byte order * * This function sends a UDP packet to a specified IP * address and UDP port. The packet will be sent with the diff --git a/core/net/ip/uip.h b/core/net/ip/uip.h index cfd095de2..78ebfef59 100644 --- a/core/net/ip/uip.h +++ b/core/net/ip/uip.h @@ -350,7 +350,7 @@ void uip_setipid(uint16_t id); * Periodic processing for a connection identified by its number. * * This function does the necessary periodic processing (timers, - * polling) for a uIP TCP conneciton, and should be called when the + * polling) for a uIP TCP connection, and should be called when the * periodic uIP timer goes off. It should be called for every * connection, regardless of whether they are open of closed. * @@ -393,8 +393,10 @@ void uip_setipid(uint16_t id); uip_process(UIP_TIMER); } while (0) /** + * Macro to determine whether a specific uIP connection is active * - * + * \param conn The connection's number + * \retval 0 Connection closed */ #define uip_conn_active(conn) (uip_conns[conn].tcpstateflags != UIP_CLOSED) @@ -489,7 +491,7 @@ void uip_reass_over(void); /** * The uIP packet buffer. * - * The uip_buf array is used to hold incoming and outgoing + * The uip_aligned_buf array is used to hold incoming and outgoing * packets. The device driver should place incoming data into this * buffer. When sending data, the device driver should read the link * level headers and the TCP/IP headers from this buffer. The size of @@ -519,6 +521,8 @@ typedef union { } uip_buf_t; CCIF extern uip_buf_t uip_aligned_buf; + +/** Macro to access uip_aligned_buf as an array of bytes */ #define uip_buf (uip_aligned_buf.u8) @@ -1097,7 +1101,7 @@ struct uip_udp_conn *uip_udp_new(const uip_ipaddr_t *ripaddr, uint16_t rport); -/** +/* * Check if an address is a broadcast address for a network. * * Checks if an address is the broadcast address for a network. The @@ -2172,7 +2176,7 @@ CCIF extern uip_lladdr_t uip_lladdr; * * See RFC1071. * - * \param buf A pointer to the buffer over which the checksum is to be + * \param data A pointer to the buffer over which the checksum is to be * computed. * * \param len The length of the buffer over which the checksum is to @@ -2180,7 +2184,7 @@ CCIF extern uip_lladdr_t uip_lladdr; * * \return The Internet checksum of the buffer. */ -uint16_t uip_chksum(uint16_t *buf, uint16_t len); +uint16_t uip_chksum(uint16_t *data, uint16_t len); /** * Calculate the IP header checksum of the packet header in uip_buf. diff --git a/core/net/ip/uip_arch.h b/core/net/ip/uip_arch.h index a27548519..352a39711 100644 --- a/core/net/ip/uip_arch.h +++ b/core/net/ip/uip_arch.h @@ -93,7 +93,7 @@ void uip_add32(uint8_t *op32, uint16_t op16); * \note This function is not called in the current version of uIP, * but future versions might make use of it. * - * \param buf A pointer to the buffer over which the checksum is to be + * \param data A pointer to the buffer over which the checksum is to be * computed. * * \param len The length of the buffer over which the checksum is to @@ -101,7 +101,7 @@ void uip_add32(uint8_t *op32, uint16_t op16); * * \return The Internet checksum of the buffer. */ -uint16_t uip_chksum(uint16_t *buf, uint16_t len); +uint16_t uip_chksum(uint16_t *data, uint16_t len); /** * Calculate the IP header checksum of the packet header in uip_buf. diff --git a/core/net/ipv4/uip.c b/core/net/ipv4/uip.c index f1bb7257a..174b0a3fa 100644 --- a/core/net/ipv4/uip.c +++ b/core/net/ipv4/uip.c @@ -699,7 +699,7 @@ uip_process(uint8_t flag) } goto drop; - /* Check if we were invoked because of the perodic timer fireing. */ + /* Check if we were invoked because of the periodic timer firing. */ } else if(flag == UIP_TIMER) { #if UIP_REASSEMBLY if(uip_reasstmr != 0) { @@ -851,7 +851,7 @@ uip_process(uint8_t flag) that the packet has been corrupted in transit. If the size of uip_len is larger than the size reported in the IP packet header, the packet has been padded and we set uip_len to the correct - value.. */ + value. */ if((BUF->len[0] << 8) + BUF->len[1] <= uip_len) { uip_len = (BUF->len[0] << 8) + BUF->len[1]; @@ -891,7 +891,7 @@ uip_process(uint8_t flag) if(uip_ipaddr_cmp(&uip_hostaddr, &uip_all_zeroes_addr)) { /* If we are configured to use ping IP address configuration and - hasn't been assigned an IP address yet, we accept all ICMP + haven't been assigned an IP address yet, we accept all ICMP packets. */ #if UIP_PINGADDRCONF && !NETSTACK_CONF_WITH_IPV6 if(BUF->proto == UIP_PROTO_ICMP) { @@ -1252,7 +1252,7 @@ uip_process(uint8_t flag) } } - /* If we didn't find and active connection that expected the packet, + /* If we didn't find an active connection that expected the packet, either this packet is an old duplicate, or this is a SYN packet destined for a connection in LISTEN. If the SYN flag isn't set, it is an old packet and we send a RST. */ @@ -1441,7 +1441,7 @@ uip_process(uint8_t flag) uip_flags = 0; /* We do a very naive form of TCP reset processing; we just accept any RST and kill our connection. We should in fact check if the - sequence number of this reset is wihtin our advertised window + sequence number of this reset is within our advertised window before we accept the reset. */ if(BUF->flags & TCP_RST) { uip_connr->tcpstateflags = UIP_CLOSED; diff --git a/core/net/ipv6/multicast/roll-tm.c b/core/net/ipv6/multicast/roll-tm.c index cfb4e66d5..20a562084 100644 --- a/core/net/ipv6/multicast/roll-tm.c +++ b/core/net/ipv6/multicast/roll-tm.c @@ -29,20 +29,15 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup roll-tm + * @{ + */ /** * \file - * This file implements IPv6 MCAST forwarding according to the - * algorithm described in the "MCAST Forwarding Using Trickle" - * internet draft. - * - * The current version of the draft can always be found in - * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast - * - * This implementation is based on the draft version stored in - * ROLL_TM_VER - * + * Implementation of the ROLL TM multicast engine * \author - * George Oikonomou - + * George Oikonomou - */ #include "contiki.h" @@ -1440,6 +1435,9 @@ init() return; } /*---------------------------------------------------------------------------*/ +/** + * \brief The ROLL TM engine driver + */ const struct uip_mcast6_driver roll_tm_driver = { "ROLL TM", init, @@ -1447,3 +1445,4 @@ const struct uip_mcast6_driver roll_tm_driver = { in, }; /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/roll-tm.h b/core/net/ipv6/multicast/roll-tm.h index 97dabb552..3ab22cc20 100644 --- a/core/net/ipv6/multicast/roll-tm.h +++ b/core/net/ipv6/multicast/roll-tm.h @@ -29,25 +29,34 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup uip6-multicast + * @{ + */ +/** + * \defgroup roll-tm ROLL Trickle Multicast + * + * IPv6 multicast according to the algorithm in the + * "MCAST Forwarding Using Trickle" internet draft. + * + * The current version of the draft can always be found in + * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast + * + * This implementation is based on the draft version stored in + * ROLL_TM_VER. + * + * In draft v2, the document was renamed to + * "Multicast Protocol for Low power and Lossy Networks (MPL)" + * Due to very significant changes between draft versions 1 and 2, + * MPL will be implemented as a separate engine and this file here + * will provide legacy support for Draft v1. + * @{ + */ /** * \file - * Header file for IPv6 multicast according to the algorithm in the - * "MCAST Forwarding Using Trickle" internet draft. - * - * The current version of the draft can always be found in - * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast - * - * This implementation is based on the draft version stored in - * ROLL_TM_VER. - * - * In draft v2, the document was renamed to - * "Multicast Protocol for Low power and Lossy Networks (MPL)" - * Due to very significant changes between draft versions 1 and 2, - * MPL will be implemented as a separate engine and this file here - * will provide legacy support for Draft v1. - * + * Header file for the implementation of the ROLL-TM multicast engine * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef ROLL_TM_H_ @@ -60,9 +69,9 @@ /*---------------------------------------------------------------------------*/ /* Protocol Constants */ /*---------------------------------------------------------------------------*/ -#define ROLL_TM_VER 1 /* Supported Draft Version */ -#define ROLL_TM_ICMP_CODE 0 /* ICMPv6 code field */ -#define ROLL_TM_IP_HOP_LIMIT 0xFF /* Hop limit for ICMP messages */ +#define ROLL_TM_VER 1 /**< Supported Draft Version */ +#define ROLL_TM_ICMP_CODE 0 /**< ROLL TM ICMPv6 code field */ +#define ROLL_TM_IP_HOP_LIMIT 0xFF /**< Hop limit for ICMP messages */ #define ROLL_TM_INFINITE_REDUNDANCY 0xFF #define ROLL_TM_DGRAM_OUT 0 #define ROLL_TM_DGRAM_IN 1 @@ -153,7 +162,7 @@ /*---------------------------------------------------------------------------*/ /* Configuration */ /*---------------------------------------------------------------------------*/ -/* +/** * Number of Sliding Windows * In essence: How many unique sources of simultaneous multicast traffic do we * want to support for our lowpan @@ -166,7 +175,7 @@ #define ROLL_TM_WINS 2 #endif /*---------------------------------------------------------------------------*/ -/* +/** * Maximum Number of Buffered Multicast Messages * This buffer is shared across all Seed IDs, therefore a new very active Seed * may eventually occupy all slots. It would make little sense (if any) to @@ -178,7 +187,7 @@ #define ROLL_TM_BUFF_NUM 6 #endif /*---------------------------------------------------------------------------*/ -/* +/** * Use Short Seed IDs [short: 2, long: 16 (default)] * It can be argued that we should (and it would be easy to) support both at * the same time but the draft doesn't list this as a MUST so we opt for @@ -190,7 +199,7 @@ #define ROLL_TM_SHORT_SEEDS 0 #endif /*---------------------------------------------------------------------------*/ -/* +/** * Destination address for our ICMPv6 advertisements. The draft gives us a * choice between LL all-nodes or LL all-routers * @@ -202,7 +211,7 @@ #define ROLL_TM_DEST_ALL_NODES 0 #endif /*---------------------------------------------------------------------------*/ -/* +/** * M param for our outgoing messages * By default, we set the M bit (conservative). Define this as 0 to clear the * M bit in our outgoing messages (aggressive) @@ -215,10 +224,21 @@ /*---------------------------------------------------------------------------*/ /* Stats datatype */ /*---------------------------------------------------------------------------*/ +/** + * \brief Multicast stats extension for the ROLL TM engine + */ struct roll_tm_stats { + /** Number of received ICMP datagrams */ UIP_MCAST6_STATS_DATATYPE icmp_in; + + /** Number of ICMP datagrams sent */ UIP_MCAST6_STATS_DATATYPE icmp_out; + + /** Number of malformed ICMP datagrams seen by us */ UIP_MCAST6_STATS_DATATYPE icmp_bad; }; - +/*---------------------------------------------------------------------------*/ #endif /* ROLL_TM_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/core/net/ipv6/multicast/smrf.c b/core/net/ipv6/multicast/smrf.c index 9e49fdc40..b1dccbd19 100644 --- a/core/net/ipv6/multicast/smrf.c +++ b/core/net/ipv6/multicast/smrf.c @@ -29,14 +29,16 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup smrf-multicast + * @{ + */ /** * \file - * This file implements 'Stateless Multicast RPL Forwarding' (SMRF) - * - * It will only work in RPL networks in MOP 3 "Storing with Multicast" + * This file implements 'Stateless Multicast RPL Forwarding' (SMRF) * * \author - * George Oikonomou - + * George Oikonomou - */ #include "contiki.h" @@ -199,6 +201,9 @@ out() return; } /*---------------------------------------------------------------------------*/ +/** + * \brief The SMRF engine driver + */ const struct uip_mcast6_driver smrf_driver = { "SMRF", init, @@ -206,3 +211,4 @@ const struct uip_mcast6_driver smrf_driver = { in, }; /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/smrf.h b/core/net/ipv6/multicast/smrf.h index d19fd6de8..51dcf216e 100644 --- a/core/net/ipv6/multicast/smrf.h +++ b/core/net/ipv6/multicast/smrf.h @@ -29,12 +29,22 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup uip6-multicast + * @{ + */ +/** + * \defgroup smrf-multicast 'Stateless Multicast RPL Forwarding' (SMRF) + * + * SMRF will only work in RPL networks in MOP 3 "Storing with Multicast" + * @{ + */ /** * \file - * Header file for 'Stateless Multicast RPL Forwarding' (SMRF) + * Header file for the SMRF forwarding engine * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef SMRF_H_ @@ -71,5 +81,8 @@ struct smrf_stats { uint16_t mcast_bad; uint16_t mcast_dropped; }; - +/*---------------------------------------------------------------------------*/ #endif /* SMRF_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-engines.h b/core/net/ipv6/multicast/uip-mcast6-engines.h index cea3c9ecc..f4bff657a 100644 --- a/core/net/ipv6/multicast/uip-mcast6-engines.h +++ b/core/net/ipv6/multicast/uip-mcast6-engines.h @@ -29,22 +29,27 @@ * This file is part of the Contiki operating system. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Header file with definition of multicast engine constants + * Header file with definition of multicast engine constants * - * When writing a new engine, add it here with a unique number and - * then modify uip-mcast6.h accordingly + * When writing a new engine, add it here with a unique number and + * then modify uip-mcast6.h accordingly * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef UIP_MCAST6_ENGINES_H_ #define UIP_MCAST6_ENGINES_H_ -#define UIP_MCAST6_ENGINE_NONE 0 /* Selecting this disables mcast */ -#define UIP_MCAST6_ENGINE_SMRF 1 -#define UIP_MCAST6_ENGINE_ROLL_TM 2 +#define UIP_MCAST6_ENGINE_NONE 0 /**< Selecting this disables mcast */ +#define UIP_MCAST6_ENGINE_SMRF 1 /**< The SMRF engine */ +#define UIP_MCAST6_ENGINE_ROLL_TM 2 /**< The ROLL TM engine */ #endif /* UIP_MCAST6_ENGINES_H_ */ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-route.c b/core/net/ipv6/multicast/uip-mcast6-route.c index e414fbf17..f6b9737fc 100644 --- a/core/net/ipv6/multicast/uip-mcast6-route.c +++ b/core/net/ipv6/multicast/uip-mcast6-route.c @@ -28,12 +28,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Multicast routing table manipulation + * Multicast routing table manipulation * * \author - * George Oikonomou - + * George Oikonomou - */ #include "contiki.h" @@ -128,3 +132,4 @@ uip_mcast6_route_init() list_init(mcast_route_list); } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-route.h b/core/net/ipv6/multicast/uip-mcast6-route.h index ef5d43f77..95e808676 100644 --- a/core/net/ipv6/multicast/uip-mcast6-route.h +++ b/core/net/ipv6/multicast/uip-mcast6-route.h @@ -28,12 +28,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Multicast routing table manipulation + * Header file for multicast routing table manipulation * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef UIP_MCAST6_ROUTE_H_ #define UIP_MCAST6_ROUTE_H_ @@ -45,18 +49,48 @@ /*---------------------------------------------------------------------------*/ /** \brief An entry in the multicast routing table */ typedef struct uip_mcast6_route { - struct uip_mcast6_route *next; - uip_ipaddr_t group; - uint32_t lifetime; /* seconds */ - void *dag; /* Pointer to an rpl_dag_t struct */ + struct uip_mcast6_route *next; /**< Routes are arranged in a linked list */ + uip_ipaddr_t group; /**< The multicast group */ + uint32_t lifetime; /**< Entry lifetime seconds */ + void *dag; /**< Pointer to an rpl_dag_t struct */ } uip_mcast6_route_t; /*---------------------------------------------------------------------------*/ /** \name Multicast Routing Table Manipulation */ /** @{ */ + +/** + * \brief Lookup a multicast route + * \param group A pointer to the multicast group to be searched for + * \return A pointer to the new routing entry, or NULL if the route could not + * be found + */ uip_mcast6_route_t *uip_mcast6_route_lookup(uip_ipaddr_t *group); + +/** + * \brief Add a multicast route + * \param group A pointer to the multicast group to be added + * \return A pointer to the new route, or NULL if the route could not be added + */ uip_mcast6_route_t *uip_mcast6_route_add(uip_ipaddr_t *group); -void uip_mcast6_route_rm(uip_mcast6_route_t *defrt); + +/** + * \brief Remove a multicast route + * \param route A pointer to the route to be removed + */ +void uip_mcast6_route_rm(uip_mcast6_route_t *route); + +/** + * \brief Retrieve the count of multicast routes + * \return The number of multicast routes + */ int uip_mcast6_route_count(void); + +/** + * \brief Retrieve a pointer to the start of the multicast routes list + * \return A pointer to the start of the multicast routes + * + * If the multicast routes list is empty, this function will return NULL + */ uip_mcast6_route_t *uip_mcast6_route_list_head(void); /*---------------------------------------------------------------------------*/ /** @@ -73,3 +107,4 @@ void uip_mcast6_route_init(void); /** @} */ #endif /* UIP_MCAST6_ROUTE_H_ */ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-stats.c b/core/net/ipv6/multicast/uip-mcast6-stats.c index ed23747f1..d617358ba 100644 --- a/core/net/ipv6/multicast/uip-mcast6-stats.c +++ b/core/net/ipv6/multicast/uip-mcast6-stats.c @@ -27,12 +27,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * IPv6 multicast forwarding stats maintenance + * IPv6 multicast forwarding stats maintenance * * \author - * George Oikonomou - + * George Oikonomou - */ #include "net/ipv6/multicast/uip-mcast6-stats.h" @@ -47,3 +51,4 @@ uip_mcast6_stats_init(void *stats) uip_mcast6_stats.engine_stats = stats; } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6-stats.h b/core/net/ipv6/multicast/uip-mcast6-stats.h index 1e3775934..263758b66 100644 --- a/core/net/ipv6/multicast/uip-mcast6-stats.h +++ b/core/net/ipv6/multicast/uip-mcast6-stats.h @@ -27,12 +27,16 @@ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. */ +/** + * \addtogroup uip6-multicast + * @{ + */ /** * \file - * Header file for IPv6 multicast forwarding stats maintenance + * Header file for IPv6 multicast forwarding stats maintenance * * \author - * George Oikonomou - + * George Oikonomou - */ #ifndef UIP_MCAST6_STATS_H_ #define UIP_MCAST6_STATS_H_ @@ -56,15 +60,35 @@ /*---------------------------------------------------------------------------*/ /* Stats datatype */ /*---------------------------------------------------------------------------*/ +/** + * \brief A data structure used to maintain multicast stats + * + * Each engine can extend this structure via the engine_stats field + */ typedef struct uip_mcast6_stats { + /** Count of unique datagrams received */ UIP_MCAST6_STATS_DATATYPE mcast_in_unique; - UIP_MCAST6_STATS_DATATYPE mcast_in_all; /* At layer 3 */ - UIP_MCAST6_STATS_DATATYPE mcast_in_ours; /* Unique and we are a group member */ - UIP_MCAST6_STATS_DATATYPE mcast_fwd; /* Forwarded by us but we are not the seed */ - UIP_MCAST6_STATS_DATATYPE mcast_out; /* We are the seed */ + + /** Count of all datagrams received */ + UIP_MCAST6_STATS_DATATYPE mcast_in_all; + + /** Count of datagrams received for a group that we have joined */ + UIP_MCAST6_STATS_DATATYPE mcast_in_ours; + + /** Count of datagrams forwarded by us but we are not the seed */ + UIP_MCAST6_STATS_DATATYPE mcast_fwd; + + /** Count of multicast datagrams originated by us */ + UIP_MCAST6_STATS_DATATYPE mcast_out; + + /** Count of malformed multicast datagrams seen by us */ UIP_MCAST6_STATS_DATATYPE mcast_bad; + + /** Count of multicast datagrams correclty formed but dropped by us */ UIP_MCAST6_STATS_DATATYPE mcast_dropped; - void *engine_stats; /* Opaque pointer to an engine's additional stats */ + + /** Opaque pointer to an engine's additional stats */ + void *engine_stats; } uip_mcast6_stats_t; /*---------------------------------------------------------------------------*/ /* Access macros */ @@ -89,3 +113,5 @@ extern uip_mcast6_stats_t uip_mcast6_stats; void uip_mcast6_stats_init(void *stats); /*---------------------------------------------------------------------------*/ #endif /* UIP_MCAST6_STATS_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/multicast/uip-mcast6.h b/core/net/ipv6/multicast/uip-mcast6.h index 9bd2b2b2d..de2003839 100644 --- a/core/net/ipv6/multicast/uip-mcast6.h +++ b/core/net/ipv6/multicast/uip-mcast6.h @@ -30,9 +30,11 @@ */ /** - * \file - * This header file contains configuration directives for uIPv6 - * multicast support. + * \addtogroup uip6 + * @{ + */ +/** + * \defgroup uip6-multicast IPv6 Multicast Forwarding * * We currently support 2 engines: * - 'Stateless Multicast RPL Forwarding' (SMRF) @@ -42,6 +44,14 @@ * in the internet draft: * http://tools.ietf.org/html/draft-ietf-roll-trickle-mcast * + * @{ + */ + +/** + * \file + * This header file contains configuration directives for uIPv6 + * multicast support. + * * \author * George Oikonomou - */ @@ -83,7 +93,11 @@ * Multicast API. Similar to NETSTACK, each engine must define a driver and * populate the fields with suitable function pointers */ +/** + * \brief The data structure used to represent a multicast engine + */ struct uip_mcast6_driver { + /** The driver's name */ char *name; /** Initialize the multicast engine */ @@ -110,6 +124,7 @@ struct uip_mcast6_driver { * * \return 0: Drop, 1: Deliver * + * * When a datagram with a multicast destination address is received, * the forwarding logic in core is bypassed. Instead, we let the * multicast engine handle forwarding internally if and as necessary. @@ -158,5 +173,7 @@ extern const struct uip_mcast6_driver UIP_MCAST6; #error "Check the value of UIP_CONF_IPV6_RPL in conf files." #endif /*---------------------------------------------------------------------------*/ - #endif /* UIP_MCAST6_H_ */ +/*---------------------------------------------------------------------------*/ +/** @} */ +/** @} */ diff --git a/core/net/ipv6/sicslowpan.h b/core/net/ipv6/sicslowpan.h index a46229b02..4dcb2ae11 100644 --- a/core/net/ipv6/sicslowpan.h +++ b/core/net/ipv6/sicslowpan.h @@ -234,7 +234,7 @@ struct sicslowpan_addr_context { * \brief check whether we can compress the IID in * address 'a' to 16 bits. * This is used for unicast addresses only, and is true - * if the address is on the format ::0000:00ff:fe00:XXXX + * if the address is on the format \::0000:00ff:fe00:XXXX * NOTE: we currently assume 64-bits prefixes */ #define sicslowpan_is_iid_16_bit_compressable(a) \ diff --git a/core/net/ipv6/uip-ds6-nbr.c b/core/net/ipv6/uip-ds6-nbr.c index 86f915d10..db14f8647 100644 --- a/core/net/ipv6/uip-ds6-nbr.c +++ b/core/net/ipv6/uip-ds6-nbr.c @@ -29,20 +29,20 @@ * */ +/** + * \addtogroup uip6 + * @{ + */ + /** * \file - * IPv6 Neighbor cache (link-layer/IPv6 address mapping) + * IPv6 Neighbor cache (link-layer/IPv6 address mapping) * \author Mathilde Durvy * \author Julien Abeille * \author Simon Duquennoy * */ -/** - * \addtogroup uip6 - * @{ - */ - #include #include #include diff --git a/core/net/ipv6/uip-ds6-nbr.h b/core/net/ipv6/uip-ds6-nbr.h index 0c9b29128..36a202e86 100644 --- a/core/net/ipv6/uip-ds6-nbr.h +++ b/core/net/ipv6/uip-ds6-nbr.h @@ -29,20 +29,20 @@ * */ +/** + * \addtogroup uip6 + * @{ + */ + /** * \file - * IPv6 Neighbor cache (link-layer/IPv6 address mapping) + * IPv6 Neighbor cache (link-layer/IPv6 address mapping) * \author Mathilde Durvy * \author Julien Abeille * \author Simon Duquennoy * */ -/** - * \addtogroup uip6 - * @{ - */ - #ifndef UIP_DS6_NEIGHBOR_H_ #define UIP_DS6_NEIGHBOR_H_ @@ -99,12 +99,12 @@ int uip_ds6_nbr_num(void); /** * \brief - * This searches inside the neighbor table for the neighbor that is about to - * expire the next. + * This searches inside the neighbor table for the neighbor that is about to + * expire the next. * * \return - * A reference to the neighbor about to expire the next or NULL if - * table is empty. + * A reference to the neighbor about to expire the next or NULL if + * table is empty. */ uip_ds6_nbr_t *uip_ds6_get_least_lifetime_neighbor(void); diff --git a/core/net/ipv6/uip-ds6-route.c b/core/net/ipv6/uip-ds6-route.c index 73a4ce9fa..3931319a0 100644 --- a/core/net/ipv6/uip-ds6-route.c +++ b/core/net/ipv6/uip-ds6-route.c @@ -29,6 +29,15 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * */ +/** + * \addtogroup uip6 + * @{ + */ + +/** + * \file + * Routing table manipulation + */ #include "net/ipv6/uip-ds6.h" #include "net/ip/uip.h" @@ -636,3 +645,4 @@ uip_ds6_defrt_periodic(void) } } /*---------------------------------------------------------------------------*/ +/** @} */ diff --git a/core/net/ipv6/uip-ds6-route.h b/core/net/ipv6/uip-ds6-route.h index 9603d6cde..27cbee79b 100644 --- a/core/net/ipv6/uip-ds6-route.h +++ b/core/net/ipv6/uip-ds6-route.h @@ -29,6 +29,14 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. * */ +/** + * \addtogroup uip6 + * @{ + */ +/** + * \file + * Header file for routing table manipulation + */ #ifndef UIP_DS6_ROUTE_H #define UIP_DS6_ROUTE_H @@ -158,3 +166,4 @@ uip_ds6_route_t *uip_ds6_route_next(uip_ds6_route_t *); /** @} */ #endif /* UIP_DS6_ROUTE_H */ +/** @} */ diff --git a/core/net/ipv6/uip-ds6.c b/core/net/ipv6/uip-ds6.c index d5b848b9a..ce75ca485 100644 --- a/core/net/ipv6/uip-ds6.c +++ b/core/net/ipv6/uip-ds6.c @@ -29,17 +29,17 @@ */ /** - * \file - * IPv6 data structures handling functions. - * Comprises part of the Neighbor discovery (RFC 4861) - * and auto configuration (RFC 4862) state machines. - * \author Mathilde Durvy - * \author Julien Abeille + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * IPv6 data structure manipulation. + * Comprises part of the Neighbor discovery (RFC 4861) + * and auto configuration (RFC 4862) state machines. + * \author Mathilde Durvy + * \author Julien Abeille */ #include diff --git a/core/net/ipv6/uip-ds6.h b/core/net/ipv6/uip-ds6.h index b6238e609..9c470a1db 100644 --- a/core/net/ipv6/uip-ds6.h +++ b/core/net/ipv6/uip-ds6.h @@ -5,7 +5,7 @@ /** * \file - * Network interface and stateless autoconfiguration (RFC 4862) + * Header file for IPv6-related data structures * \author Mathilde Durvy * \author Julien Abeille * diff --git a/core/net/ipv6/uip-icmp6.c b/core/net/ipv6/uip-icmp6.c index b14ac2d64..ee8d94c77 100644 --- a/core/net/ipv6/uip-icmp6.c +++ b/core/net/ipv6/uip-icmp6.c @@ -31,15 +31,15 @@ */ /** - * \file - * ICMPv6 echo request and error messages (RFC 4443) - * \author Julien Abeille - * \author Mathilde Durvy + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * ICMPv6 (RFC 4443) implementation, with message and error handling + * \author Julien Abeille + * \author Mathilde Durvy */ #include diff --git a/core/net/ipv6/uip-icmp6.h b/core/net/ipv6/uip-icmp6.h index aa44bff5a..5633791fd 100644 --- a/core/net/ipv6/uip-icmp6.h +++ b/core/net/ipv6/uip-icmp6.h @@ -31,15 +31,15 @@ */ /** - * \file - * ICMPv6 echo request and error messages (RFC 4443) - * \author Julien Abeille - * \author Mathilde Durvy + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * Header file for ICMPv6 message and error handing (RFC 4443) + * \author Julien Abeille + * \author Mathilde Durvy */ #ifndef ICMP6_H_ diff --git a/core/net/ipv6/uip-nd6.c b/core/net/ipv6/uip-nd6.c index 273b45134..accaf8271 100644 --- a/core/net/ipv6/uip-nd6.c +++ b/core/net/ipv6/uip-nd6.c @@ -57,15 +57,15 @@ */ /** - * \file - * Neighbor discovery (RFC 4861) - * \author Mathilde Durvy - * \author Julien Abeille + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * Neighbor discovery (RFC 4861) + * \author Mathilde Durvy + * \author Julien Abeille */ #include diff --git a/core/net/ipv6/uip-nd6.h b/core/net/ipv6/uip-nd6.h index 0ece86522..6c88de614 100644 --- a/core/net/ipv6/uip-nd6.h +++ b/core/net/ipv6/uip-nd6.h @@ -31,15 +31,15 @@ */ /** - * \file - * Neighbor discovery (RFC 4861) - * \author Julien Abeille - * \author Mathilde Durvy + * \addtogroup uip6 + * @{ */ /** - * \addtogroup uip6 - * @{ + * \file + * Header file for IPv6 Neighbor discovery (RFC 4861) + * \author Julien Abeille + * \author Mathilde Durvy */ #ifndef UIP_ND6_H_ diff --git a/core/net/ipv6/uip6.c b/core/net/ipv6/uip6.c index 2debd54d7..a5d1db13c 100644 --- a/core/net/ipv6/uip6.c +++ b/core/net/ipv6/uip6.c @@ -31,20 +31,20 @@ * */ +/** + * \addtogroup uip6 + * @{ + */ + /** * \file - * The uIP TCP/IPv6 stack code. + * The uIP TCP/IPv6 stack code. * * \author Adam Dunkels * \author Julien Abeille (IPv6 related code) * \author Mathilde Durvy (IPv6 related code) */ -/** - * \addtogroup uip6 - * @{ - */ - /* * uIP is a small implementation of the IP, UDP and TCP protocols (as * well as some basic ICMP stuff). The implementation couples the IP, @@ -105,7 +105,10 @@ struct uip_stats uip_stat; /*---------------------------------------------------------------------------*/ -/** @{ \name Layer 2 variables */ +/** + * \name Layer 2 variables + * @{ + */ /*---------------------------------------------------------------------------*/ /** Host L2 address */ #if UIP_CONF_LL_802154 @@ -116,7 +119,10 @@ uip_lladdr_t uip_lladdr = {{0x00,0x06,0x98,0x00,0x02,0x32}}; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name Layer 3 variables */ +/** + * \name Layer 3 variables + * @{ + */ /*---------------------------------------------------------------------------*/ /** * \brief Type of the next header in IPv6 header or extension headers @@ -141,8 +147,9 @@ uint8_t uip_ext_opt_offset = 0; /*---------------------------------------------------------------------------*/ /* Buffers */ /*---------------------------------------------------------------------------*/ -/** \name Buffer defines - * @{ +/** + * \name Buffer defines + * @{ */ #define FBUF ((struct uip_tcpip_hdr *)&uip_reassbuf[0]) #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) @@ -161,8 +168,9 @@ uint8_t uip_ext_opt_offset = 0; #endif /* UIP_CONF_IPV6_RPL */ #define UIP_ICMP6_ERROR_BUF ((struct uip_icmp6_error *)&uip_buf[uip_l2_l3_icmp_hdr_len]) /** @} */ -/** \name Buffer variables - * @{ +/** + * \name Buffer variables + * @{ */ /** Packet buffer for incoming and outgoing packets */ #ifndef UIP_CONF_EXTERNAL_BUFFER @@ -185,7 +193,10 @@ uint16_t uip_len, uip_slen; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name General variables */ +/** + * \name General variables + * @{ + */ /*---------------------------------------------------------------------------*/ /* The uip_flags variable is used for communication between the TCP/IP stack @@ -209,7 +220,8 @@ static uint16_t lastport; /*---------------------------------------------------------------------------*/ /* TCP */ /*---------------------------------------------------------------------------*/ -/** \name TCP defines +/** + * \name TCP defines *@{ */ /* Structures and definitions. */ @@ -227,7 +239,8 @@ static uint16_t lastport; #define TCP_OPT_MSS_LEN 4 /* Length of TCP MSS option. */ /** @} */ -/** \name TCP variables +/** + * \name TCP variables *@{ */ #if UIP_TCP @@ -248,7 +261,10 @@ static uint16_t tmp16; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name UDP variables */ +/** + * \name UDP variables + * @{ + */ /*---------------------------------------------------------------------------*/ #if UIP_UDP struct uip_udp_conn *uip_udp_conn; @@ -257,7 +273,10 @@ struct uip_udp_conn uip_udp_conns[UIP_UDP_CONNS]; /** @} */ /*---------------------------------------------------------------------------*/ -/** @{ \name ICMPv6 variables */ +/** + * \name ICMPv6 variables + * @{ + */ /*---------------------------------------------------------------------------*/ #if UIP_CONF_ICMP6 /** single possible icmpv6 "connection" */ diff --git a/core/net/llsec/anti-replay.h b/core/net/llsec/anti-replay.h index 2f8e7b2d8..9211a6e7a 100644 --- a/core/net/llsec/anti-replay.h +++ b/core/net/llsec/anti-replay.h @@ -64,12 +64,13 @@ uint32_t anti_replay_get_counter(void); /** * \brief Initializes the anti-replay information about the sender + * \param info Anti-replay information about the sender */ void anti_replay_init_info(struct anti_replay_info *info); /** * \brief Checks if received frame was replayed - * \param last_counters Anti-replay information about the sender + * \param info Anti-replay information about the sender * \retval 0 <-> received frame was not replayed */ int anti_replay_was_replayed(struct anti_replay_info *info); diff --git a/core/net/llsec/llsec802154.h b/core/net/llsec/llsec802154.h index 5d81d9cb4..6ab6a9793 100644 --- a/core/net/llsec/llsec802154.h +++ b/core/net/llsec/llsec802154.h @@ -43,7 +43,7 @@ */ /** - * \defgroup llsec802154 + * \defgroup llsec802154 Link Layer Security Common Functionality * * Common functionality of 802.15.4-compliant llsec_drivers. * diff --git a/core/net/llsec/noncoresec/noncoresec.h b/core/net/llsec/noncoresec/noncoresec.h index 493ff5ce5..1e2172590 100644 --- a/core/net/llsec/noncoresec/noncoresec.h +++ b/core/net/llsec/noncoresec/noncoresec.h @@ -43,7 +43,7 @@ */ /** - * \defgroup noncoresec + * \defgroup noncoresec LLSEC driver using a network-wide key (NONCORESEC) * * Noncompromise-resilient 802.15.4 security * diff --git a/core/net/llsec/nullsec.h b/core/net/llsec/nullsec.h index 2682bd343..30488e5d4 100644 --- a/core/net/llsec/nullsec.h +++ b/core/net/llsec/nullsec.h @@ -43,7 +43,7 @@ */ /** - * \defgroup nullsec + * \defgroup nullsec LLSEC driver with zero security (NULLSEC) * * Insecure link layer security driver. * diff --git a/core/net/mac/frame802154.h b/core/net/mac/frame802154.h index 4b3a81049..64a367120 100644 --- a/core/net/mac/frame802154.h +++ b/core/net/mac/frame802154.h @@ -44,7 +44,7 @@ */ /** - * \addtogroup net 802.15.4 frame creation and parsing + * \addtogroup net * @{ */ diff --git a/core/net/rime/abc.h b/core/net/rime/abc.h index 8e2b1d86b..b1f7f8f29 100644 --- a/core/net/rime/abc.h +++ b/core/net/rime/abc.h @@ -49,7 +49,7 @@ * The abc module sends packets to all local area neighbors. The abc * module adds no headers to outgoing packets. * - * \section channels Channels + * \section abc-channels Channels * * The abc module uses 1 channel. * diff --git a/core/net/rime/announcement.h b/core/net/rime/announcement.h index 759ab8b08..802d1da84 100644 --- a/core/net/rime/announcement.h +++ b/core/net/rime/announcement.h @@ -131,6 +131,7 @@ void announcement_remove(struct announcement *a); * \brief Set the value of an announcement * \param a A pointer to a struct announcement that has * previously been registered + * \param value The new value * * This function sets the value of an announcement that * has previously been registered with diff --git a/core/net/rime/broadcast-announcement.h b/core/net/rime/broadcast-announcement.h index 371c84fc9..0cca9d85c 100644 --- a/core/net/rime/broadcast-announcement.h +++ b/core/net/rime/broadcast-announcement.h @@ -50,7 +50,7 @@ * announcement. THe module announces the announcements that have been * registered with the \ref rimeannouncement "announcement module". * - * \section channels Channels + * \section bcast-announce-channels Channels * * The broadcast announcement module uses 1 channel. * diff --git a/core/net/rime/broadcast.h b/core/net/rime/broadcast.h index c4e427405..4a4c885d7 100644 --- a/core/net/rime/broadcast.h +++ b/core/net/rime/broadcast.h @@ -56,7 +56,7 @@ * either directly or indirectly through any of the other * communication primitives that are based on the broadcast primitive. * - * \section channels Channels + * \section broadcast-channels Channels * * The broadcast module uses 1 channel. * diff --git a/core/net/rime/collect.h b/core/net/rime/collect.h index 333d71628..d731a531b 100644 --- a/core/net/rime/collect.h +++ b/core/net/rime/collect.h @@ -49,7 +49,7 @@ * The collect module implements a hop-by-hop reliable data collection * mechanism. * - * \section channels Channels + * \section collect-channels Channels * * The collect module uses 2 channels; one for neighbor discovery and one * for data packets. diff --git a/core/net/rime/ipolite.h b/core/net/rime/ipolite.h index c76505913..e1fa683b3 100644 --- a/core/net/rime/ipolite.h +++ b/core/net/rime/ipolite.h @@ -84,7 +84,7 @@ * The polite broadcast module does not add any packet attributes to * outgoing packets apart from those added by the upper layer. * - * \section channels Channels + * \section ipolite-channels Channels * * The ipolite module uses 1 channel. * diff --git a/core/net/rime/mesh.h b/core/net/rime/mesh.h index 35a009366..40aaf5bd1 100644 --- a/core/net/rime/mesh.h +++ b/core/net/rime/mesh.h @@ -50,7 +50,7 @@ * receiver somewhere in the network. * * - * \section channels Channels + * \section mesh-channels Channels * * The mesh module uses 3 channel; one for the multi-hop forwarding * (\ref rimemultihop "multihop") and two for the route disovery (\ref diff --git a/core/net/rime/multihop.h b/core/net/rime/multihop.h index bf1bf8c44..a577a3339 100644 --- a/core/net/rime/multihop.h +++ b/core/net/rime/multihop.h @@ -61,7 +61,7 @@ * process. * * - * \section channels Channels + * \section multihop-channels Channels * * The multihop module uses 1 channel. * diff --git a/core/net/rime/neighbor-discovery.h b/core/net/rime/neighbor-discovery.h index 113ec1418..337a9c15a 100644 --- a/core/net/rime/neighbor-discovery.h +++ b/core/net/rime/neighbor-discovery.h @@ -50,7 +50,7 @@ * discovery mechanism. A callback is invoked for every incoming * neighbor discovery message. * - * \section channels Channels + * \section neighbor-discovery-channels Channels * * The neighbor-discovery module uses 1 channel. * diff --git a/core/net/rime/netflood.h b/core/net/rime/netflood.h index 5c791f086..d21593cf2 100644 --- a/core/net/rime/netflood.h +++ b/core/net/rime/netflood.h @@ -65,7 +65,7 @@ * If the time to live reaches zero, the primitive does not forward * the packet. * - * \section channels Channels + * \section netflood-channels Channels * * The netflood module uses 1 channel. * diff --git a/core/net/rime/packetqueue.h b/core/net/rime/packetqueue.h index 5ec581a6c..5956d67e8 100644 --- a/core/net/rime/packetqueue.h +++ b/core/net/rime/packetqueue.h @@ -78,7 +78,7 @@ struct packetqueue { * This structure holds the state of a packet queue. It is * an opaque structure with no user-visible elements. The * function packetqueue_queuebuf() is used to extract a - * \ref queuebuf "queubuf" from the item. The function + * "queubuf" from the item. The function * packetqueue_ptr() is used to extract the opaque pointer * that was registered with the * packetqueue_enqueue_packetbuf() function. diff --git a/core/net/rime/polite-announcement.h b/core/net/rime/polite-announcement.h index c3af5d814..76b4a12ec 100644 --- a/core/net/rime/polite-announcement.h +++ b/core/net/rime/polite-announcement.h @@ -50,7 +50,7 @@ * announcement. THe module announces the announcements that have been * registered with the \ref rimeannouncement "announcement module". * - * \section channels Channels + * \section polite-announcement-channels Channels * * The polite announcement module uses 1 channel. * diff --git a/core/net/rime/polite.h b/core/net/rime/polite.h index 82e6e911b..59c424608 100644 --- a/core/net/rime/polite.h +++ b/core/net/rime/polite.h @@ -84,7 +84,7 @@ * The polite broadcast module does not add any packet attributes to * outgoing packets apart from those added by the upper layer. * - * \section channels Channels + * \section polite-channels Channels * * The polite module uses 1 channel. * diff --git a/core/net/rime/rmh.h b/core/net/rime/rmh.h index f7d7786a6..14faac14d 100644 --- a/core/net/rime/rmh.h +++ b/core/net/rime/rmh.h @@ -56,7 +56,7 @@ * reliable single-hop primitive for the communication between two * single-hop neighbors. * - * \section channels Channels + * \section rmh-channels Channels * * The rmh module uses 1 channel. * diff --git a/core/net/rime/route-discovery.h b/core/net/rime/route-discovery.h index f1ac6fd3a..81d454d5f 100644 --- a/core/net/rime/route-discovery.h +++ b/core/net/rime/route-discovery.h @@ -48,7 +48,7 @@ * * The route-discovery module does route discovery for Rime. * - * \section channels Channels + * \section route-discovery-channels Channels * * The ibc module uses 2 channels; one for the flooded route request * packets and one for the unicast route replies. diff --git a/core/net/rime/rudolph0.h b/core/net/rime/rudolph0.h index 21ac1c086..695d97950 100644 --- a/core/net/rime/rudolph0.h +++ b/core/net/rime/rudolph0.h @@ -49,7 +49,7 @@ * The rudolph0 module implements a single-hop reliable bulk data * transfer mechanism. * - * \section channels Channels + * \section rudolph0-channels Channels * * The rudolph0 module uses 2 channels; one for data packets and one * for NACK and repair packets. diff --git a/core/net/rime/rudolph1.h b/core/net/rime/rudolph1.h index 6b487bbe9..399a0a84e 100644 --- a/core/net/rime/rudolph1.h +++ b/core/net/rime/rudolph1.h @@ -49,7 +49,7 @@ * The rudolph1 module implements a multi-hop reliable bulk data * transfer mechanism. * - * \section channels Channels + * \section rudolph1-channels Channels * * The rudolph1 module uses 2 channels; one for data transmissions and * one for NACKs and repair packets. diff --git a/core/net/rime/rudolph2.h b/core/net/rime/rudolph2.h index 6afe5506e..e1d43e8fa 100644 --- a/core/net/rime/rudolph2.h +++ b/core/net/rime/rudolph2.h @@ -49,7 +49,7 @@ * The rudolph2 module implements a single-hop reliable bulk data * transfer mechanism. * - * \section channels Channels + * \section rudolph2-channels Channels * * The rudolph2 module uses 2 channels; one for data packets and one * for NACK and repair packets. diff --git a/core/net/rime/runicast.h b/core/net/rime/runicast.h index a3b55a5e6..a7e199435 100644 --- a/core/net/rime/runicast.h +++ b/core/net/rime/runicast.h @@ -69,7 +69,7 @@ * callback. * * - * \section channels Channels + * \section runicast-channels Channels * * The runicast module uses 1 channel. * diff --git a/core/net/rime/stbroadcast.h b/core/net/rime/stbroadcast.h index 2c04dc273..0b656827e 100644 --- a/core/net/rime/stbroadcast.h +++ b/core/net/rime/stbroadcast.h @@ -51,7 +51,7 @@ * either the message is canceled or a new message is sent. Messages * sent with the stbroadcast module are not identified with a sender ID. * - * \section channels Channels + * \section stbroadcast-channels Channels * * The stbroadcast module uses 1 channel. * diff --git a/core/net/rime/stunicast.h b/core/net/rime/stunicast.h index cac93cc84..6e02d88ff 100644 --- a/core/net/rime/stunicast.h +++ b/core/net/rime/stunicast.h @@ -63,7 +63,7 @@ * number of retransmissions for a packet as a packet attribute on * outgoing packets. * - * \section channels Channels + * \section stunicast-channels Channels * * The stunicast module uses 1 channel. * diff --git a/core/net/rime/trickle.h b/core/net/rime/trickle.h index 5a33bec32..1521024b7 100644 --- a/core/net/rime/trickle.h +++ b/core/net/rime/trickle.h @@ -48,7 +48,7 @@ * * The trickle module sends a single packet to all nodes on the network. * - * \section channels Channels + * \section trickle-channels Channels * * The trickle module uses 1 channel. * diff --git a/core/net/rime/unicast.h b/core/net/rime/unicast.h index 9b0e06db7..3cb5bb148 100644 --- a/core/net/rime/unicast.h +++ b/core/net/rime/unicast.h @@ -53,7 +53,7 @@ * single-hop receiver address attribute and discards the packet if * the address does not match the address of the node. * - * \section channels Channels + * \section unicast-channels Channels * * The unicast module uses 1 channel. * diff --git a/core/net/rpl/rpl-icmp6.c b/core/net/rpl/rpl-icmp6.c index 8fdefdedc..c9890b706 100644 --- a/core/net/rpl/rpl-icmp6.c +++ b/core/net/rpl/rpl-icmp6.c @@ -64,7 +64,7 @@ /*---------------------------------------------------------------------------*/ #define RPL_DIO_GROUNDED 0x80 #define RPL_DIO_MOP_SHIFT 3 -#define RPL_DIO_MOP_MASK 0x3c +#define RPL_DIO_MOP_MASK 0x38 #define RPL_DIO_PREFERENCE_MASK 0x07 #define UIP_IP_BUF ((struct uip_ip_hdr *)&uip_buf[UIP_LLH_LEN]) diff --git a/core/net/rpl/rpl.c b/core/net/rpl/rpl.c index f71c5fb4c..f92d5f5f8 100644 --- a/core/net/rpl/rpl.c +++ b/core/net/rpl/rpl.c @@ -76,9 +76,9 @@ rpl_set_mode(enum rpl_mode m) switching to. */ if(m == RPL_MODE_MESH) { - /* If we switcht to mesh mode, we should send out a DAO message to + /* If we switch to mesh mode, we should send out a DAO message to inform our parent that we now are reachable. Before we do this, - we must set the mode variable, since DAOs will not be send if + we must set the mode variable, since DAOs will not be sent if we are in feather mode. */ PRINTF("RPL: switching to mesh mode\n"); mode = m; diff --git a/core/sys/cc.h b/core/sys/cc.h index 53a5af4db..90ef3e710 100644 --- a/core/sys/cc.h +++ b/core/sys/cc.h @@ -133,7 +133,7 @@ * strings. * * We need use two macros (CC_CONCAT and CC_CONCAT2) in order to allow - * concatenation of two #defined macros. + * concatenation of two \#defined macros. */ #define CC_CONCAT(s1, s2) CC_CONCAT2(s1, s2) diff --git a/core/sys/clock.h b/core/sys/clock.h index 46232273e..4cbfdb223 100644 --- a/core/sys/clock.h +++ b/core/sys/clock.h @@ -57,7 +57,7 @@ * * \note The clock library need in many cases not be used * directly. Rather, the \ref timer "timer library", \ref etimer - * "event timers", or \ref trimer "rtimer library" should be used. + * "event timers", or \ref rtimer "rtimer library" should be used. * * \sa \ref timer "Timer library" * \sa \ref etimer "Event timers" diff --git a/core/sys/dsc.h b/core/sys/dsc.h index ad7632390..b8b70433e 100644 --- a/core/sys/dsc.h +++ b/core/sys/dsc.h @@ -105,7 +105,7 @@ struct dsc { * * \param prgname The name of the program on disk. * - * \param initfunc A pointer to the initialization function of the + * \param process A pointer to the initialization function of the * program. * * \param icon A pointer to the CTK icon. diff --git a/core/sys/process.c b/core/sys/process.c index ef28f80f4..b2ed5701c 100644 --- a/core/sys/process.c +++ b/core/sys/process.c @@ -267,7 +267,7 @@ do_event(void) receiver = events[fevent].p; /* Since we have seen the new event, we move pointer upwards - and decrese the number of events. */ + and decrease the number of events. */ fevent = (fevent + 1) % PROCESS_CONF_NUMEVENTS; --nevents; @@ -337,7 +337,7 @@ process_post(struct process *p, process_event_t ev, process_data_t data) if(p == PROCESS_BROADCAST) { printf("soft panic: event queue is full when broadcast event %d was posted from %s\n", ev, PROCESS_NAME_STRING(process_current)); } else { - printf("soft panic: event queue is full when event %d was posted to %s frpm %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current)); + printf("soft panic: event queue is full when event %d was posted to %s from %s\n", ev, PROCESS_NAME_STRING(p), PROCESS_NAME_STRING(process_current)); } #endif /* DEBUG */ return PROCESS_ERR_FULL; diff --git a/core/sys/process.h b/core/sys/process.h index 43547f3bd..2d15ca89c 100644 --- a/core/sys/process.h +++ b/core/sys/process.h @@ -335,7 +335,7 @@ struct process { * * \param p A pointer to a process structure. * - * \param arg An argument pointer that can be passed to the new + * \param data An argument pointer that can be passed to the new * process * */ diff --git a/cpu/arm/aducrf101/Makefile.aducrf101.gnu b/cpu/arm/aducrf101/Makefile.aducrf101.gnu index 93de277a2..bafb06aa9 100644 --- a/cpu/arm/aducrf101/Makefile.aducrf101.gnu +++ b/cpu/arm/aducrf101/Makefile.aducrf101.gnu @@ -39,8 +39,8 @@ CROSS_COMPILE = arm-none-eabi- CC = $(CROSS_COMPILE)gcc LD = $(CROSS_COMPILE)gcc AS = $(CROSS_COMPILE)gcc -AR = $(CROSS_COMPILE)ar -NM = $(CROSS_COMPILE)nm +AR = $(CROSS_COMPILE)gcc-ar +NM = $(CROSS_COMPILE)gcc-nm OBJCOPY = $(CROSS_COMPILE)objcopy OBJDUMP = $(CROSS_COMPILE)objdump STRIP = $(CROSS_COMPILE)strip diff --git a/cpu/avr/dev/clock.c b/cpu/avr/dev/clock.c index 16dfe1d6a..95e730feb 100644 --- a/cpu/avr/dev/clock.c +++ b/cpu/avr/dev/clock.c @@ -159,7 +159,7 @@ clock_set_seconds(unsigned long sec) seconds = sec; } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a number of clock ticks. */ void @@ -175,7 +175,7 @@ clock_wait(clock_time_t t) } } /*---------------------------------------------------------------------------*/ -/** +/* * Delay the CPU for up to 65535*(4000000/F_CPU) microseconds. * Copied from _delay_loop_2 in AVR library delay_basic.h, 4 clocks per loop. * For accurate short delays, inline _delay_loop_2 in the caller, use a constant @@ -193,44 +193,44 @@ my_delay_loop_2(uint16_t __count) ); } void -clock_delay_usec(uint16_t howlong) +clock_delay_usec(uint16_t dt) { #if 0 /* Accurate delay at any frequency, but introduces a 64 bit intermediate * and has a 279 clock overhead. */ - if(howlong<=(uint16_t)(279000000UL/F_CPU)) return; - howlong-=(uint16_t) (279000000UL/F_CPU); - my_delay_loop_2(((uint64_t)(howlong) * (uint64_t) F_CPU) / 4000000ULL); + if(dt<=(uint16_t)(279000000UL/F_CPU)) return; + dt-=(uint16_t) (279000000UL/F_CPU); + my_delay_loop_2(((uint64_t)(dt) * (uint64_t) F_CPU) / 4000000ULL); /* Remaining numbers tweaked for the breakpoint CPU frequencies */ /* Add other frequencies as necessary */ #elif F_CPU>=16000000UL - if(howlong<1) return; - my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000))); + if(dt<1) return; + my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000))); #elif F_CPU >= 12000000UL - if(howlong<2) return; - howlong-=(uint16_t) (3*12000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/3250000))); + if(dt<2) return; + dt-=(uint16_t) (3*12000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/3250000))); #elif F_CPU >= 8000000UL - if(howlong<4) return; - howlong-=(uint16_t) (3*8000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2); + if(dt<4) return; + dt-=(uint16_t) (3*8000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2); #elif F_CPU >= 4000000UL - if(howlong<5) return; - howlong-=(uint16_t) (4*4000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/2000000))/2); + if(dt<5) return; + dt-=(uint16_t) (4*4000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/2000000))/2); #elif F_CPU >= 2000000UL - if(howlong<11) return; - howlong-=(uint16_t) (10*2000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4); + if(dt<11) return; + dt-=(uint16_t) (10*2000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4); #elif F_CPU >= 1000000UL - if(howlong<=17) return; - howlong-=(uint16_t) (17*1000000/F_CPU); - my_delay_loop_2((howlong*(uint16_t)(F_CPU/1000000))/4); + if(dt<=17) return; + dt-=(uint16_t) (17*1000000/F_CPU); + my_delay_loop_2((dt*(uint16_t)(F_CPU/1000000))/4); #else - howlong >> 5; - if (howlong < 1) return; - my_delay_loop_2(howlong); + dt >> 5; + if (dt < 1) return; + my_delay_loop_2(dt); #endif } #if 0 @@ -250,7 +250,7 @@ clock_delay(unsigned int howlong) /*---------------------------------------------------------------------------*/ /** * Delay up to 65535 milliseconds. - * \param dt How many milliseconds to delay. + * \param howlong How many milliseconds to delay. * * Neither interrupts nor the watchdog timer is disabled over the delay. * Platforms are not required to implement this call. @@ -279,7 +279,7 @@ clock_delay_msec(uint16_t howlong) /*---------------------------------------------------------------------------*/ /** * Adjust the system current clock time. - * \param dt How many ticks to add + * \param howmany How many ticks to add * * Typically used to add ticks after an MCU sleep * clock_seconds will increment if necessary to reflect the tick addition. diff --git a/cpu/cc2430/dev/clock.c b/cpu/cc2430/dev/clock.c index c0b8f2c9d..1fc781b1b 100644 --- a/cpu/cc2430/dev/clock.c +++ b/cpu/cc2430/dev/clock.c @@ -54,7 +54,7 @@ static unsigned long timer_value; static volatile CC_AT_DATA clock_time_t count = 0; /* Uptime in ticks */ static volatile CC_AT_DATA clock_time_t seconds = 0; /* Uptime in secs */ /*---------------------------------------------------------------------------*/ -/** +/* * Each iteration is ~1.0xy usec, so this function delays for roughly len usec */ void @@ -68,7 +68,7 @@ clock_delay_usec(uint16_t len) ENABLE_INTERRUPTS(); } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of ~8 ms (a tick) */ void diff --git a/cpu/cc2538/clock.c b/cpu/cc2538/clock.c index 98abdf2e3..b453f2aa3 100644 --- a/cpu/cc2538/clock.c +++ b/cpu/cc2538/clock.c @@ -136,16 +136,15 @@ clock_wait(clock_time_t i) while(clock_time() - start < (clock_time_t)i); } /*---------------------------------------------------------------------------*/ -/** - * \brief Arch-specific implementation of clock_delay_usec for the cc2538 - * \param len Delay \e len uSecs +/* + * Arch-specific implementation of clock_delay_usec for the cc2538 * * See clock_init() for GPT0 Timer A's configuration */ void -clock_delay_usec(uint16_t len) +clock_delay_usec(uint16_t dt) { - REG(GPT_0_BASE | GPTIMER_TAILR) = len; + REG(GPT_0_BASE | GPTIMER_TAILR) = dt; REG(GPT_0_BASE | GPTIMER_CTL) |= GPTIMER_CTL_TAEN; /* One-Shot mode: TAEN will be cleared when the timer reaches 0 */ diff --git a/cpu/cc2538/cpu.h b/cpu/cc2538/cpu.h index e8cd7e282..51ffa9075 100644 --- a/cpu/cc2538/cpu.h +++ b/cpu/cc2538/cpu.h @@ -29,12 +29,21 @@ * OF THE POSSIBILITY OF SUCH DAMAGE. */ /** - * \addtogroup cc2538 + * \addtogroup platform + * @{ + * + * \defgroup cc2538-platforms TI cc2538-powered platforms + * + * Documentation for all platforms powered by the TI cc2538 System-on-Chip + * @{ + * + * \defgroup cc2538 The TI cc2538 System-on-Chip + * CPU-Specific functionality - available to all cc2538-based platforms * @{ * * \defgroup cc2538-cpu cc2538 CPU * - * cc2538 CPU-specific functions for the cc2538 core + * CPU-specific functions for the cc2538 core * @{ * * \file @@ -60,6 +69,8 @@ unsigned long cpu_cpsie(void); #endif /* CPU_H_ */ /** + * @} + * @} * @} * @} */ diff --git a/cpu/cc2538/dbg.h b/cpu/cc2538/dbg.h index d861cadd7..2e283c0b1 100644 --- a/cpu/cc2538/dbg.h +++ b/cpu/cc2538/dbg.h @@ -34,7 +34,7 @@ * * \defgroup cc2538-char-io cc2538 Character I/O * - * cc2538 CPU-specific functions for debugging and SLIP I/O + * CPU-specific functions for debugging and SLIP I/O * * On the cc2538, character I/O can be directed over USB or UART. This is * controlled by a series of configuration directives: diff --git a/cpu/cc2538/dev/cc2538-rf.c b/cpu/cc2538/dev/cc2538-rf.c index f20354cc2..e8ec81309 100644 --- a/cpu/cc2538/dev/cc2538-rf.c +++ b/cpu/cc2538/dev/cc2538-rf.c @@ -122,6 +122,7 @@ static const uint8_t magic[] = { 0x53, 0x6E, 0x69, 0x66 }; /** Snif */ #endif /*---------------------------------------------------------------------------*/ static uint8_t rf_flags; +static uint8_t rf_channel = CC2538_RF_CHANNEL; static int on(void); static int off(void); @@ -186,10 +187,22 @@ set_channel(uint8_t channel) } /* Changes to FREQCTRL take effect after the next recalibration */ - off(); + + /* If we are off, save state, otherwise switch off and save state */ + if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { + rf_flags |= WAS_OFF; + } else { + rf_flags &= ~WAS_OFF; + off(); + } REG(RFCORE_XREG_FREQCTRL) = (CC2538_RF_CHANNEL_MIN + (channel - CC2538_RF_CHANNEL_MIN) * CC2538_RF_CHANNEL_SPACING); - on(); + /* switch radio back on only if radio was on before - otherwise will turn on radio foor sleepy nodes */ + if((rf_flags & WAS_OFF) != WAS_OFF) { + on(); + } + + rf_channel = channel; return (int8_t) channel; } @@ -445,7 +458,7 @@ init(void) /* Set TX Power */ REG(RFCORE_XREG_TXPOWER) = CC2538_RF_TX_POWER; - set_channel(CC2538_RF_CHANNEL); + set_channel(rf_channel); /* Acknowledge RF interrupts, FIFOP only */ REG(RFCORE_XREG_RFIRQM0) |= RFCORE_XREG_RFIRQM0_FIFOP; @@ -951,10 +964,21 @@ PROCESS_THREAD(cc2538_rf_process, ev, data) /* If we were polled due to an RF error, reset the transceiver */ if(rf_flags & RF_MUST_RESET) { + uint8_t was_on; rf_flags = 0; + /* save state so we know if to switch on again after re-init */ + if((REG(RFCORE_XREG_FSMSTAT0) & RFCORE_XREG_FSMSTAT0_FSM_FFCTRL_STATE) == 0) { + was_on = 0; + } else { + was_on = 1; + } off(); init(); + if(was_on) { + /* switch back on */ + on(); + } } } diff --git a/cpu/cc2538/dev/gpio.h b/cpu/cc2538/dev/gpio.h index 8a61f668b..3f93633a1 100644 --- a/cpu/cc2538/dev/gpio.h +++ b/cpu/cc2538/dev/gpio.h @@ -117,6 +117,20 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); /** \brief Set pins with PIN_MASK of port with PORT_BASE to value. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 + * \param value The new value to write to the register. Only pins specified + * by PIN_MASK will be set. + * + * \note The outcome of this macro invocation will be to write to the register + * a new value for multiple pins. For that reason, the value argument cannot be + * a simple 0 or 1. Instead, it must be the value corresponding to the pins that + * you wish to set. + * + * Thus, if you only want to set a single pin (e.g. pin 2), do \e not pass 1, + * but you must pass 0x04 instead (1 << 2). This may seem counter-intuitive at + * first glance, but it allows a single invocation of this macro to set + * multiple pins in one go if so desired. For example, you can set pins 3 and 1 + * and the same time clear pins 2 and 0. To do so, pass 0x0F as the PIN_MASK + * and then use 0x0A as the value ((1 << 3) | (1 << 1) for pins 3 and 1) */ #define GPIO_WRITE_PIN(PORT_BASE, PIN_MASK, value) \ do { REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) = (value); } while(0) @@ -124,6 +138,12 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); /** \brief Read pins with PIN_MASK of port with PORT_BASE. * \param PORT_BASE GPIO Port register offset * \param PIN_MASK Pin number mask. Pin 0: 0x01, Pin 1: 0x02 ... Pin 7: 0x80 + * \return The value of the pins specified by PIN_MASK + * + * This macro will \e not return 0 or 1. Instead, it will return the values of + * the pins specified by PIN_MASK ORd together. Thus, if you pass 0xC3 + * (0x80 | 0x40 | 0x02 | 0x01) as the PIN_MASK and pins 7 and 0 are high, + * the macro will return 0x81. */ #define GPIO_READ_PIN(PORT_BASE, PIN_MASK) \ REG(((PORT_BASE) | GPIO_DATA) + ((PIN_MASK) << 2)) @@ -261,7 +281,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); /** * \brief Converts a pin number to a pin mask - * \param The pin number in the range [0..7] + * \param PIN The pin number in the range [0..7] * \return A pin mask which can be used as the PIN_MASK argument of the macros * in this category */ @@ -269,7 +289,7 @@ typedef void (* gpio_callback_t)(uint8_t port, uint8_t pin); /** * \brief Converts a port number to the port base address - * \param The port number in the range 0 - 3. Likely GPIO_X_NUM. + * \param PORT The port number in the range 0 - 3. Likely GPIO_X_NUM. * \return The base address for the registers corresponding to that port * number. */ diff --git a/cpu/cc2538/dev/ioc.h b/cpu/cc2538/dev/ioc.h index 34fcce809..7fad9d275 100644 --- a/cpu/cc2538/dev/ioc.h +++ b/cpu/cc2538/dev/ioc.h @@ -34,7 +34,7 @@ * * \defgroup cc2538-ioc cc2538 I/O Control * - * cc2538 I/O Control Module + * Driver for the cc2538 I/O Control Module * @{ * * \file diff --git a/cpu/cc2538/dev/scb.h b/cpu/cc2538/dev/scb.h index 53b1535e4..e91951ecb 100644 --- a/cpu/cc2538/dev/scb.h +++ b/cpu/cc2538/dev/scb.h @@ -32,7 +32,9 @@ * \addtogroup cc2538 * @{ * - * \defgroup cc2538-scb cc2538 System Control Block + * \defgroup cc2538-scb cc2538 System Control Block (SCB) + * + * Offsets and bit definitions for SCB registers * @{ * * \file diff --git a/cpu/cc2538/dev/spi.c b/cpu/cc2538/dev/spi.c index 586c738bc..bff1783b5 100644 --- a/cpu/cc2538/dev/spi.c +++ b/cpu/cc2538/dev/spi.c @@ -31,7 +31,7 @@ * @{ * * \file - * Implementation of the cc2538 SPI peripheral + * Implementation of the cc2538 SPI peripheral driver */ #include "contiki.h" #include "reg.h" @@ -52,7 +52,7 @@ /** * \brief Initialize the SPI bus. * - * This SPI init() function uses the following #defines to set the pins: + * This SPI init() function uses the following defines to set the pins: * SPI_CLK_PORT SPI_CLK_PIN * SPI_MOSI_PORT SPI_MOSI_PIN * SPI_MISO_PORT SPI_MISO_PIN @@ -126,7 +126,9 @@ spi_disable(void) REG(SYS_CTRL_RCGCSSI) &= ~1; } /*---------------------------------------------------------------------------*/ -void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity, uint32_t clock_phase, uint32_t data_size) +void +spi_set_mode(uint32_t frame_format, uint32_t clock_polarity, + uint32_t clock_phase, uint32_t data_size) { /* Disable the SSI peripheral to configure it */ REG(SSI0_BASE + SSI_CR1) = 0; diff --git a/cpu/cc2538/dev/sys-ctrl.h b/cpu/cc2538/dev/sys-ctrl.h index f63fd5a50..3c9885a89 100644 --- a/cpu/cc2538/dev/sys-ctrl.h +++ b/cpu/cc2538/dev/sys-ctrl.h @@ -32,7 +32,7 @@ * \addtogroup cc2538 * @{ * - * \defgroup cc2538-sys-ctrl cc2538 System Control + * \defgroup cc2538-sys-ctrl cc2538 System Control (SysCtrl) * * Driver for the cc2538 System Control Module * @{ diff --git a/cpu/cc2538/dev/udma.h b/cpu/cc2538/dev/udma.h index a6ddfc199..79cd58c20 100644 --- a/cpu/cc2538/dev/udma.h +++ b/cpu/cc2538/dev/udma.h @@ -560,12 +560,13 @@ void udma_init(void); /** * \brief Sets the channels source address * \param channel The channel as a value in [0 , UDMA_CONF_MAX_CHANNEL] - * \param + * \param src_end The source's end address */ void udma_set_channel_src(uint8_t channel, uint32_t src_end); /** - * \brief + * \brief Sets the channel's destination address + * \param dst_end The destination's end address * \param channel The channel as a value in [0 , UDMA_CONF_MAX_CHANNEL] */ void udma_set_channel_dst(uint8_t channel, uint32_t dst_end); diff --git a/cpu/cc2538/spi-arch.h b/cpu/cc2538/spi-arch.h index 53d7fe78d..46d8d3bf4 100644 --- a/cpu/cc2538/spi-arch.h +++ b/cpu/cc2538/spi-arch.h @@ -27,16 +27,13 @@ * SUCH DAMAGE. */ /** - * \addtogroup cc2538 + * \addtogroup cc2538-spi * @{ * - * Implementation of the low-level SPI primitives such as waiting for the TX - * FIFO to be ready, inserting into the TX FIFO, etc. - * @{ - */ -/** * \file - * Header file for the cc2538 SPI commands + * Header file for the cc2538 SPI driver, including macros for the + * implementation of the low-level SPI primitives such as waiting for the TX + * FIFO to be ready, inserting into the TX FIFO, etc. */ #ifndef SPI_ARCH_H_ #define SPI_ARCH_H_ @@ -121,6 +118,5 @@ void spi_set_mode(uint32_t frame_format, uint32_t clock_polarity, #endif /* SPI_ARCH_H_ */ /** - * @} * @} */ diff --git a/cpu/cc253x/dev/clock.c b/cpu/cc253x/dev/clock.c index ff1c4cf4a..e78635361 100644 --- a/cpu/cc253x/dev/clock.c +++ b/cpu/cc253x/dev/clock.c @@ -70,7 +70,7 @@ clock_delay_usec(uint16_t len) ENABLE_INTERRUPTS(); } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of ~8 ms (a tick) */ void diff --git a/cpu/cc253x/dev/uart0.c b/cpu/cc253x/dev/uart0.c index a6a358a18..f5dc35640 100644 --- a/cpu/cc253x/dev/uart0.c +++ b/cpu/cc253x/dev/uart0.c @@ -39,7 +39,7 @@ uart0_init() #else PERCFG &= ~PERCFG_U0CFG; /* alternative port 1 = P0.5-2 */ #ifdef UART0_RTSCTS - P0SEL |= 0x20 | 0x10; /* peripheral select for TX and RX */ + P0SEL |= 0x3C; /* peripheral select for RTS and CTS, TX, RX */ #else P0SEL |= 0x0C; /* peripheral select for TX and RX */ P0 &= ~0x20; /* RTS down */ diff --git a/cpu/mc1322x/clock.c b/cpu/mc1322x/clock.c index 611a90251..ac70dfcf5 100644 --- a/cpu/mc1322x/clock.c +++ b/cpu/mc1322x/clock.c @@ -97,7 +97,7 @@ clock_wait(clock_time_t t) while ((signed long)(current_clock - endticks) < 0) {;} } /*---------------------------------------------------------------------------*/ -/** +/* * Delay the CPU for up to 65535 microseconds. * Use the 250KHz MACA clock for longer delays to avoid interrupt effects. * However that can't be used if the radio is being power cycled! @@ -118,7 +118,7 @@ clock_delay_usec(uint16_t howlong) while(--i); } /*---------------------------------------------------------------------------*/ -/** +/* * Delay the CPU for up to 65535 milliseconds. The watchdog is NOT disabled. */ void @@ -127,7 +127,7 @@ clock_delay_msec(uint16_t howlong) while(howlong--) clock_delay_usec(1000); } /*---------------------------------------------------------------------------*/ -/** +/* * Legacy delay. The original clock_delay for the msp430 used a granularity * of 2.83 usec. This approximates that delay for values up to 1456 usec. * (The largest core call in leds.c uses 400). @@ -139,7 +139,7 @@ clock_delay(unsigned int howlong) clock_delay_usec((283*howlong)/100); } /*---------------------------------------------------------------------------*/ -/** +/* * Adjust clock ticks after a cpu sleep. */ void clock_adjust_ticks(clock_time_t howmany) { diff --git a/cpu/msp430/f1xxx/clock.c b/cpu/msp430/f1xxx/clock.c index b99827c04..b81bb7498 100644 --- a/cpu/msp430/f1xxx/clock.c +++ b/cpu/msp430/f1xxx/clock.c @@ -195,7 +195,7 @@ clock_delay(unsigned int i) } } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of 10 ms. * */ diff --git a/cpu/msp430/f5xxx/clock.c b/cpu/msp430/f5xxx/clock.c index b0047a9e6..1def811e6 100644 --- a/cpu/msp430/f5xxx/clock.c +++ b/cpu/msp430/f5xxx/clock.c @@ -192,7 +192,7 @@ clock_delay(unsigned int i) } } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of 10 ms. * */ diff --git a/cpu/stm32w108/clock.c b/cpu/stm32w108/clock.c index f4a17ad53..5e3464d16 100644 --- a/cpu/stm32w108/clock.c +++ b/cpu/stm32w108/clock.c @@ -113,7 +113,7 @@ clock_delay(unsigned int i) } } /*---------------------------------------------------------------------------*/ -/** +/* * Wait for a multiple of 1 ms. */ void diff --git a/doc/Doxyfile b/doc/Doxyfile index cd6b1235b..371ada4d5 100644 --- a/doc/Doxyfile +++ b/doc/Doxyfile @@ -1,110 +1,129 @@ -# Doxyfile 1.8.1.2 +# Doxyfile 1.8.8 # This file describes the settings to be used by the documentation system # doxygen (www.doxygen.org) for a project. # -# All text after a hash (#) is considered a comment and will be ignored. +# All text after a double hash (##) is considered a comment and is placed in +# front of the TAG it is preceding. +# +# All text after a single hash (#) is considered a comment and will be ignored. # The format is: -# TAG = value [value, ...] -# For lists items can also be appended using: -# TAG += value [value, ...] -# Values that contain spaces should be placed between quotes (" "). +# TAG = value [value, ...] +# For lists, items can also be appended using: +# TAG += value [value, ...] +# Values that contain spaces should be placed between quotes (\" \"). #--------------------------------------------------------------------------- # Project related configuration options #--------------------------------------------------------------------------- # This tag specifies the encoding used for all characters in the config file -# that follow. The default is UTF-8 which is also the encoding used for all -# text before the first occurrence of this tag. Doxygen uses libiconv (or the -# iconv built into libc) for the transcoding. See -# http://www.gnu.org/software/libiconv for the list of possible encodings. +# that follow. The default is UTF-8 which is also the encoding used for all text +# before the first occurrence of this tag. Doxygen uses libiconv (or the iconv +# built into libc) for the transcoding. See http://www.gnu.org/software/libiconv +# for the list of possible encodings. +# The default value is: UTF-8. DOXYFILE_ENCODING = UTF-8 -# The PROJECT_NAME tag is a single word (or sequence of words) that should -# identify the project. Note that if you do not use Doxywizard you need -# to put quotes around the project name if it contains spaces. +# The PROJECT_NAME tag is a single word (or a sequence of words surrounded by +# double-quotes, unless you are using Doxywizard) that should identify the +# project for which the documentation is generated. This name is used in the +# title of most generated pages and in a few other places. +# The default value is: My Project. PROJECT_NAME = "Contiki 3.x" -# The PROJECT_NUMBER tag can be used to enter a project or revision number. -# This could be handy for archiving the generated documentation or -# if some version control system is used. +# The PROJECT_NUMBER tag can be used to enter a project or revision number. This +# could be handy for archiving the generated documentation or if some version +# control system is used. PROJECT_NUMBER = # Using the PROJECT_BRIEF tag one can provide an optional one line description -# for a project that appears at the top of each page and should give viewer -# a quick idea about the purpose of the project. Keep the description short. +# for a project that appears at the top of each page and should give viewer a +# quick idea about the purpose of the project. Keep the description short. PROJECT_BRIEF = -# With the PROJECT_LOGO tag one can specify an logo or icon that is -# included in the documentation. The maximum height of the logo should not -# exceed 55 pixels and the maximum width should not exceed 200 pixels. -# Doxygen will copy the logo to the output directory. +# With the PROJECT_LOGO tag one can specify an logo or icon that is included in +# the documentation. The maximum height of the logo should not exceed 55 pixels +# and the maximum width should not exceed 200 pixels. Doxygen will copy the logo +# to the output directory. PROJECT_LOGO = -# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) -# base path where the generated documentation will be put. -# If a relative path is entered, it will be relative to the location -# where doxygen was started. If left blank the current directory will be used. +# The OUTPUT_DIRECTORY tag is used to specify the (relative or absolute) path +# into which the generated documentation will be written. If a relative path is +# entered, it will be relative to the location where doxygen was started. If +# left blank the current directory will be used. OUTPUT_DIRECTORY = . -# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create -# 4096 sub-directories (in 2 levels) under the output directory of each output -# format and will distribute the generated files over these directories. -# Enabling this option can be useful when feeding doxygen a huge amount of -# source files, where putting all generated files in the same directory would -# otherwise cause performance problems for the file system. +# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create 4096 sub- +# directories (in 2 levels) under the output directory of each output format and +# will distribute the generated files over these directories. Enabling this +# option can be useful when feeding doxygen a huge amount of source files, where +# putting all generated files in the same directory would otherwise causes +# performance problems for the file system. +# The default value is: NO. CREATE_SUBDIRS = NO +# If the ALLOW_UNICODE_NAMES tag is set to YES, doxygen will allow non-ASCII +# characters to appear in the names of generated files. If set to NO, non-ASCII +# characters will be escaped, for example _xE3_x81_x84 will be used for Unicode +# U+3044. +# The default value is: NO. + +ALLOW_UNICODE_NAMES = NO + # The OUTPUT_LANGUAGE tag is used to specify the language in which all # documentation generated by doxygen is written. Doxygen will use this # information to generate all constant output in the proper language. -# The default language is English, other supported languages are: -# Afrikaans, Arabic, Brazilian, Catalan, Chinese, Chinese-Traditional, -# Croatian, Czech, Danish, Dutch, Esperanto, Farsi, Finnish, French, German, -# Greek, Hungarian, Italian, Japanese, Japanese-en (Japanese with English -# messages), Korean, Korean-en, Lithuanian, Norwegian, Macedonian, Persian, -# Polish, Portuguese, Romanian, Russian, Serbian, Serbian-Cyrillic, Slovak, -# Slovene, Spanish, Swedish, Ukrainian, and Vietnamese. +# Possible values are: Afrikaans, Arabic, Armenian, Brazilian, Catalan, Chinese, +# Chinese-Traditional, Croatian, Czech, Danish, Dutch, English (United States), +# Esperanto, Farsi (Persian), Finnish, French, German, Greek, Hungarian, +# Indonesian, Italian, Japanese, Japanese-en (Japanese with English messages), +# Korean, Korean-en (Korean with English messages), Latvian, Lithuanian, +# Macedonian, Norwegian, Persian (Farsi), Polish, Portuguese, Romanian, Russian, +# Serbian, Serbian-Cyrillic, Slovak, Slovene, Spanish, Swedish, Turkish, +# Ukrainian and Vietnamese. +# The default value is: English. OUTPUT_LANGUAGE = English -# If the BRIEF_MEMBER_DESC tag is set to YES (the default) Doxygen will -# include brief member descriptions after the members that are listed in -# the file and class documentation (similar to JavaDoc). -# Set to NO to disable this. +# If the BRIEF_MEMBER_DESC tag is set to YES doxygen will include brief member +# descriptions after the members that are listed in the file and class +# documentation (similar to Javadoc). Set to NO to disable this. +# The default value is: YES. BRIEF_MEMBER_DESC = YES -# If the REPEAT_BRIEF tag is set to YES (the default) Doxygen will prepend -# the brief description of a member or function before the detailed description. -# Note: if both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the +# If the REPEAT_BRIEF tag is set to YES doxygen will prepend the brief +# description of a member or function before the detailed description +# +# Note: If both HIDE_UNDOC_MEMBERS and BRIEF_MEMBER_DESC are set to NO, the # brief descriptions will be completely suppressed. +# The default value is: YES. REPEAT_BRIEF = YES -# This tag implements a quasi-intelligent brief description abbreviator -# that is used to form the text in various listings. Each string -# in this list, if found as the leading text of the brief description, will be -# stripped from the text and the result after processing the whole list, is -# used as the annotated text. Otherwise, the brief description is used as-is. -# If left blank, the following values are used ("$name" is automatically -# replaced with the name of the entity): "The $name class" "The $name widget" -# "The $name file" "is" "provides" "specifies" "contains" -# "represents" "a" "an" "the" +# This tag implements a quasi-intelligent brief description abbreviator that is +# used to form the text in various listings. Each string in this list, if found +# as the leading text of the brief description, will be stripped from the text +# and the result, after processing the whole list, is used as the annotated +# text. Otherwise, the brief description is used as-is. If left blank, the +# following values are used ($name is automatically replaced with the name of +# the entity):The $name class, The $name widget, The $name file, is, provides, +# specifies, contains, represents, a, an and the. ABBREVIATE_BRIEF = # If the ALWAYS_DETAILED_SEC and REPEAT_BRIEF tags are both set to YES then -# Doxygen will generate a detailed section even if there is only a brief +# doxygen will generate a detailed section even if there is only a brief # description. +# The default value is: NO. ALWAYS_DETAILED_SEC = NO @@ -112,169 +131,207 @@ ALWAYS_DETAILED_SEC = NO # inherited members of a class in the documentation of that class as if those # members were ordinary class members. Constructors, destructors and assignment # operators of the base classes will not be shown. +# The default value is: NO. INLINE_INHERITED_MEMB = NO -# If the FULL_PATH_NAMES tag is set to YES then Doxygen will prepend the full -# path before files name in the file list and in the header files. If set -# to NO the shortest path that makes the file name unique will be used. +# If the FULL_PATH_NAMES tag is set to YES doxygen will prepend the full path +# before files name in the file list and in the header files. If set to NO the +# shortest path that makes the file name unique will be used +# The default value is: YES. FULL_PATH_NAMES = YES -# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag -# can be used to strip a user-defined part of the path. Stripping is -# only done if one of the specified strings matches the left-hand part of -# the path. The tag can be used to show relative paths in the file list. -# If left blank the directory from which doxygen is run is used as the -# path to strip. +# The STRIP_FROM_PATH tag can be used to strip a user-defined part of the path. +# Stripping is only done if one of the specified strings matches the left-hand +# part of the path. The tag can be used to show relative paths in the file list. +# If left blank the directory from which doxygen is run is used as the path to +# strip. +# +# Note that you can specify absolute paths here, but also relative paths, which +# will be relative from the directory where doxygen is started. +# This tag requires that the tag FULL_PATH_NAMES is set to YES. STRIP_FROM_PATH = $(docroot) -# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of -# the path mentioned in the documentation of a class, which tells -# the reader which header file to include in order to use a class. -# If left blank only the name of the header file containing the class -# definition is used. Otherwise one should specify the include paths that -# are normally passed to the compiler using the -I flag. +# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of the +# path mentioned in the documentation of a class, which tells the reader which +# header file to include in order to use a class. If left blank only the name of +# the header file containing the class definition is used. Otherwise one should +# specify the list of include paths that are normally passed to the compiler +# using the -I flag. STRIP_FROM_INC_PATH = $(docroot) -# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter -# (but less readable) file names. This can be useful if your file system -# doesn't support long names like on DOS, Mac, or CD-ROM. +# If the SHORT_NAMES tag is set to YES, doxygen will generate much shorter (but +# less readable) file names. This can be useful is your file systems doesn't +# support long names like on DOS, Mac, or CD-ROM. +# The default value is: NO. SHORT_NAMES = YES -# If the JAVADOC_AUTOBRIEF tag is set to YES then Doxygen -# will interpret the first line (until the first dot) of a JavaDoc-style -# comment as the brief description. If set to NO, the JavaDoc -# comments will behave just like regular Qt-style comments -# (thus requiring an explicit @brief command for a brief description.) +# If the JAVADOC_AUTOBRIEF tag is set to YES then doxygen will interpret the +# first line (until the first dot) of a Javadoc-style comment as the brief +# description. If set to NO, the Javadoc-style will behave just like regular Qt- +# style comments (thus requiring an explicit @brief command for a brief +# description.) +# The default value is: NO. JAVADOC_AUTOBRIEF = YES -# If the QT_AUTOBRIEF tag is set to YES then Doxygen will -# interpret the first line (until the first dot) of a Qt-style -# comment as the brief description. If set to NO, the comments -# will behave just like regular Qt-style comments (thus requiring -# an explicit \brief command for a brief description.) +# If the QT_AUTOBRIEF tag is set to YES then doxygen will interpret the first +# line (until the first dot) of a Qt-style comment as the brief description. If +# set to NO, the Qt-style will behave just like regular Qt-style comments (thus +# requiring an explicit \brief command for a brief description.) +# The default value is: NO. QT_AUTOBRIEF = NO -# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make Doxygen -# treat a multi-line C++ special comment block (i.e. a block of //! or /// -# comments) as a brief description. This used to be the default behaviour. -# The new default is to treat a multi-line C++ comment block as a detailed -# description. Set this tag to YES if you prefer the old behaviour instead. +# The MULTILINE_CPP_IS_BRIEF tag can be set to YES to make doxygen treat a +# multi-line C++ special comment block (i.e. a block of //! or /// comments) as +# a brief description. This used to be the default behavior. The new default is +# to treat a multi-line C++ comment block as a detailed description. Set this +# tag to YES if you prefer the old behavior instead. +# +# Note that setting this tag to YES also means that rational rose comments are +# not recognized any more. +# The default value is: NO. MULTILINE_CPP_IS_BRIEF = NO -# If the INHERIT_DOCS tag is set to YES (the default) then an undocumented -# member inherits the documentation from any documented member that it -# re-implements. +# If the INHERIT_DOCS tag is set to YES then an undocumented member inherits the +# documentation from any documented member that it re-implements. +# The default value is: YES. INHERIT_DOCS = YES -# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce -# a new page for each member. If set to NO, the documentation of a member will -# be part of the file/class/namespace that contains it. +# If the SEPARATE_MEMBER_PAGES tag is set to YES, then doxygen will produce a +# new page for each member. If set to NO, the documentation of a member will be +# part of the file/class/namespace that contains it. +# The default value is: NO. SEPARATE_MEMBER_PAGES = NO -# The TAB_SIZE tag can be used to set the number of spaces in a tab. -# Doxygen uses this value to replace tabs by spaces in code fragments. +# The TAB_SIZE tag can be used to set the number of spaces in a tab. Doxygen +# uses this value to replace tabs by spaces in code fragments. +# Minimum value: 1, maximum value: 16, default value: 4. TAB_SIZE = 8 -# This tag can be used to specify a number of aliases that acts -# as commands in the documentation. An alias has the form "name=value". -# For example adding "sideeffect=\par Side Effects:\n" will allow you to -# put the command \sideeffect (or @sideeffect) in the documentation, which -# will result in a user-defined paragraph with heading "Side Effects:". -# You can put \n's in the value part of an alias to insert newlines. +# This tag can be used to specify a number of aliases that act as commands in +# the documentation. An alias has the form: +# name=value +# For example adding +# "sideeffect=@par Side Effects:\n" +# will allow you to put the command \sideeffect (or @sideeffect) in the +# documentation, which will result in a user-defined paragraph with heading +# "Side Effects:". You can put \n's in the value part of an alias to insert +# newlines. ALIASES = # This tag can be used to specify a number of word-keyword mappings (TCL only). -# A mapping has the form "name=value". For example adding -# "class=itcl::class" will allow you to use the command class in the -# itcl::class meaning. +# A mapping has the form "name=value". For example adding "class=itcl::class" +# will allow you to use the command class in the itcl::class meaning. TCL_SUBST = -# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C -# sources only. Doxygen will then generate output that is more tailored for C. -# For instance, some of the names that are used will be different. The list -# of all members will be omitted, etc. +# Set the OPTIMIZE_OUTPUT_FOR_C tag to YES if your project consists of C sources +# only. Doxygen will then generate output that is more tailored for C. For +# instance, some of the names that are used will be different. The list of all +# members will be omitted, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_FOR_C = YES -# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java -# sources only. Doxygen will then generate output that is more tailored for -# Java. For instance, namespaces will be presented as packages, qualified -# scopes will look different, etc. +# Set the OPTIMIZE_OUTPUT_JAVA tag to YES if your project consists of Java or +# Python sources only. Doxygen will then generate output that is more tailored +# for that language. For instance, namespaces will be presented as packages, +# qualified scopes will look different, etc. +# The default value is: NO. OPTIMIZE_OUTPUT_JAVA = NO # Set the OPTIMIZE_FOR_FORTRAN tag to YES if your project consists of Fortran -# sources only. Doxygen will then generate output that is more tailored for -# Fortran. +# sources. Doxygen will then generate output that is tailored for Fortran. +# The default value is: NO. OPTIMIZE_FOR_FORTRAN = NO # Set the OPTIMIZE_OUTPUT_VHDL tag to YES if your project consists of VHDL -# sources. Doxygen will then generate output that is tailored for -# VHDL. +# sources. Doxygen will then generate output that is tailored for VHDL. +# The default value is: NO. OPTIMIZE_OUTPUT_VHDL = NO # Doxygen selects the parser to use depending on the extension of the files it -# parses. With this tag you can assign which parser to use for a given extension. -# Doxygen has a built-in mapping, but you can override or extend it using this -# tag. The format is ext=language, where ext is a file extension, and language -# is one of the parsers supported by doxygen: IDL, Java, Javascript, CSharp, C, -# C++, D, PHP, Objective-C, Python, Fortran, VHDL, C, C++. For instance to make -# doxygen treat .inc files as Fortran files (default is PHP), and .f files as C -# (default is Fortran), use: inc=Fortran f=C. Note that for custom extensions -# you also need to set FILE_PATTERNS otherwise the files are not read by doxygen. +# parses. With this tag you can assign which parser to use for a given +# extension. Doxygen has a built-in mapping, but you can override or extend it +# using this tag. The format is ext=language, where ext is a file extension, and +# language is one of the parsers supported by doxygen: IDL, Java, Javascript, +# C#, C, C++, D, PHP, Objective-C, Python, Fortran (fixed format Fortran: +# FortranFixed, free formatted Fortran: FortranFree, unknown formatted Fortran: +# Fortran. In the later case the parser tries to guess whether the code is fixed +# or free formatted code, this is the default for Fortran type files), VHDL. For +# instance to make doxygen treat .inc files as Fortran files (default is PHP), +# and .f files as C (default is Fortran), use: inc=Fortran f=C. +# +# Note For files without extension you can use no_extension as a placeholder. +# +# Note that for custom extensions you also need to set FILE_PATTERNS otherwise +# the files are not read by doxygen. EXTENSION_MAPPING = -# If MARKDOWN_SUPPORT is enabled (the default) then doxygen pre-processes all -# comments according to the Markdown format, which allows for more readable +# If the MARKDOWN_SUPPORT tag is enabled then doxygen pre-processes all comments +# according to the Markdown format, which allows for more readable # documentation. See http://daringfireball.net/projects/markdown/ for details. -# The output of markdown processing is further processed by doxygen, so you -# can mix doxygen, HTML, and XML commands with Markdown formatting. -# Disable only in case of backward compatibilities issues. +# The output of markdown processing is further processed by doxygen, so you can +# mix doxygen, HTML, and XML commands with Markdown formatting. Disable only in +# case of backward compatibilities issues. +# The default value is: YES. MARKDOWN_SUPPORT = YES +# When enabled doxygen tries to link words that correspond to documented +# classes, or namespaces to their corresponding documentation. Such a link can +# be prevented in individual cases by by putting a % sign in front of the word +# or globally by setting AUTOLINK_SUPPORT to NO. +# The default value is: YES. + +AUTOLINK_SUPPORT = YES + # If you use STL classes (i.e. std::string, std::vector, etc.) but do not want -# to include (a tag file for) the STL sources as input, then you should -# set this tag to YES in order to let doxygen match functions declarations and -# definitions whose arguments contain STL classes (e.g. func(std::string); v.s. -# func(std::string) {}). This also makes the inheritance and collaboration +# to include (a tag file for) the STL sources as input, then you should set this +# tag to YES in order to let doxygen match functions declarations and +# definitions whose arguments contain STL classes (e.g. func(std::string); +# versus func(std::string) {}). This also make the inheritance and collaboration # diagrams that involve STL classes more complete and accurate. +# The default value is: NO. BUILTIN_STL_SUPPORT = NO # If you use Microsoft's C++/CLI language, you should set this option to YES to # enable parsing support. +# The default value is: NO. CPP_CLI_SUPPORT = NO -# Set the SIP_SUPPORT tag to YES if your project consists of sip sources only. -# Doxygen will parse them like normal C++ but will assume all classes use public -# instead of private inheritance when no explicit protection keyword is present. +# Set the SIP_SUPPORT tag to YES if your project consists of sip (see: +# http://www.riverbankcomputing.co.uk/software/sip/intro) sources only. Doxygen +# will parse them like normal C++ but will assume all classes use public instead +# of private inheritance when no explicit protection keyword is present. +# The default value is: NO. SIP_SUPPORT = NO -# For Microsoft's IDL there are propget and propput attributes to indicate getter -# and setter methods for a property. Setting this option to YES (the default) -# will make doxygen replace the get and set methods by a property in the -# documentation. This will only work if the methods are indeed getting or -# setting a simple type. If this is not the case, or you want to show the -# methods anyway, you should set this option to NO. +# For Microsoft's IDL there are propget and propput attributes to indicate +# getter and setter methods for a property. Setting this option to YES will make +# doxygen to replace the get and set methods by a property in the documentation. +# This will only work if the methods are indeed getting or setting a simple +# type. If this is not the case, or you want to show the methods anyway, you +# should set this option to NO. +# The default value is: YES. IDL_PROPERTY_SUPPORT = YES @@ -282,67 +339,61 @@ IDL_PROPERTY_SUPPORT = YES # tag is set to YES, then doxygen will reuse the documentation of the first # member in the group (if any) for the other members of the group. By default # all members of a group must be documented explicitly. +# The default value is: NO. DISTRIBUTE_GROUP_DOC = NO -# Set the SUBGROUPING tag to YES (the default) to allow class member groups of -# the same type (for instance a group of public functions) to be put as a -# subgroup of that type (e.g. under the Public Functions section). Set it to -# NO to prevent subgrouping. Alternatively, this can be done per class using -# the \nosubgrouping command. +# Set the SUBGROUPING tag to YES to allow class member groups of the same type +# (for instance a group of public functions) to be put as a subgroup of that +# type (e.g. under the Public Functions section). Set it to NO to prevent +# subgrouping. Alternatively, this can be done per class using the +# \nosubgrouping command. +# The default value is: YES. SUBGROUPING = YES -# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and -# unions are shown inside the group in which they are included (e.g. using -# @ingroup) instead of on a separate page (for HTML and Man pages) or -# section (for LaTeX and RTF). +# When the INLINE_GROUPED_CLASSES tag is set to YES, classes, structs and unions +# are shown inside the group in which they are included (e.g. using \ingroup) +# instead of on a separate page (for HTML and Man pages) or section (for LaTeX +# and RTF). +# +# Note that this feature does not work in combination with +# SEPARATE_MEMBER_PAGES. +# The default value is: NO. INLINE_GROUPED_CLASSES = NO -# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and -# unions with only public data fields will be shown inline in the documentation -# of the scope in which they are defined (i.e. file, namespace, or group -# documentation), provided this scope is documented. If set to NO (the default), -# structs, classes, and unions are shown on a separate page (for HTML and Man -# pages) or section (for LaTeX and RTF). +# When the INLINE_SIMPLE_STRUCTS tag is set to YES, structs, classes, and unions +# with only public data fields or simple typedef fields will be shown inline in +# the documentation of the scope in which they are defined (i.e. file, +# namespace, or group documentation), provided this scope is documented. If set +# to NO, structs, classes, and unions are shown on a separate page (for HTML and +# Man pages) or section (for LaTeX and RTF). +# The default value is: NO. INLINE_SIMPLE_STRUCTS = NO -# When TYPEDEF_HIDES_STRUCT is enabled, a typedef of a struct, union, or enum -# is documented as struct, union, or enum with the name of the typedef. So +# When TYPEDEF_HIDES_STRUCT tag is enabled, a typedef of a struct, union, or +# enum is documented as struct, union, or enum with the name of the typedef. So # typedef struct TypeS {} TypeT, will appear in the documentation as a struct # with name TypeT. When disabled the typedef will appear as a member of a file, -# namespace, or class. And the struct will be named TypeS. This can typically -# be useful for C code in case the coding convention dictates that all compound +# namespace, or class. And the struct will be named TypeS. This can typically be +# useful for C code in case the coding convention dictates that all compound # types are typedef'ed and only the typedef is referenced, never the tag name. +# The default value is: NO. TYPEDEF_HIDES_STRUCT = NO -# The SYMBOL_CACHE_SIZE determines the size of the internal cache use to -# determine which symbols to keep in memory and which to flush to disk. -# When the cache is full, less often used symbols will be written to disk. -# For small to medium size projects (<1000 input files) the default value is -# probably good enough. For larger projects a too small cache size can cause -# doxygen to be busy swapping symbols to and from disk most of the time -# causing a significant performance penalty. -# If the system has enough physical memory increasing the cache will improve the -# performance by keeping more symbols in memory. Note that the value works on -# a logarithmic scale so increasing the size by one will roughly double the -# memory usage. The cache size is given by this formula: -# 2^(16+SYMBOL_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. - -SYMBOL_CACHE_SIZE = 0 - -# Similar to the SYMBOL_CACHE_SIZE the size of the symbol lookup cache can be -# set using LOOKUP_CACHE_SIZE. This cache is used to resolve symbols given -# their name and scope. Since this can be an expensive process and often the -# same symbol appear multiple times in the code, doxygen keeps a cache of -# pre-resolved symbols. If the cache is too small doxygen will become slower. -# If the cache is too large, memory is wasted. The cache size is given by this -# formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range is 0..9, the default is 0, -# corresponding to a cache size of 2^16 = 65536 symbols. +# The size of the symbol lookup cache can be set using LOOKUP_CACHE_SIZE. This +# cache is used to resolve symbols given their name and scope. Since this can be +# an expensive process and often the same symbol appears multiple times in the +# code, doxygen keeps a cache of pre-resolved symbols. If the cache is too small +# doxygen will become slower. If the cache is too large, memory is wasted. The +# cache size is given by this formula: 2^(16+LOOKUP_CACHE_SIZE). The valid range +# is 0..9, the default is 0, corresponding to a cache size of 2^16=65536 +# symbols. At the end of a run doxygen will report the cache usage and suggest +# the optimal cache size from a speed point of view. +# Minimum value: 0, maximum value: 9, default value: 0. LOOKUP_CACHE_SIZE = 0 @@ -351,342 +402,392 @@ LOOKUP_CACHE_SIZE = 0 #--------------------------------------------------------------------------- # If the EXTRACT_ALL tag is set to YES doxygen will assume all entities in -# documentation are documented, even if no documentation was available. -# Private class members and static file members will be hidden unless -# the EXTRACT_PRIVATE and EXTRACT_STATIC tags are set to YES +# documentation are documented, even if no documentation was available. Private +# class members and static file members will be hidden unless the +# EXTRACT_PRIVATE respectively EXTRACT_STATIC tags are set to YES. +# Note: This will also disable the warnings about undocumented members that are +# normally produced when WARNINGS is set to YES. +# The default value is: NO. EXTRACT_ALL = NO -# If the EXTRACT_PRIVATE tag is set to YES all private members of a class -# will be included in the documentation. +# If the EXTRACT_PRIVATE tag is set to YES all private members of a class will +# be included in the documentation. +# The default value is: NO. EXTRACT_PRIVATE = NO -# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal scope will be included in the documentation. +# If the EXTRACT_PACKAGE tag is set to YES all members with package or internal +# scope will be included in the documentation. +# The default value is: NO. EXTRACT_PACKAGE = NO -# If the EXTRACT_STATIC tag is set to YES all static members of a file -# will be included in the documentation. +# If the EXTRACT_STATIC tag is set to YES all static members of a file will be +# included in the documentation. +# The default value is: NO. EXTRACT_STATIC = NO -# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) -# defined locally in source files will be included in the documentation. -# If set to NO only classes defined in header files are included. +# If the EXTRACT_LOCAL_CLASSES tag is set to YES classes (and structs) defined +# locally in source files will be included in the documentation. If set to NO +# only classes defined in header files are included. Does not have any effect +# for Java sources. +# The default value is: YES. EXTRACT_LOCAL_CLASSES = NO -# This flag is only useful for Objective-C code. When set to YES local -# methods, which are defined in the implementation section but not in -# the interface are included in the documentation. -# If set to NO (the default) only methods in the interface are included. +# This flag is only useful for Objective-C code. When set to YES local methods, +# which are defined in the implementation section but not in the interface are +# included in the documentation. If set to NO only methods in the interface are +# included. +# The default value is: NO. EXTRACT_LOCAL_METHODS = NO # If this flag is set to YES, the members of anonymous namespaces will be # extracted and appear in the documentation as a namespace called -# 'anonymous_namespace{file}', where file will be replaced with the base -# name of the file that contains the anonymous namespace. By default -# anonymous namespaces are hidden. +# 'anonymous_namespace{file}', where file will be replaced with the base name of +# the file that contains the anonymous namespace. By default anonymous namespace +# are hidden. +# The default value is: NO. EXTRACT_ANON_NSPACES = NO -# If the HIDE_UNDOC_MEMBERS tag is set to YES, Doxygen will hide all -# undocumented members of documented classes, files or namespaces. -# If set to NO (the default) these members will be included in the -# various overviews, but no documentation section is generated. -# This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_MEMBERS tag is set to YES, doxygen will hide all +# undocumented members inside documented classes or files. If set to NO these +# members will be included in the various overviews, but no documentation +# section is generated. This option has no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_MEMBERS = YES -# If the HIDE_UNDOC_CLASSES tag is set to YES, Doxygen will hide all -# undocumented classes that are normally visible in the class hierarchy. -# If set to NO (the default) these classes will be included in the various -# overviews. This option has no effect if EXTRACT_ALL is enabled. +# If the HIDE_UNDOC_CLASSES tag is set to YES, doxygen will hide all +# undocumented classes that are normally visible in the class hierarchy. If set +# to NO these classes will be included in the various overviews. This option has +# no effect if EXTRACT_ALL is enabled. +# The default value is: NO. HIDE_UNDOC_CLASSES = YES -# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, Doxygen will hide all -# friend (class|struct|union) declarations. -# If set to NO (the default) these declarations will be included in the -# documentation. +# If the HIDE_FRIEND_COMPOUNDS tag is set to YES, doxygen will hide all friend +# (class|struct|union) declarations. If set to NO these declarations will be +# included in the documentation. +# The default value is: NO. HIDE_FRIEND_COMPOUNDS = NO -# If the HIDE_IN_BODY_DOCS tag is set to YES, Doxygen will hide any -# documentation blocks found inside the body of a function. -# If set to NO (the default) these blocks will be appended to the -# function's detailed documentation block. +# If the HIDE_IN_BODY_DOCS tag is set to YES, doxygen will hide any +# documentation blocks found inside the body of a function. If set to NO these +# blocks will be appended to the function's detailed documentation block. +# The default value is: NO. HIDE_IN_BODY_DOCS = NO -# The INTERNAL_DOCS tag determines if documentation -# that is typed after a \internal command is included. If the tag is set -# to NO (the default) then the documentation will be excluded. -# Set it to YES to include the internal documentation. +# The INTERNAL_DOCS tag determines if documentation that is typed after a +# \internal command is included. If the tag is set to NO then the documentation +# will be excluded. Set it to YES to include the internal documentation. +# The default value is: NO. INTERNAL_DOCS = NO -# If the CASE_SENSE_NAMES tag is set to NO then Doxygen will only generate -# file names in lower-case letters. If set to YES upper-case letters are also +# If the CASE_SENSE_NAMES tag is set to NO then doxygen will only generate file +# names in lower-case letters. If set to YES upper-case letters are also # allowed. This is useful if you have classes or files whose names only differ # in case and if your file system supports case sensitive file names. Windows # and Mac users are advised to set this option to NO. +# The default value is: system dependent. CASE_SENSE_NAMES = YES -# If the HIDE_SCOPE_NAMES tag is set to NO (the default) then Doxygen -# will show members with their full class and namespace scopes in the -# documentation. If set to YES the scope will be hidden. +# If the HIDE_SCOPE_NAMES tag is set to NO then doxygen will show members with +# their full class and namespace scopes in the documentation. If set to YES the +# scope will be hidden. +# The default value is: NO. HIDE_SCOPE_NAMES = NO -# If the SHOW_INCLUDE_FILES tag is set to YES (the default) then Doxygen -# will put a list of the files that are included by a file in the documentation -# of that file. +# If the SHOW_INCLUDE_FILES tag is set to YES then doxygen will put a list of +# the files that are included by a file in the documentation of that file. +# The default value is: YES. SHOW_INCLUDE_FILES = YES -# If the FORCE_LOCAL_INCLUDES tag is set to YES then Doxygen -# will list include files with double quotes in the documentation -# rather than with sharp brackets. +# If the SHOW_GROUPED_MEMB_INC tag is set to YES then Doxygen will add for each +# grouped member an include statement to the documentation, telling the reader +# which file to include in order to use the member. +# The default value is: NO. + +SHOW_GROUPED_MEMB_INC = NO + +# If the FORCE_LOCAL_INCLUDES tag is set to YES then doxygen will list include +# files with double quotes in the documentation rather than with sharp brackets. +# The default value is: NO. FORCE_LOCAL_INCLUDES = NO -# If the INLINE_INFO tag is set to YES (the default) then a tag [inline] -# is inserted in the documentation for inline members. +# If the INLINE_INFO tag is set to YES then a tag [inline] is inserted in the +# documentation for inline members. +# The default value is: YES. INLINE_INFO = YES -# If the SORT_MEMBER_DOCS tag is set to YES (the default) then doxygen -# will sort the (detailed) documentation of file and class members -# alphabetically by member name. If set to NO the members will appear in -# declaration order. +# If the SORT_MEMBER_DOCS tag is set to YES then doxygen will sort the +# (detailed) documentation of file and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. +# The default value is: YES. SORT_MEMBER_DOCS = YES -# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the -# brief documentation of file, namespace and class members alphabetically -# by member name. If set to NO (the default) the members will appear in -# declaration order. +# If the SORT_BRIEF_DOCS tag is set to YES then doxygen will sort the brief +# descriptions of file, namespace and class members alphabetically by member +# name. If set to NO the members will appear in declaration order. Note that +# this will also influence the order of the classes in the class list. +# The default value is: NO. SORT_BRIEF_DOCS = NO -# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen -# will sort the (brief and detailed) documentation of class members so that -# constructors and destructors are listed first. If set to NO (the default) -# the constructors will appear in the respective orders defined by -# SORT_MEMBER_DOCS and SORT_BRIEF_DOCS. -# This tag will be ignored for brief docs if SORT_BRIEF_DOCS is set to NO -# and ignored for detailed docs if SORT_MEMBER_DOCS is set to NO. +# If the SORT_MEMBERS_CTORS_1ST tag is set to YES then doxygen will sort the +# (brief and detailed) documentation of class members so that constructors and +# destructors are listed first. If set to NO the constructors will appear in the +# respective orders defined by SORT_BRIEF_DOCS and SORT_MEMBER_DOCS. +# Note: If SORT_BRIEF_DOCS is set to NO this option is ignored for sorting brief +# member documentation. +# Note: If SORT_MEMBER_DOCS is set to NO this option is ignored for sorting +# detailed member documentation. +# The default value is: NO. SORT_MEMBERS_CTORS_1ST = NO -# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the -# hierarchy of group names into alphabetical order. If set to NO (the default) -# the group names will appear in their defined order. +# If the SORT_GROUP_NAMES tag is set to YES then doxygen will sort the hierarchy +# of group names into alphabetical order. If set to NO the group names will +# appear in their defined order. +# The default value is: NO. SORT_GROUP_NAMES = NO -# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be -# sorted by fully-qualified names, including namespaces. If set to -# NO (the default), the class list will be sorted only by class name, -# not including the namespace part. +# If the SORT_BY_SCOPE_NAME tag is set to YES, the class list will be sorted by +# fully-qualified names, including namespaces. If set to NO, the class list will +# be sorted only by class name, not including the namespace part. # Note: This option is not very useful if HIDE_SCOPE_NAMES is set to YES. -# Note: This option applies only to the class list, not to the -# alphabetical list. +# Note: This option applies only to the class list, not to the alphabetical +# list. +# The default value is: NO. SORT_BY_SCOPE_NAME = NO -# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to -# do proper type resolution of all parameters of a function it will reject a -# match between the prototype and the implementation of a member function even -# if there is only one candidate or it is obvious which candidate to choose -# by doing a simple string match. By disabling STRICT_PROTO_MATCHING doxygen -# will still accept a match between prototype and implementation in such cases. +# If the STRICT_PROTO_MATCHING option is enabled and doxygen fails to do proper +# type resolution of all parameters of a function it will reject a match between +# the prototype and the implementation of a member function even if there is +# only one candidate or it is obvious which candidate to choose by doing a +# simple string match. By disabling STRICT_PROTO_MATCHING doxygen will still +# accept a match between prototype and implementation in such cases. +# The default value is: NO. STRICT_PROTO_MATCHING = NO -# The GENERATE_TODOLIST tag can be used to enable (YES) or -# disable (NO) the todo list. This list is created by putting \todo -# commands in the documentation. +# The GENERATE_TODOLIST tag can be used to enable ( YES) or disable ( NO) the +# todo list. This list is created by putting \todo commands in the +# documentation. +# The default value is: YES. GENERATE_TODOLIST = YES -# The GENERATE_TESTLIST tag can be used to enable (YES) or -# disable (NO) the test list. This list is created by putting \test -# commands in the documentation. +# The GENERATE_TESTLIST tag can be used to enable ( YES) or disable ( NO) the +# test list. This list is created by putting \test commands in the +# documentation. +# The default value is: YES. GENERATE_TESTLIST = YES -# The GENERATE_BUGLIST tag can be used to enable (YES) or -# disable (NO) the bug list. This list is created by putting \bug -# commands in the documentation. +# The GENERATE_BUGLIST tag can be used to enable ( YES) or disable ( NO) the bug +# list. This list is created by putting \bug commands in the documentation. +# The default value is: YES. GENERATE_BUGLIST = NO -# The GENERATE_DEPRECATEDLIST tag can be used to enable (YES) or -# disable (NO) the deprecated list. This list is created by putting -# \deprecated commands in the documentation. +# The GENERATE_DEPRECATEDLIST tag can be used to enable ( YES) or disable ( NO) +# the deprecated list. This list is created by putting \deprecated commands in +# the documentation. +# The default value is: YES. GENERATE_DEPRECATEDLIST= NO -# The ENABLED_SECTIONS tag can be used to enable conditional -# documentation sections, marked by \if sectionname ... \endif. +# The ENABLED_SECTIONS tag can be used to enable conditional documentation +# sections, marked by \if ... \endif and \cond +# ... \endcond blocks. ENABLED_SECTIONS = -# The MAX_INITIALIZER_LINES tag determines the maximum number of lines -# the initial value of a variable or macro consists of for it to appear in -# the documentation. If the initializer consists of more lines than specified -# here it will be hidden. Use a value of 0 to hide initializers completely. -# The appearance of the initializer of individual variables and macros in the -# documentation can be controlled using \showinitializer or \hideinitializer -# command in the documentation regardless of this setting. +# The MAX_INITIALIZER_LINES tag determines the maximum number of lines that the +# initial value of a variable or macro / define can have for it to appear in the +# documentation. If the initializer consists of more lines than specified here +# it will be hidden. Use a value of 0 to hide initializers completely. The +# appearance of the value of individual variables and macros / defines can be +# controlled using \showinitializer or \hideinitializer command in the +# documentation regardless of this setting. +# Minimum value: 0, maximum value: 10000, default value: 30. MAX_INITIALIZER_LINES = 30 -# Set the SHOW_USED_FILES tag to NO to disable the list of files generated -# at the bottom of the documentation of classes and structs. If set to YES the -# list will mention the files that were used to generate the documentation. +# Set the SHOW_USED_FILES tag to NO to disable the list of files generated at +# the bottom of the documentation of classes and structs. If set to YES the list +# will mention the files that were used to generate the documentation. +# The default value is: YES. SHOW_USED_FILES = NO -# Set the SHOW_FILES tag to NO to disable the generation of the Files page. -# This will remove the Files entry from the Quick Index and from the -# Folder Tree View (if specified). The default is YES. +# Set the SHOW_FILES tag to NO to disable the generation of the Files page. This +# will remove the Files entry from the Quick Index and from the Folder Tree View +# (if specified). +# The default value is: YES. SHOW_FILES = YES -# Set the SHOW_NAMESPACES tag to NO to disable the generation of the -# Namespaces page. -# This will remove the Namespaces entry from the Quick Index -# and from the Folder Tree View (if specified). The default is YES. +# Set the SHOW_NAMESPACES tag to NO to disable the generation of the Namespaces +# page. This will remove the Namespaces entry from the Quick Index and from the +# Folder Tree View (if specified). +# The default value is: YES. SHOW_NAMESPACES = YES # The FILE_VERSION_FILTER tag can be used to specify a program or script that # doxygen should invoke to get the current version for each file (typically from # the version control system). Doxygen will invoke the program by executing (via -# popen()) the command , where is the value of -# the FILE_VERSION_FILTER tag, and is the name of an input file -# provided by doxygen. Whatever the program writes to standard output -# is used as the file version. See the manual for examples. +# popen()) the command command input-file, where command is the value of the +# FILE_VERSION_FILTER tag, and input-file is the name of an input file provided +# by doxygen. Whatever the program writes to standard output is used as the file +# version. For an example see the documentation. FILE_VERSION_FILTER = # The LAYOUT_FILE tag can be used to specify a layout file which will be parsed # by doxygen. The layout file controls the global structure of the generated # output files in an output format independent way. To create the layout file -# that represents doxygen's defaults, run doxygen with the -l option. -# You can optionally specify a file name after the option, if omitted -# DoxygenLayout.xml will be used as the name of the layout file. +# that represents doxygen's defaults, run doxygen with the -l option. You can +# optionally specify a file name after the option, if omitted DoxygenLayout.xml +# will be used as the name of the layout file. +# +# Note that if you run doxygen from a directory containing a file called +# DoxygenLayout.xml, doxygen will parse it automatically even if the LAYOUT_FILE +# tag is left empty. LAYOUT_FILE = -# The CITE_BIB_FILES tag can be used to specify one or more bib files -# containing the references data. This must be a list of .bib files. The -# .bib extension is automatically appended if omitted. Using this command -# requires the bibtex tool to be installed. See also -# http://en.wikipedia.org/wiki/BibTeX for more info. For LaTeX the style -# of the bibliography can be controlled using LATEX_BIB_STYLE. To use this -# feature you need bibtex and perl available in the search path. +# The CITE_BIB_FILES tag can be used to specify one or more bib files containing +# the reference definitions. This must be a list of .bib files. The .bib +# extension is automatically appended if omitted. This requires the bibtex tool +# to be installed. See also http://en.wikipedia.org/wiki/BibTeX for more info. +# For LaTeX the style of the bibliography can be controlled using +# LATEX_BIB_STYLE. To use this feature you need bibtex and perl available in the +# search path. See also \cite for info how to create references. CITE_BIB_FILES = #--------------------------------------------------------------------------- -# configuration options related to warning and progress messages +# Configuration options related to warning and progress messages #--------------------------------------------------------------------------- -# The QUIET tag can be used to turn on/off the messages that are generated -# by doxygen. Possible values are YES and NO. If left blank NO is used. +# The QUIET tag can be used to turn on/off the messages that are generated to +# standard output by doxygen. If QUIET is set to YES this implies that the +# messages are off. +# The default value is: NO. QUIET = NO # The WARNINGS tag can be used to turn on/off the warning messages that are -# generated by doxygen. Possible values are YES and NO. If left blank -# NO is used. +# generated to standard error ( stderr) by doxygen. If WARNINGS is set to YES +# this implies that the warnings are on. +# +# Tip: Turn warnings on while writing the documentation. +# The default value is: YES. WARNINGS = YES -# If WARN_IF_UNDOCUMENTED is set to YES, then doxygen will generate warnings -# for undocumented members. If EXTRACT_ALL is set to YES then this flag will -# automatically be disabled. +# If the WARN_IF_UNDOCUMENTED tag is set to YES, then doxygen will generate +# warnings for undocumented members. If EXTRACT_ALL is set to YES then this flag +# will automatically be disabled. +# The default value is: YES. WARN_IF_UNDOCUMENTED = NO -# If WARN_IF_DOC_ERROR is set to YES, doxygen will generate warnings for -# potential errors in the documentation, such as not documenting some -# parameters in a documented function, or documenting parameters that -# don't exist or using markup commands wrongly. +# If the WARN_IF_DOC_ERROR tag is set to YES, doxygen will generate warnings for +# potential errors in the documentation, such as not documenting some parameters +# in a documented function, or documenting parameters that don't exist or using +# markup commands wrongly. +# The default value is: YES. WARN_IF_DOC_ERROR = YES -# The WARN_NO_PARAMDOC option can be enabled to get warnings for -# functions that are documented, but have no documentation for their parameters -# or return value. If set to NO (the default) doxygen will only warn about -# wrong or incomplete parameter documentation, but not about the absence of -# documentation. +# This WARN_NO_PARAMDOC option can be enabled to get warnings for functions that +# are documented, but have no documentation for their parameters or return +# value. If set to NO doxygen will only warn about wrong or incomplete parameter +# documentation, but not about the absence of documentation. +# The default value is: NO. WARN_NO_PARAMDOC = NO -# The WARN_FORMAT tag determines the format of the warning messages that -# doxygen can produce. The string should contain the $file, $line, and $text -# tags, which will be replaced by the file and line number from which the -# warning originated and the warning text. Optionally the format may contain -# $version, which will be replaced by the version of the file (if it could -# be obtained via FILE_VERSION_FILTER) +# The WARN_FORMAT tag determines the format of the warning messages that doxygen +# can produce. The string should contain the $file, $line, and $text tags, which +# will be replaced by the file and line number from which the warning originated +# and the warning text. Optionally the format may contain $version, which will +# be replaced by the version of the file (if it could be obtained via +# FILE_VERSION_FILTER) +# The default value is: $file:$line: $text. WARN_FORMAT = "$file:$line: $text" -# The WARN_LOGFILE tag can be used to specify a file to which warning -# and error messages should be written. If left blank the output is written -# to stderr. +# The WARN_LOGFILE tag can be used to specify a file to which warning and error +# messages should be written. If left blank the output is written to standard +# error (stderr). WARN_LOGFILE = doxygen.log #--------------------------------------------------------------------------- -# configuration options related to the input files +# Configuration options related to the input files #--------------------------------------------------------------------------- -# The INPUT tag can be used to specify the files and/or directories that contain -# documented source files. You may enter file names like "myfile.cpp" or -# directories like "/usr/src/myproject". Separate the files or directories -# with spaces. +# The INPUT tag is used to specify the files and/or directories that contain +# documented source files. You may enter file names like myfile.cpp or +# directories like /usr/src/myproject. Separate the files or directories with +# spaces. +# Note: If this tag is empty the current directory is searched. INPUT = $(docsrc) # This tag can be used to specify the character encoding of the source files -# that doxygen parses. Internally doxygen uses the UTF-8 encoding, which is -# also the default input encoding. Doxygen uses libiconv (or the iconv built -# into libc) for the transcoding. See http://www.gnu.org/software/libiconv for -# the list of possible encodings. +# that doxygen parses. Internally doxygen uses the UTF-8 encoding. Doxygen uses +# libiconv (or the iconv built into libc) for the transcoding. See the libiconv +# documentation (see: http://www.gnu.org/software/libiconv) for the list of +# possible encodings. +# The default value is: UTF-8. INPUT_ENCODING = UTF-8 # If the value of the INPUT tag contains directories, you can use the -# FILE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank the following patterns are tested: -# *.c *.cc *.cxx *.cpp *.c++ *.d *.java *.ii *.ixx *.ipp *.i++ *.inl *.h *.hh -# *.hxx *.hpp *.h++ *.idl *.odl *.cs *.php *.php3 *.inc *.m *.mm *.dox *.py -# *.f90 *.f *.for *.vhd *.vhdl +# FILE_PATTERNS tag to specify one or more wildcard patterns (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank the +# following patterns are tested:*.c, *.cc, *.cxx, *.cpp, *.c++, *.java, *.ii, +# *.ixx, *.ipp, *.i++, *.inl, *.idl, *.ddl, *.odl, *.h, *.hh, *.hxx, *.hpp, +# *.h++, *.cs, *.d, *.php, *.php4, *.php5, *.phtml, *.inc, *.m, *.markdown, +# *.md, *.mm, *.dox, *.py, *.f90, *.f, *.for, *.tcl, *.vhd, *.vhdl, *.ucf, +# *.qsf, *.as and *.js. FILE_PATTERNS = *.h \ *.c \ *.doc.html \ *.txt -# The RECURSIVE tag can be used to turn specify whether or not subdirectories -# should be searched for input files as well. Possible values are YES and NO. -# If left blank NO is used. +# The RECURSIVE tag can be used to specify whether or not subdirectories should +# be searched for input files as well. +# The default value is: NO. RECURSIVE = NO # The EXCLUDE tag can be used to specify files and/or directories that should be # excluded from the INPUT source files. This way you can easily exclude a # subdirectory from a directory tree whose root is specified with the INPUT tag. +# # Note that relative paths are relative to the directory from which doxygen is # run. @@ -695,14 +796,16 @@ EXCLUDE = # The EXCLUDE_SYMLINKS tag can be used to select whether or not files or # directories that are symbolic links (a Unix file system feature) are excluded # from the input. +# The default value is: NO. EXCLUDE_SYMLINKS = NO # If the value of the INPUT tag contains directories, you can use the # EXCLUDE_PATTERNS tag to specify one or more wildcard patterns to exclude -# certain files from those directories. Note that the wildcards are matched -# against the file with absolute path, so to exclude all test directories -# for example use the pattern */test/* +# certain files from those directories. +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories for example use the pattern */test/* EXCLUDE_PATTERNS = @@ -711,757 +814,1082 @@ EXCLUDE_PATTERNS = # output. The symbol name can be a fully qualified name, a word, or if the # wildcard * is used, a substring. Examples: ANamespace, AClass, # AClass::ANamespace, ANamespace::*Test +# +# Note that the wildcards are matched against the file with absolute path, so to +# exclude all test directories use the pattern */test/* EXCLUDE_SYMBOLS = -# The EXAMPLE_PATH tag can be used to specify one or more files or -# directories that contain example code fragments that are included (see -# the \include command). +# The EXAMPLE_PATH tag can be used to specify one or more files or directories +# that contain example code fragments that are included (see the \include +# command). EXAMPLE_PATH = . \ ../examples/rime \ ../examples/multi-threading # If the value of the EXAMPLE_PATH tag contains directories, you can use the -# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp -# and *.h) to filter out the source-files in the directories. If left -# blank all files are included. +# EXAMPLE_PATTERNS tag to specify one or more wildcard pattern (like *.cpp and +# *.h) to filter out the source-files in the directories. If left blank all +# files are included. EXAMPLE_PATTERNS = # If the EXAMPLE_RECURSIVE tag is set to YES then subdirectories will be -# searched for input files to be used with the \include or \dontinclude -# commands irrespective of the value of the RECURSIVE tag. -# Possible values are YES and NO. If left blank NO is used. +# searched for input files to be used with the \include or \dontinclude commands +# irrespective of the value of the RECURSIVE tag. +# The default value is: NO. EXAMPLE_RECURSIVE = NO -# The IMAGE_PATH tag can be used to specify one or more files or -# directories that contain image that are included in the documentation (see -# the \image command). +# The IMAGE_PATH tag can be used to specify one or more files or directories +# that contain images that are to be included in the documentation (see the +# \image command). IMAGE_PATH = pics # The INPUT_FILTER tag can be used to specify a program that doxygen should # invoke to filter for each input file. Doxygen will invoke the filter program -# by executing (via popen()) the command , where -# is the value of the INPUT_FILTER tag, and is the name of an -# input file. Doxygen will then use the output that the filter program writes -# to standard output. -# If FILTER_PATTERNS is specified, this tag will be -# ignored. +# by executing (via popen()) the command: +# +# +# +# where is the value of the INPUT_FILTER tag, and is the +# name of an input file. Doxygen will then use the output that the filter +# program writes to standard output. If FILTER_PATTERNS is specified, this tag +# will be ignored. +# +# Note that the filter must not add or remove lines; it is applied before the +# code is scanned, but not when the output code is generated. If lines are added +# or removed, the anchors will not be placed correctly. INPUT_FILTER = # The FILTER_PATTERNS tag can be used to specify filters on a per file pattern -# basis. -# Doxygen will compare the file name with each pattern and apply the -# filter if there is a match. -# The filters are a list of the form: -# pattern=filter (like *.cpp=my_cpp_filter). See INPUT_FILTER for further -# info on how filters are used. If FILTER_PATTERNS is empty or if -# non of the patterns match the file name, INPUT_FILTER is applied. +# basis. Doxygen will compare the file name with each pattern and apply the +# filter if there is a match. The filters are a list of the form: pattern=filter +# (like *.cpp=my_cpp_filter). See INPUT_FILTER for further information on how +# filters are used. If the FILTER_PATTERNS tag is empty or if none of the +# patterns match the file name, INPUT_FILTER is applied. FILTER_PATTERNS = # If the FILTER_SOURCE_FILES tag is set to YES, the input filter (if set using -# INPUT_FILTER) will be used to filter the input files when producing source -# files to browse (i.e. when SOURCE_BROWSER is set to YES). +# INPUT_FILTER ) will also be used to filter the input files that are used for +# producing the source files to browse (i.e. when SOURCE_BROWSER is set to YES). +# The default value is: NO. FILTER_SOURCE_FILES = NO # The FILTER_SOURCE_PATTERNS tag can be used to specify source filters per file -# pattern. A pattern will override the setting for FILTER_PATTERN (if any) -# and it is also possible to disable source filtering for a specific pattern -# using *.ext= (so without naming a filter). This option only has effect when -# FILTER_SOURCE_FILES is enabled. +# pattern. A pattern will override the setting for FILTER_PATTERN (if any) and +# it is also possible to disable source filtering for a specific pattern using +# *.ext= (so without naming a filter). +# This tag requires that the tag FILTER_SOURCE_FILES is set to YES. FILTER_SOURCE_PATTERNS = +# If the USE_MDFILE_AS_MAINPAGE tag refers to the name of a markdown file that +# is part of the input, its contents will be placed on the main page +# (index.html). This can be useful if you have a project on for instance GitHub +# and want to reuse the introduction page also for the doxygen output. + +USE_MDFILE_AS_MAINPAGE = + #--------------------------------------------------------------------------- -# configuration options related to source browsing +# Configuration options related to source browsing #--------------------------------------------------------------------------- -# If the SOURCE_BROWSER tag is set to YES then a list of source files will -# be generated. Documented entities will be cross-referenced with these sources. -# Note: To get rid of all source code in the generated output, make sure also -# VERBATIM_HEADERS is set to NO. +# If the SOURCE_BROWSER tag is set to YES then a list of source files will be +# generated. Documented entities will be cross-referenced with these sources. +# +# Note: To get rid of all source code in the generated output, make sure that +# also VERBATIM_HEADERS is set to NO. +# The default value is: NO. SOURCE_BROWSER = YES -# Setting the INLINE_SOURCES tag to YES will include the body -# of functions and classes directly in the documentation. +# Setting the INLINE_SOURCES tag to YES will include the body of functions, +# classes and enums directly into the documentation. +# The default value is: NO. INLINE_SOURCES = NO -# Setting the STRIP_CODE_COMMENTS tag to YES (the default) will instruct -# doxygen to hide any special comment blocks from generated source code -# fragments. Normal C, C++ and Fortran comments will always remain visible. +# Setting the STRIP_CODE_COMMENTS tag to YES will instruct doxygen to hide any +# special comment blocks from generated source code fragments. Normal C, C++ and +# Fortran comments will always remain visible. +# The default value is: YES. STRIP_CODE_COMMENTS = NO -# If the REFERENCED_BY_RELATION tag is set to YES -# then for each documented function all documented -# functions referencing it will be listed. +# If the REFERENCED_BY_RELATION tag is set to YES then for each documented +# function all documented functions referencing it will be listed. +# The default value is: NO. REFERENCED_BY_RELATION = YES -# If the REFERENCES_RELATION tag is set to YES -# then for each documented function all documented entities -# called/used by that function will be listed. +# If the REFERENCES_RELATION tag is set to YES then for each documented function +# all documented entities called/used by that function will be listed. +# The default value is: NO. REFERENCES_RELATION = YES -# If the REFERENCES_LINK_SOURCE tag is set to YES (the default) -# and SOURCE_BROWSER tag is set to YES, then the hyperlinks from -# functions in REFERENCES_RELATION and REFERENCED_BY_RELATION lists will -# link to the source code. -# Otherwise they will link to the documentation. +# If the REFERENCES_LINK_SOURCE tag is set to YES and SOURCE_BROWSER tag is set +# to YES, then the hyperlinks from functions in REFERENCES_RELATION and +# REFERENCED_BY_RELATION lists will link to the source code. Otherwise they will +# link to the documentation. +# The default value is: YES. REFERENCES_LINK_SOURCE = YES -# If the USE_HTAGS tag is set to YES then the references to source code -# will point to the HTML generated by the htags(1) tool instead of doxygen -# built-in source browser. The htags tool is part of GNU's global source -# tagging system (see http://www.gnu.org/software/global/global.html). You -# will need version 4.8.6 or higher. +# If SOURCE_TOOLTIPS is enabled (the default) then hovering a hyperlink in the +# source code will show a tooltip with additional information such as prototype, +# brief description and links to the definition and documentation. Since this +# will make the HTML file larger and loading of large files a bit slower, you +# can opt to disable this feature. +# The default value is: YES. +# This tag requires that the tag SOURCE_BROWSER is set to YES. + +SOURCE_TOOLTIPS = YES + +# If the USE_HTAGS tag is set to YES then the references to source code will +# point to the HTML generated by the htags(1) tool instead of doxygen built-in +# source browser. The htags tool is part of GNU's global source tagging system +# (see http://www.gnu.org/software/global/global.html). You will need version +# 4.8.6 or higher. +# +# To use it do the following: +# - Install the latest version of global +# - Enable SOURCE_BROWSER and USE_HTAGS in the config file +# - Make sure the INPUT points to the root of the source tree +# - Run doxygen as normal +# +# Doxygen will invoke htags (and that will in turn invoke gtags), so these +# tools must be available from the command line (i.e. in the search path). +# +# The result: instead of the source browser generated by doxygen, the links to +# source code will now point to the output of htags. +# The default value is: NO. +# This tag requires that the tag SOURCE_BROWSER is set to YES. USE_HTAGS = NO -# If the VERBATIM_HEADERS tag is set to YES (the default) then Doxygen -# will generate a verbatim copy of the header file for each class for -# which an include is specified. Set to NO to disable this. +# If the VERBATIM_HEADERS tag is set the YES then doxygen will generate a +# verbatim copy of the header file for each class for which an include is +# specified. Set to NO to disable this. +# See also: Section \class. +# The default value is: YES. VERBATIM_HEADERS = YES #--------------------------------------------------------------------------- -# configuration options related to the alphabetical class index +# Configuration options related to the alphabetical class index #--------------------------------------------------------------------------- -# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index -# of all compounds will be generated. Enable this if the project -# contains a lot of classes, structs, unions or interfaces. +# If the ALPHABETICAL_INDEX tag is set to YES, an alphabetical index of all +# compounds will be generated. Enable this if the project contains a lot of +# classes, structs, unions or interfaces. +# The default value is: YES. ALPHABETICAL_INDEX = YES -# If the alphabetical index is enabled (see ALPHABETICAL_INDEX) then -# the COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns -# in which this list will be split (can be a number in the range [1..20]) +# The COLS_IN_ALPHA_INDEX tag can be used to specify the number of columns in +# which the alphabetical index list will be split. +# Minimum value: 1, maximum value: 20, default value: 5. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. COLS_IN_ALPHA_INDEX = 5 -# In case all classes in a project start with a common prefix, all -# classes will be put under the same header in the alphabetical index. -# The IGNORE_PREFIX tag can be used to specify one or more prefixes that -# should be ignored while generating the index headers. +# In case all classes in a project start with a common prefix, all classes will +# be put under the same header in the alphabetical index. The IGNORE_PREFIX tag +# can be used to specify a prefix (or a list of prefixes) that should be ignored +# while generating the index headers. +# This tag requires that the tag ALPHABETICAL_INDEX is set to YES. IGNORE_PREFIX = #--------------------------------------------------------------------------- -# configuration options related to the HTML output +# Configuration options related to the HTML output #--------------------------------------------------------------------------- -# If the GENERATE_HTML tag is set to YES (the default) Doxygen will -# generate HTML output. +# If the GENERATE_HTML tag is set to YES doxygen will generate HTML output +# The default value is: YES. GENERATE_HTML = YES -# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. -# If a relative path is entered the value of OUTPUT_DIRECTORY will be -# put in front of it. If left blank `html' will be used as the default path. +# The HTML_OUTPUT tag is used to specify where the HTML docs will be put. If a +# relative path is entered the value of OUTPUT_DIRECTORY will be put in front of +# it. +# The default directory is: html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_OUTPUT = html -# The HTML_FILE_EXTENSION tag can be used to specify the file extension for -# each generated HTML page (for example: .htm,.php,.asp). If it is left blank -# doxygen will generate files with .html extension. +# The HTML_FILE_EXTENSION tag can be used to specify the file extension for each +# generated HTML page (for example: .htm, .php, .asp). +# The default value is: .html. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FILE_EXTENSION = .html -# The HTML_HEADER tag can be used to specify a personal HTML header for -# each generated HTML page. If it is left blank doxygen will generate a -# standard header. Note that when using a custom header you are responsible -# for the proper inclusion of any scripts and style sheets that doxygen -# needs, which is dependent on the configuration options used. -# It is advised to generate a default header using "doxygen -w html -# header.html footer.html stylesheet.css YourConfigFile" and then modify -# that header. Note that the header is subject to change so you typically -# have to redo this when upgrading to a newer version of doxygen or when -# changing the value of configuration settings such as GENERATE_TREEVIEW! +# The HTML_HEADER tag can be used to specify a user-defined HTML header file for +# each generated HTML page. If the tag is left blank doxygen will generate a +# standard header. +# +# To get valid HTML the header file that includes any scripts and style sheets +# that doxygen needs, which is dependent on the configuration options used (e.g. +# the setting GENERATE_TREEVIEW). It is highly recommended to start with a +# default header using +# doxygen -w html new_header.html new_footer.html new_stylesheet.css +# YourConfigFile +# and then modify the file new_header.html. See also section "Doxygen usage" +# for information on how to generate the default header that doxygen normally +# uses. +# Note: The header is subject to change so you typically have to regenerate the +# default header when upgrading to a newer version of doxygen. For a description +# of the possible markers and block names see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_HEADER = -# The HTML_FOOTER tag can be used to specify a personal HTML footer for -# each generated HTML page. If it is left blank doxygen will generate a -# standard footer. +# The HTML_FOOTER tag can be used to specify a user-defined HTML footer for each +# generated HTML page. If the tag is left blank doxygen will generate a standard +# footer. See HTML_HEADER for more information on how to generate a default +# footer and what special commands can be used inside the footer. See also +# section "Doxygen usage" for information on how to generate the default footer +# that doxygen normally uses. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_FOOTER = -# The HTML_STYLESHEET tag can be used to specify a user-defined cascading -# style sheet that is used by each HTML page. It can be used to -# fine-tune the look of the HTML output. If the tag is left blank doxygen -# will generate a default style sheet. Note that doxygen will try to copy -# the style sheet file to the HTML output directory, so don't put your own -# style sheet in the HTML output directory as well, or it will be erased! +# The HTML_STYLESHEET tag can be used to specify a user-defined cascading style +# sheet that is used by each HTML page. It can be used to fine-tune the look of +# the HTML output. If left blank doxygen will generate a default style sheet. +# See also section "Doxygen usage" for information on how to generate the style +# sheet that doxygen normally uses. +# Note: It is recommended to use HTML_EXTRA_STYLESHEET instead of this tag, as +# it is more robust and this tag (HTML_STYLESHEET) will in the future become +# obsolete. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_STYLESHEET = +# The HTML_EXTRA_STYLESHEET tag can be used to specify additional user-defined +# cascading style sheets that are included after the standard style sheets +# created by doxygen. Using this option one can overrule certain style aspects. +# This is preferred over using HTML_STYLESHEET since it does not replace the +# standard style sheet and is therefor more robust against future updates. +# Doxygen will copy the style sheet files to the output directory. +# Note: The order of the extra stylesheet files is of importance (e.g. the last +# stylesheet in the list overrules the setting of the previous ones in the +# list). For an example see the documentation. +# This tag requires that the tag GENERATE_HTML is set to YES. + +HTML_EXTRA_STYLESHEET = + # The HTML_EXTRA_FILES tag can be used to specify one or more extra images or # other source files which should be copied to the HTML output directory. Note # that these files will be copied to the base HTML output directory. Use the -# $relpath$ marker in the HTML_HEADER and/or HTML_FOOTER files to load these -# files. In the HTML_STYLESHEET file, use the file name only. Also note that -# the files will be copied as-is; there are no commands or markers available. +# $relpath^ marker in the HTML_HEADER and/or HTML_FOOTER files to load these +# files. In the HTML_STYLESHEET file, use the file name only. Also note that the +# files will be copied as-is; there are no commands or markers available. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_EXTRA_FILES = -# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. -# Doxygen will adjust the colors in the style sheet and background images -# according to this color. Hue is specified as an angle on a colorwheel, -# see http://en.wikipedia.org/wiki/Hue for more information. -# For instance the value 0 represents red, 60 is yellow, 120 is green, -# 180 is cyan, 240 is blue, 300 purple, and 360 is red again. -# The allowed range is 0 to 359. +# The HTML_COLORSTYLE_HUE tag controls the color of the HTML output. Doxygen +# will adjust the colors in the stylesheet and background images according to +# this color. Hue is specified as an angle on a colorwheel, see +# http://en.wikipedia.org/wiki/Hue for more information. For instance the value +# 0 represents red, 60 is yellow, 120 is green, 180 is cyan, 240 is blue, 300 +# purple, and 360 is red again. +# Minimum value: 0, maximum value: 359, default value: 220. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_HUE = 220 -# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of -# the colors in the HTML output. For a value of 0 the output will use -# grayscales only. A value of 255 will produce the most vivid colors. +# The HTML_COLORSTYLE_SAT tag controls the purity (or saturation) of the colors +# in the HTML output. For a value of 0 the output will use grayscales only. A +# value of 255 will produce the most vivid colors. +# Minimum value: 0, maximum value: 255, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_SAT = 100 -# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to -# the luminance component of the colors in the HTML output. Values below -# 100 gradually make the output lighter, whereas values above 100 make -# the output darker. The value divided by 100 is the actual gamma applied, -# so 80 represents a gamma of 0.8, The value 220 represents a gamma of 2.2, -# and 100 does not change the gamma. +# The HTML_COLORSTYLE_GAMMA tag controls the gamma correction applied to the +# luminance component of the colors in the HTML output. Values below 100 +# gradually make the output lighter, whereas values above 100 make the output +# darker. The value divided by 100 is the actual gamma applied, so 80 represents +# a gamma of 0.8, The value 220 represents a gamma of 2.2, and 100 does not +# change the gamma. +# Minimum value: 40, maximum value: 240, default value: 80. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_COLORSTYLE_GAMMA = 80 # If the HTML_TIMESTAMP tag is set to YES then the footer of each generated HTML -# page will contain the date and time when the page was generated. Setting -# this to NO can help when comparing the output of multiple runs. +# page will contain the date and time when the page was generated. Setting this +# to NO can help when comparing the output of multiple runs. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_TIMESTAMP = YES # If the HTML_DYNAMIC_SECTIONS tag is set to YES then the generated HTML # documentation will contain sections that can be hidden and shown after the # page has loaded. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_DYNAMIC_SECTIONS = NO -# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of -# entries shown in the various tree structured indices initially; the user -# can expand and collapse entries dynamically later on. Doxygen will expand -# the tree to such a level that at most the specified number of entries are -# visible (unless a fully collapsed tree already exceeds this amount). -# So setting the number of entries 1 will produce a full collapsed tree by -# default. 0 is a special value representing an infinite number of entries -# and will result in a full expanded tree by default. +# With HTML_INDEX_NUM_ENTRIES one can control the preferred number of entries +# shown in the various tree structured indices initially; the user can expand +# and collapse entries dynamically later on. Doxygen will expand the tree to +# such a level that at most the specified number of entries are visible (unless +# a fully collapsed tree already exceeds this amount). So setting the number of +# entries 1 will produce a full collapsed tree by default. 0 is a special value +# representing an infinite number of entries and will result in a full expanded +# tree by default. +# Minimum value: 0, maximum value: 9999, default value: 100. +# This tag requires that the tag GENERATE_HTML is set to YES. HTML_INDEX_NUM_ENTRIES = 100 -# If the GENERATE_DOCSET tag is set to YES, additional index files -# will be generated that can be used as input for Apple's Xcode 3 -# integrated development environment, introduced with OSX 10.5 (Leopard). -# To create a documentation set, doxygen will generate a Makefile in the -# HTML output directory. Running make will produce the docset in that -# directory and running "make install" will install the docset in -# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find -# it at startup. -# See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html +# If the GENERATE_DOCSET tag is set to YES, additional index files will be +# generated that can be used as input for Apple's Xcode 3 integrated development +# environment (see: http://developer.apple.com/tools/xcode/), introduced with +# OSX 10.5 (Leopard). To create a documentation set, doxygen will generate a +# Makefile in the HTML output directory. Running make will produce the docset in +# that directory and running make install will install the docset in +# ~/Library/Developer/Shared/Documentation/DocSets so that Xcode will find it at +# startup. See http://developer.apple.com/tools/creatingdocsetswithdoxygen.html # for more information. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_DOCSET = NO -# When GENERATE_DOCSET tag is set to YES, this tag determines the name of the -# feed. A documentation feed provides an umbrella under which multiple -# documentation sets from a single provider (such as a company or product suite) -# can be grouped. +# This tag determines the name of the docset feed. A documentation feed provides +# an umbrella under which multiple documentation sets from a single provider +# (such as a company or product suite) can be grouped. +# The default value is: Doxygen generated docs. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_FEEDNAME = "Doxygen generated docs" -# When GENERATE_DOCSET tag is set to YES, this tag specifies a string that -# should uniquely identify the documentation set bundle. This should be a -# reverse domain-name style string, e.g. com.mycompany.MyDocSet. Doxygen -# will append .docset to the name. +# This tag specifies a string that should uniquely identify the documentation +# set bundle. This should be a reverse domain-name style string, e.g. +# com.mycompany.MyDocSet. Doxygen will append .docset to the name. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_BUNDLE_ID = org.doxygen.Project -# When GENERATE_PUBLISHER_ID tag specifies a string that should uniquely identify +# The DOCSET_PUBLISHER_ID tag specifies a string that should uniquely identify # the documentation publisher. This should be a reverse domain-name style # string, e.g. com.mycompany.MyDocSet.documentation. +# The default value is: org.doxygen.Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_ID = org.doxygen.Publisher -# The GENERATE_PUBLISHER_NAME tag identifies the documentation publisher. +# The DOCSET_PUBLISHER_NAME tag identifies the documentation publisher. +# The default value is: Publisher. +# This tag requires that the tag GENERATE_DOCSET is set to YES. DOCSET_PUBLISHER_NAME = Publisher -# If the GENERATE_HTMLHELP tag is set to YES, additional index files -# will be generated that can be used as input for tools like the -# Microsoft HTML help workshop to generate a compiled HTML help file (.chm) -# of the generated HTML documentation. +# If the GENERATE_HTMLHELP tag is set to YES then doxygen generates three +# additional HTML index files: index.hhp, index.hhc, and index.hhk. The +# index.hhp is a project file that can be read by Microsoft's HTML Help Workshop +# (see: http://www.microsoft.com/en-us/download/details.aspx?id=21138) on +# Windows. +# +# The HTML Help Workshop contains a compiler that can convert all HTML output +# generated by doxygen into a single compiled HTML file (.chm). Compiled HTML +# files are now used as the Windows 98 help format, and will replace the old +# Windows help format (.hlp) on all Windows platforms in the future. Compressed +# HTML files also contain an index, a table of contents, and you can search for +# words in the documentation. The HTML workshop also contains a viewer for +# compressed HTML files. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_HTMLHELP = YES -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_FILE tag can -# be used to specify the file name of the resulting .chm file. You -# can add a path in front of the file if the result should not be +# The CHM_FILE tag can be used to specify the file name of the resulting .chm +# file. You can add a path in front of the file if the result should not be # written to the html output directory. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_FILE = -# If the GENERATE_HTMLHELP tag is set to YES, the HHC_LOCATION tag can -# be used to specify the location (absolute path including file name) of -# the HTML help compiler (hhc.exe). If non-empty doxygen will try to run -# the HTML help compiler on the generated index.hhp. +# The HHC_LOCATION tag can be used to specify the location (absolute path +# including file name) of the HTML help compiler ( hhc.exe). If non-empty +# doxygen will try to run the HTML help compiler on the generated index.hhp. +# The file has to be specified with full path. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. HHC_LOCATION = -# If the GENERATE_HTMLHELP tag is set to YES, the GENERATE_CHI flag -# controls if a separate .chi index file is generated (YES) or that -# it should be included in the master .chm file (NO). +# The GENERATE_CHI flag controls if a separate .chi index file is generated ( +# YES) or that it should be included in the master .chm file ( NO). +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. GENERATE_CHI = YES -# If the GENERATE_HTMLHELP tag is set to YES, the CHM_INDEX_ENCODING -# is used to encode HtmlHelp index (hhk), content (hhc) and project file -# content. +# The CHM_INDEX_ENCODING is used to encode HtmlHelp index ( hhk), content ( hhc) +# and project file content. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. CHM_INDEX_ENCODING = -# If the GENERATE_HTMLHELP tag is set to YES, the BINARY_TOC flag -# controls whether a binary table of contents is generated (YES) or a -# normal table of contents (NO) in the .chm file. +# The BINARY_TOC flag controls whether a binary table of contents is generated ( +# YES) or a normal table of contents ( NO) in the .chm file. Furthermore it +# enables the Previous and Next buttons. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. BINARY_TOC = YES -# The TOC_EXPAND flag can be set to YES to add extra items for group members -# to the contents of the HTML help documentation and to the tree view. +# The TOC_EXPAND flag can be set to YES to add extra items for group members to +# the table of contents of the HTML help documentation and to the tree view. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTMLHELP is set to YES. TOC_EXPAND = YES # If the GENERATE_QHP tag is set to YES and both QHP_NAMESPACE and -# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated -# that can be used as input for Qt's qhelpgenerator to generate a -# Qt Compressed Help (.qch) of the generated HTML documentation. +# QHP_VIRTUAL_FOLDER are set, an additional index file will be generated that +# can be used as input for Qt's qhelpgenerator to generate a Qt Compressed Help +# (.qch) of the generated HTML documentation. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_QHP = NO -# If the QHG_LOCATION tag is specified, the QCH_FILE tag can -# be used to specify the file name of the resulting .qch file. -# The path specified is relative to the HTML output folder. +# If the QHG_LOCATION tag is specified, the QCH_FILE tag can be used to specify +# the file name of the resulting .qch file. The path specified is relative to +# the HTML output folder. +# This tag requires that the tag GENERATE_QHP is set to YES. QCH_FILE = -# The QHP_NAMESPACE tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#namespace +# The QHP_NAMESPACE tag specifies the namespace to use when generating Qt Help +# Project output. For more information please see Qt Help Project / Namespace +# (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#namespace). +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_NAMESPACE = org.doxygen.Project -# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating -# Qt Help Project output. For more information please see -# http://doc.trolltech.com/qthelpproject.html#virtual-folders +# The QHP_VIRTUAL_FOLDER tag specifies the namespace to use when generating Qt +# Help Project output. For more information please see Qt Help Project / Virtual +# Folders (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#virtual- +# folders). +# The default value is: doc. +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_VIRTUAL_FOLDER = doc -# If QHP_CUST_FILTER_NAME is set, it specifies the name of a custom filter to -# add. For more information please see -# http://doc.trolltech.com/qthelpproject.html#custom-filters +# If the QHP_CUST_FILTER_NAME tag is set, it specifies the name of a custom +# filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_NAME = -# The QHP_CUST_FILT_ATTRS tag specifies the list of the attributes of the -# custom filter to add. For more information please see -# -# Qt Help Project / Custom Filters. +# The QHP_CUST_FILTER_ATTRS tag specifies the list of the attributes of the +# custom filter to add. For more information please see Qt Help Project / Custom +# Filters (see: http://qt-project.org/doc/qt-4.8/qthelpproject.html#custom- +# filters). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_CUST_FILTER_ATTRS = # The QHP_SECT_FILTER_ATTRS tag specifies the list of the attributes this -# project's -# filter section matches. -# -# Qt Help Project / Filter Attributes. +# project's filter section matches. Qt Help Project / Filter Attributes (see: +# http://qt-project.org/doc/qt-4.8/qthelpproject.html#filter-attributes). +# This tag requires that the tag GENERATE_QHP is set to YES. QHP_SECT_FILTER_ATTRS = -# If the GENERATE_QHP tag is set to YES, the QHG_LOCATION tag can -# be used to specify the location of Qt's qhelpgenerator. -# If non-empty doxygen will try to run qhelpgenerator on the generated -# .qhp file. +# The QHG_LOCATION tag can be used to specify the location of Qt's +# qhelpgenerator. If non-empty doxygen will try to run qhelpgenerator on the +# generated .qhp file. +# This tag requires that the tag GENERATE_QHP is set to YES. QHG_LOCATION = -# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files -# will be generated, which together with the HTML files, form an Eclipse help -# plugin. To install this plugin and make it available under the help contents -# menu in Eclipse, the contents of the directory containing the HTML and XML -# files needs to be copied into the plugins directory of eclipse. The name of -# the directory within the plugins directory should be the same as -# the ECLIPSE_DOC_ID value. After copying Eclipse needs to be restarted before -# the help appears. +# If the GENERATE_ECLIPSEHELP tag is set to YES, additional index files will be +# generated, together with the HTML files, they form an Eclipse help plugin. To +# install this plugin and make it available under the help contents menu in +# Eclipse, the contents of the directory containing the HTML and XML files needs +# to be copied into the plugins directory of eclipse. The name of the directory +# within the plugins directory should be the same as the ECLIPSE_DOC_ID value. +# After copying Eclipse needs to be restarted before the help appears. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. GENERATE_ECLIPSEHELP = NO -# A unique identifier for the eclipse help plugin. When installing the plugin -# the directory name containing the HTML and XML files should also have -# this name. +# A unique identifier for the Eclipse help plugin. When installing the plugin +# the directory name containing the HTML and XML files should also have this +# name. Each documentation set should have its own identifier. +# The default value is: org.doxygen.Project. +# This tag requires that the tag GENERATE_ECLIPSEHELP is set to YES. ECLIPSE_DOC_ID = org.doxygen.Project -# The DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) -# at top of each HTML page. The value NO (the default) enables the index and -# the value YES disables it. Since the tabs have the same information as the -# navigation tree you can set this option to NO if you already set -# GENERATE_TREEVIEW to YES. +# If you want full control over the layout of the generated HTML pages it might +# be necessary to disable the index and replace it with your own. The +# DISABLE_INDEX tag can be used to turn on/off the condensed index (tabs) at top +# of each HTML page. A value of NO enables the index and the value YES disables +# it. Since the tabs in the index contain the same information as the navigation +# tree, you can set this option to YES if you also set GENERATE_TREEVIEW to YES. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. DISABLE_INDEX = NO # The GENERATE_TREEVIEW tag is used to specify whether a tree-like index -# structure should be generated to display hierarchical information. -# If the tag value is set to YES, a side panel will be generated -# containing a tree-like index structure (just like the one that -# is generated for HTML Help). For this to work a browser that supports -# JavaScript, DHTML, CSS and frames is required (i.e. any modern browser). -# Windows users are probably better off using the HTML help feature. -# Since the tree basically has the same information as the tab index you -# could consider to set DISABLE_INDEX to NO when enabling this option. +# structure should be generated to display hierarchical information. If the tag +# value is set to YES, a side panel will be generated containing a tree-like +# index structure (just like the one that is generated for HTML Help). For this +# to work a browser that supports JavaScript, DHTML, CSS and frames is required +# (i.e. any modern browser). Windows users are probably better off using the +# HTML help feature. Via custom stylesheets (see HTML_EXTRA_STYLESHEET) one can +# further fine-tune the look of the index. As an example, the default style +# sheet generated by doxygen has an example that shows how to put an image at +# the root of the tree instead of the PROJECT_NAME. Since the tree basically has +# the same information as the tab index, you could consider setting +# DISABLE_INDEX to YES when enabling this option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. -GENERATE_TREEVIEW = YES +GENERATE_TREEVIEW = NO -# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values -# (range [0,1..20]) that doxygen will group on one line in the generated HTML -# documentation. Note that a value of 0 will completely suppress the enum -# values from appearing in the overview section. +# The ENUM_VALUES_PER_LINE tag can be used to set the number of enum values that +# doxygen will group on one line in the generated HTML documentation. +# +# Note that a value of 0 will completely suppress the enum values from appearing +# in the overview section. +# Minimum value: 0, maximum value: 20, default value: 4. +# This tag requires that the tag GENERATE_HTML is set to YES. ENUM_VALUES_PER_LINE = 4 -# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be -# used to set the initial width (in pixels) of the frame in which the tree -# is shown. +# If the treeview is enabled (see GENERATE_TREEVIEW) then this tag can be used +# to set the initial width (in pixels) of the frame in which the tree is shown. +# Minimum value: 0, maximum value: 1500, default value: 250. +# This tag requires that the tag GENERATE_HTML is set to YES. TREEVIEW_WIDTH = 250 -# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open -# links to external symbols imported via tag files in a separate window. +# When the EXT_LINKS_IN_WINDOW option is set to YES doxygen will open links to +# external symbols imported via tag files in a separate window. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. EXT_LINKS_IN_WINDOW = NO -# Use this tag to change the font size of Latex formulas included -# as images in the HTML documentation. The default is 10. Note that -# when you change the font size after a successful doxygen run you need -# to manually remove any form_*.png images from the HTML output directory -# to force them to be regenerated. +# Use this tag to change the font size of LaTeX formulas included as images in +# the HTML documentation. When you change the font size after a successful +# doxygen run you need to manually remove any form_*.png images from the HTML +# output directory to force them to be regenerated. +# Minimum value: 8, maximum value: 50, default value: 10. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_FONTSIZE = 10 # Use the FORMULA_TRANPARENT tag to determine whether or not the images -# generated for formulas are transparent PNGs. Transparent PNGs are -# not supported properly for IE 6.0, but are supported on all modern browsers. -# Note that when changing this option you need to delete any form_*.png files -# in the HTML output before the changes have effect. +# generated for formulas are transparent PNGs. Transparent PNGs are not +# supported properly for IE 6.0, but are supported on all modern browsers. +# +# Note that when changing this option you need to delete any form_*.png files in +# the HTML output directory before the changes have effect. +# The default value is: YES. +# This tag requires that the tag GENERATE_HTML is set to YES. FORMULA_TRANSPARENT = YES -# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax -# (see http://www.mathjax.org) which uses client side Javascript for the -# rendering instead of using prerendered bitmaps. Use this if you do not -# have LaTeX installed or if you want to formulas look prettier in the HTML -# output. When enabled you may also need to install MathJax separately and -# configure the path to it using the MATHJAX_RELPATH option. +# Enable the USE_MATHJAX option to render LaTeX formulas using MathJax (see +# http://www.mathjax.org) which uses client side Javascript for the rendering +# instead of using prerendered bitmaps. Use this if you do not have LaTeX +# installed or if you want to formulas look prettier in the HTML output. When +# enabled you may also need to install MathJax separately and configure the path +# to it using the MATHJAX_RELPATH option. +# The default value is: NO. +# This tag requires that the tag GENERATE_HTML is set to YES. USE_MATHJAX = NO -# When MathJax is enabled you need to specify the location relative to the -# HTML output directory using the MATHJAX_RELPATH option. The destination -# directory should contain the MathJax.js script. For instance, if the mathjax -# directory is located at the same level as the HTML output directory, then -# MATHJAX_RELPATH should be ../mathjax. The default value points to -# the MathJax Content Delivery Network so you can quickly see the result without -# installing MathJax. -# However, it is strongly recommended to install a local -# copy of MathJax from http://www.mathjax.org before deployment. +# When MathJax is enabled you can set the default output format to be used for +# the MathJax output. See the MathJax site (see: +# http://docs.mathjax.org/en/latest/output.html) for more details. +# Possible values are: HTML-CSS (which is slower, but has the best +# compatibility), NativeMML (i.e. MathML) and SVG. +# The default value is: HTML-CSS. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_FORMAT = HTML-CSS + +# When MathJax is enabled you need to specify the location relative to the HTML +# output directory using the MATHJAX_RELPATH option. The destination directory +# should contain the MathJax.js script. For instance, if the mathjax directory +# is located at the same level as the HTML output directory, then +# MATHJAX_RELPATH should be ../mathjax. The default value points to the MathJax +# Content Delivery Network so you can quickly see the result without installing +# MathJax. However, it is strongly recommended to install a local copy of +# MathJax from http://www.mathjax.org before deployment. +# The default value is: http://cdn.mathjax.org/mathjax/latest. +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_RELPATH = http://cdn.mathjax.org/mathjax/latest -# The MATHJAX_EXTENSIONS tag can be used to specify one or MathJax extension -# names that should be enabled during MathJax rendering. +# The MATHJAX_EXTENSIONS tag can be used to specify one or more MathJax +# extension names that should be enabled during MathJax rendering. For example +# MATHJAX_EXTENSIONS = TeX/AMSmath TeX/AMSsymbols +# This tag requires that the tag USE_MATHJAX is set to YES. MATHJAX_EXTENSIONS = -# When the SEARCHENGINE tag is enabled doxygen will generate a search box -# for the HTML output. The underlying search engine uses javascript -# and DHTML and should work on any modern browser. Note that when using -# HTML help (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets -# (GENERATE_DOCSET) there is already a search function so this one should -# typically be disabled. For large projects the javascript based search engine -# can be slow, then enabling SERVER_BASED_SEARCH may provide a better solution. +# The MATHJAX_CODEFILE tag can be used to specify a file with javascript pieces +# of code that will be used on startup of the MathJax code. See the MathJax site +# (see: http://docs.mathjax.org/en/latest/output.html) for more details. For an +# example see the documentation. +# This tag requires that the tag USE_MATHJAX is set to YES. + +MATHJAX_CODEFILE = + +# When the SEARCHENGINE tag is enabled doxygen will generate a search box for +# the HTML output. The underlying search engine uses javascript and DHTML and +# should work on any modern browser. Note that when using HTML help +# (GENERATE_HTMLHELP), Qt help (GENERATE_QHP), or docsets (GENERATE_DOCSET) +# there is already a search function so this one should typically be disabled. +# For large projects the javascript based search engine can be slow, then +# enabling SERVER_BASED_SEARCH may provide a better solution. It is possible to +# search using the keyboard; to jump to the search box use + S +# (what the is depends on the OS and browser, but it is typically +# , /