OpenTag's C API (OTAPI) contains a special-purpose logger module. Logging is such a fundamental feature of embedded applications that it is built-in to OTAPI. The commonly used “printf” function, which can be implemented in unpredictable ways depending on the embedded library you are using, should not be used in OpenTag builds. The Logger functions should be used instead, because they can be guaranteed not to interfere with the kernel or other features.
The Logger module requires that the NDEF module and the MPipe module and compiled into the OpenTag build. This is because Logger requires MPipe as the way to do logging, and MPipe requires NDEF. Additionally, if the Logger ALP is used, the ALP Module needs to be compiled into the build.
The ALP API uses the Protocol ID 0x03 for the Logger. Logger command codes are defined based on the output format of the logger, and the Response bit of the command code (bit 7) will cause echo. Client-to-server logger ALP packets may be ignored.
|Logger ALP Command codes|
|0x00||Payload is raw binary|
|0x01||Payload is UTF-8 text|
|0x02||Payload is Unicode text|
|0x03||Payload is UTF-8 text formatted as Hex numbers with spaces (e.g. 1A 2B 3C …)|
|0x04||Payload is a UTF-8 label followed by raw binary|
|0x05||Payload is a UTF-8 label followed by UTF-8 text|
|0x06||Payload is a UTF-8 label followed by Unicode text|
|0x07||Payload is a UTF-8 label followed by UTF-8 Hex numbers|
UTF-8 label are space-terminated
The Logger module has several built-in functions. Each one outputs data in a different way. Logger is part of OTAPI, so the logger functions follow the "special-case" OTAPI form.
ot_u16 otapi_log(ot_u8 subcode, ot_int length, ot_u8* data)
Basic logging puts a stream of binary data (data) of a pre-defined payload length (length) onto MPipe. The subcode argument allows you to specify the ALP command that gets transferred in the NDEF ID (see the ALP command code table above)
ot_u16 otapi_log_direct(ot_u8* data)
If you have a pre-formatted NDEF/ALP datastream, you can push it over MPipe with this function.
Message logging uses the Logger ALP command codes 4 through 7. UTF-16 Unicode data is not supported in the current OTAPI logger functions (apart from otapi_log() which is supplied with user-defined data). A “Message” is just a space-terminated UTF-8 label that precedes the rest of the logged data.
ot_u16 otapi_log_msg(ot_int label_len, ot_int data_len, ot_u8* label, ot_u8* data)
Log a raw binary message with a UTF-8 label.
ot_u16 otapi_log_hexmsg(ot_int label_len, ot_int data_len, ot_u8* label, ot_u8* data)
Log a Hex Number message with a UTF-8 label
Logger functions are defined in OTAPI.h The relevant parts of OTAPI.h are pasted below, to show the logger function declarations.
/** @brief Log a datastream directly (no double buffering) * @param data (ot_u8*) the pre-formatted datastream (NDEF) * @retval ot_u16 0 on failure, non-zero on non-failure * @ingroup OTAPI_c * * This is the fastest way to log, but the data must be already formatted into * logging format (for official ports, this is NDEF). The data pointed-to by * the data parameter is not double-buffered into an output buffer, so use it * cautiously. */ ot_u16 otapi_log_direct(ot_u8* data); /** @brief Format and log a generic block of data * @param subcode (ot_u8) Type of data that's being logged * @param length (ot_int) length in bytes of the supplied datastream * @param data (ot_u8*) the arbitrary datastream * @retval ot_u16 0 on failure, non-zero on non-failure * @ingroup OTAPI_c * * On the subcode: * The logger directive uses directive ID = 0x04. There is also a subcode byte * in the directive header. System messages and error codes have subcode = 2. * 0x01 is for response logging. You can use any other subcode, although there * might be some standards that emerge. */ ot_u16 otapi_log(ot_u8 subcode, ot_int length, ot_u8* data); #define otapi_log_response(LENGTH, DATA) otapi_log(0x01, LENGTH, DATA) /** @brief Log arbitrary "message," which is type + data. * @param label_len (ot_int) number of bytes/chars in the label * @param data_len (ot_int) number of bytes/chars in the data * @param label (ot_u8*) label byte array * @param data (ot_u8*) data byte array * @retval ot_u16 0 on failure, non-zero on non-failure * @ingroup OTAPI_core * @sa otapi_log_msg * * Similar to otapi_log_raw() except that a label string is applied to the * datastream prior to the data payload. The label string is zero-terminated, * so it should take on ASCII values or similar. */ ot_u16 otapi_log_msg(ot_int label_len, ot_int data_len, ot_u8* label, ot_u8* data); /** @brief Identical to otapi_log_msg, but converts data into ASCII Hex * @param label_len (ot_int) number of bytes/chars in the label * @param data_len (ot_int) number of bytes/chars in the data * @param label (ot_u8*) label byte array * @param data (ot_u8*) data byte array * @retval ot_u16 0 on failure, non-zero on non-failure * @ingroup OTAPI_core * @sa otapi_log_msg * * The hex output is in capital letters. One byte of data is converted into * three bytes of hex output -- two characters and a space -- therefore the * output buffer must be oversized in order for this function to print out * a full, 255 byte data frame. * * @note otapi_log_hexmsg is intended for usage with debugging builds or to push * messages to clients that do not have message interpreters (namely, binary * to hex conversion on the client side). Needless to say, it is a better * use of resources to do any kind of message interpreting on the cilent side. */ ot_u16 otapi_log_hexmsg(ot_int label_len, ot_int data_len, ot_u8* label, ot_u8* data);