Indigresso Wiki

Open Source Stuff for DASH7

User Tools

Site Tools


opentag:otlib:otapi

OTAPI (OTlib)

The OpenTag C API for internal, function-based programming on the server-side is called OTAPI. OTAPI is not defined in DASH7 Mode 2, it is an API purpose-built for OpenTag that contains functionality that can be used to work with DASH7.

File Organization

OTAPI declarations are contained in OTlib and spread across several files that have the name “OTAPI” in them.

  • OTAPI.h: main header for OTAPI that bundles the rest of OTAPI into a single header.
  • OTAPI_c.h: C functions available to OTAPI
  • OTAPI_tmpl.h: data templates used by OTAPI functions (and often the rest of OTlib as well)

OTAPI function implementations are stored in the code modules that are appropriate to the features that each OTAPI function needs to use. For example, OTAPI functions that work directly with session data with be stored in the session module, OTAPI functions that need to work with M2QP data are stored in the M2QP module, etc. Below is a list of the current modules and code files, stored in OTlib, that contain some OTAPI function implementations.

  • Session Module (session.c): implementations for OTAPI session functions
  • System/Kernel (in kernel): implementations for OTAPI system functions
  • M2QP Module (session.c): implementations for OTAPI Query/M2QP functions

Usage Notes

Existing OTAPI functions are very low-level, and they have a direct relationship with OTlib functions. Therefore, using OTAPI functions is like “building with small blocks.” It often takes many OTAPI functions, organized in a specific way, in order to build a dialog or achieve whatever other sort of functionality is desired. Therefore, using OTAPI functions correctly requires some knowledge of the DASH7 specification. Users may build extensions to OTAPI that bundle multiple OTAPI calls into single routines, but the nature of these “bundling” routines is very application-specific. OTlib must be very lightweight and generic, so the OTAPI is also very generic. In time, many easy-to-use, application-specific bundles will be available to OpenTag users looking for simpler interfaces.

OTAPI Function Design

OTAPI functions have a mostly consistent design.

Common Form

ot_u16 otapi_function(ot_u8* status, void* template)

Return Value
OTAPI function MUST all return a 16 bit value (ot_u16). In the C header, this is an unsigned 16 bit integer, although the data can be anything.

Status Argument
OTAPI functions should take an 8 bit pointer value (ot_u8*), which reports a status value (zero on failure, non-zero on success). Functions that do not take a status argument are special cases, and these functions can be assumed to always run successfully (implicit status is non-zero).

Template Argument
OTAPI functions should take a template pointer to a data structure. This is the input data that goes into the OTAPI function, which allows easy transition from an ALP-type input stream to C-function argument. It is not always (void*), but it is always a structure pointer.

Special Case Form

ot_u16 otapi_function(...);

Special-case OTAPI functions are occasionally used when there is a substantial code-efficiency gain that can be attained by using a special case form rather than the common form (above). New OTAPI functions should not use special-case form.

OTAPI Templates (OTlib/OTAPI_tmpl.h)

Templates fit into the Common Form OTAPI function. The same templates are often used elsewhere in OpenTag, in order to make the data transition between OTAPI to OTlib nearly effortless, with as little data-copying as possible and no double-bufferring unless it is absolutely necessary.

Below is the code from OTAPI_tmpl.h, which can also be found in the Doxygen documentation.

#include "OT_types.h"
#include "OT_config.h"

#define __SIZEOF(TMPL)      (__SIZEOF_##TMPL)
#define __ALLOCOF(TMPL)     ((__SIZEOF_##TMPL + (PLATFORM_WORD_SIZE-1))/PLATFORM_WORD_SIZE)

/// Veelite Templates
#define __SIZEOF_vladdr_tmpl (1+1)
typedef struct {
    ot_u8   block;
    ot_u8   id;
} vladdr_tmpl;

#define __SIZEOF_vlheader_tmpl (1+1+1+1+2+2)
typedef struct {
    ot_u8   block;
    ot_u8   id;
    ot_u8   permissions;
    ot_u8   is_mirrored;
    ot_u16  length;
    ot_u16  alloc;
} vlheader_tmpl;

#define __SIZEOF_vldata_tmpl (2+2+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u16  offset;
    ot_u16  bytes;
    ot_u8*  data;
} vldata_tmpl;


/// Session Template

#define __SIZEOF_session_tmpl (1+1+1+1+1+2)
typedef struct {
    ot_u8   channel;
    ot_u8   subnet;
    ot_u8   subnetmask;
    ot_u8   flags;
    ot_u8   flagmask;
    ot_u16  timeout;
} session_tmpl;


/// Mode 2 MAC/Protocol Templates
typedef enum {
    ADDR_unicast    = 0x00,
    ADDR_broadcast  = 0x40,
    ADDR_anycast    = 0x80,
    ADDR_multicast  = 0xC0
} addr_type;


#define __SIZEOF_adv_tmpl (2+2+2)
typedef struct {
    ot_u16 count;
    ot_u16 duty_on;
    ot_u16 duty_off;
} adv_tmpl;


#define __SIZEOF_chanlist_tmpl (2+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u16 length;
    ot_u8* list;
} chanlist_tmpl;


#define __SIZEOF_csma_tmpl (1+2+2+2)
typedef struct {
    ot_u8  csma_type;
    ot_u16 csma_guard_us;
    ot_u16 csma_guess_us;       // usually determined by algorithm
    ot_u16 csma_timeout;        // usually determined by algorithm
} csma_tmpl;


#define __SIZEOF_id_tmpl (1+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8 length;
    ot_u8* value;
} id_tmpl;


#define __SIZEOF_idlist_tmpl (1+1+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8 idcount;
    ot_u8 listlen;
    ot_u8* idlist;
} idlist_tmpl;


#define __SIZEOF_routing_tmpl (1+1+(3*__ALLOCOF(id_tmpl))
typedef struct {
    ot_u8   hop_code;  
    ot_u8   hop_ext;
    id_tmpl dlog;
    id_tmpl orig;
    id_tmpl dest;
} routing_tmpl;



/// Mode 2 Protocol Templates

#define __SIZEOF_ack_tmpl (1+1+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8   count;
    ot_u8   length;
    ot_u8*  list;
} ack_tmpl;


#define __SIZEOF_command_tmpl (1+1+1)
typedef struct {
    ot_u8  type;
    ot_u8  opcode;
    ot_u8  extension;
} command_tmpl; 


typedef enum {
    CMDEXT_none             = 0,
    CMDEXT_no_response      = 0x02,
    CMDEXT_no_csma          = 0x04,
    CMDEXT_ca_raind         = (1<<3),
    CMDEXT_ca_aind          = (2<<3),
    CMDEXT_ca_mac           = (7<<3)
} command_extensions;


typedef enum {
    CMD_announce_file            = 0,
    CMD_announce_series          = 1,
    CMD_inventory_on_file        = 2,
    CMD_inventory_on_series      = 3,
    CMD_udp_on_file              = 4,
    CMD_udp_on_series            = 5,
    CMD_collect_file_on_file     = 6,
    CMD_collect_series_on_file   = 7,
    CMD_collect_file_on_series   = 8,
    CMD_collect_series_on_series = 9,
    CMD_request_datastream       = 12,
    CMD_propose_datastream       = 13,
    CMD_ack_datastream           = 14,
    CMD_reserved                 = 15
} command_opcodes;


typedef enum {
    CMDTYPE_response            = 0,
    CMDTYPE_error               = (1 << 4),
    CMDTYPE_na2p_request        = (2 << 4),
    CMDTYPE_a2p_init_request    = (4 << 4),
    CMDTYPE_a2p_inter_request   = (5 << 4),
    CMDTYPE_a2p_final_request   = (7 << 4)
} command_types;


#define __SIZEOF_error_tmpl (1+1+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8   code;
    ot_u8   subcode;
    ot_u8*  data;
} error_tmpl;


#define __SIZEOF_dialog_tmpl (2+2+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u16 timeout;
    ot_u16 channels;
    ot_u8* chanlist;
} dialog_tmpl; 


#define __SIZEOF_dp_tmpl (2+1+1+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u16  data_condition;
    ot_u8   length;
    ot_u8   pid;
    ot_u8*  data;
} dp_tmpl;


#define __SIZEOF_isfcall_tmpl (1+1+2+2)
typedef struct {
    ot_u8   is_series;
    ot_u8   isf_id;
    ot_s16  max_return;
    ot_s16  offset;
} isfcall_tmpl;


#define __SIZEOF_isfcomp_tmpl (1+1+2)
typedef struct {
    ot_u8   is_series;
    ot_u8   isf_id;
    ot_s16  offset;
} isfcomp_tmpl;


#define __SIZEOF_isfreturn_tmpl (1+1+1+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8   isf_id;
    ot_u8   offset;
    ot_u8   length;
    ot_u8*  data;
} isfreturn_tmpl;


#define __SIZEOF_isfseriesreturn_tmpl (1+1+2+2+(2*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8   isfs_id;
    ot_u8   series_length;
    ot_s16  contents_offset;
    ot_s16  content_length;
    ot_u8*  series_data;
    ot_u8*  contents_data;
} isfseriesreturn_tmpl;


typedef enum {
    QCODE_ismasked          = 0x80,
    QCODE_nonnull           = 0,
    QCODE_notequal          = 0x20,
    QCODE_equal             = 0x21,
    QCODE_lessthan          = 0x22,
    QCODE_lessthan_equal    = 0x23,
    QCODE_greaterthan       = 0x24,
    QCODE_greaterthan_equal = 0x25,
    QCODE_search            = 0x26
} query_codes;


#define __SIZEOF_query_tmpl (1+1+(2*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8   code;
    ot_u8   length;
    ot_u8*  mask;
    ot_u8*  value;
} query_tmpl;


#define __SIZEOF_shell_tmpl (1+1+1+(1*PLATFORM_POINTER_SIZE))
typedef struct {
    ot_u8   req_port;
    ot_u8   resp_port;
    ot_u8   data_length;
    ot_u8*  data;
} shell_tmpl;

OTlib/OTAPI_c.h

Below is the code from OTAPI_c.h, which can also be found in the Doxygen documentation. Here is where all of the OTAPI functions are defined.

#include "OT_types.h"
#include "OT_config.h"
#include "OTAPI_tmpl.h"


/******************************************************************************
  * System API Functions (implemented in system.c)
  *
  * @note   Session management is typically done via the System module.
  *
  * Request building process notes:
  * 1. Determin session parameters and store into a session_tmpl struct
  * 2. Call otapi_new_session() with the session_tmpl as a parameter
  * 3. Call otapi_open_request()
  * 4. Call transport protocol constructors (i.e. M2QP otapi functions)
  * 5. Call otapi_close_request()
  * 6. Call otapi_start_dialog() or otapi_start_flood() to send the request
  *
  * This process allows total configurability of the request.  If your 
  * application can be simplified, and it does not need total configurability,
  * you can pretty easily write subroutines that wrap this process into a single
  * function that is simple to use.
  *****************************************************************************/

#define OTAPI_SYSTEM_FUNCTIONS  6

/** @brief Refreshes system settings, wipes sessions, and brings to idle.
  * @param  none
  * @retval ot_u16      0/1 on failure/success
  * @ingroup OTAPI_c
  * @sa sys_refresh()
  *
  * Despite the name, otapi_sysinit() is a wrapper for sys_refresh() and not
  * sys_init().  sys_refresh(), and hence otapi_sysinit(), will restart OpenTag 
  * without clobbering the user application callbacks & data objects.
  */
ot_u16 otapi_sysinit();


/** @brief Manually creates a new ad-hoc session and prepares system.
  * @param  s_tmpl      (session_tmpl*) Session parameters
  * @retval ot_u16      The session number (see otapi_session_number)
  * @ingroup OTAPI_c
  * @sa otapi_session_number()
  * @sa otapi_new_request()
  * @sa otapi_start_flood()
  *
  * Call this when some event occurs that makes you want to send a DASH7 packet.
  * A session needs to exist for the DASH7 engine to do its job.  All sessions
  * that you would generate by this function are ad-hoc, meaning they are not
  * scheduled for some time in the future (they happen right away).  Scheduled
  * sessions are reserved for internal DASH7 usage.
  */
ot_u16 otapi_new_session(session_tmpl* s_tmpl);


/** @brief  Manually creates (and opens) a request frame in the top session
  * @param  addr        (addr_type) enumerated addressing method (unicast, broadcast, etc)
  * @param  routing     (routing_tmpl*) A routing_tmpl
  * @retval ot_u16      The post-op length of the TX queue in bytes
  * @ingroup OTAPI_c
  * @sa otapi_close_request()
  * @sa otapi_new_session()
  *
  * Most often you will call this immediately after otapi_new_session().  Any
  * kind of event-generated frame/packet in DASH7 is always a request.  A DASH7
  * response is defined as something that follows a request, so if you are 
  * starting a new ad-hoc session, the outgoing packet will always be a request.
  *
  * The second input parameter, routing, is a void pointer and must be used
  * according to the value of addr.  
  * - If addr is BROADCAST or MULTICAST, routing should = NULL.  
  * - If addr is UNICAST, routing should be of type (id_tmpl*).
  * - If addr is ANYCAST, routing should be of type (routing_tmpl*)
  *
  * As you can see, Anycast addressing is the only form of request addressing  
  * that supports multi-hop routing.
  */
ot_u16 otapi_open_request(addr_type addr, routing_tmpl* routing);


/** @brief Manually finishes a request frame in the top session
  * @retval ot_u16      The post-op length of the TX queue in bytes
  * @ingroup OTAPI_c
  * @sa otapi_open_request()
  * @sa otapi_start_flood()
  * @sa otapi_start_dialog()
  *
  * In certain cases, footer data needs to be appended to the frame (mostly,
  * this is when you are doing some kind of encryption).  In these cases, 
  * otapi_close_request() will make sure to put it in the TX queue after the
  * frame data.
  *
  * Best practice is to always call otapi_close_request() when you are done
  * building the request.  When there is no encryption, you technically do not
  * need to call it, but this can lead to bugs in your application if you 
  * decide to add encryption later.  (If you are not encrypting, it adds maybe
  * only 8 instruction cycles to your runtime)
  */
ot_u16 otapi_close_request();


/** @brief  Begins a DASH7 M2AdvP flood onto the top session.
  * @param  flood_duration  (ot_u16) Number of ticks for the flood duration
  * @retval ot_u16          0/1 on failure/success of the flood initialization
  * @ingroup OTAPI_c
  * @sa otapi_new_session()
  * @sa otapi_new_request()
  * @sa otapi_start_dialog()
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  *
  * An M2AdvP flood is a way to take control of a channel so that a session can 
  * be guaranteed to occur at some point in the near future (precisely, a few 
  * ticks after the time of flood initialization + flood_duration).  
  *
  * To initialize a flood, a session has to be started with otapi_new_session().
  * Then call otapi_open_request(), whatever M2QP functions you need to build 
  * that request, and otapi_close_request().  Then call otapi_start_flood() to
  * begin the flood.  When the flood is over, OpenTag will automatically begin
  * the request dialog (no need to call otapi_start_dialog()).
  */
ot_u16 otapi_start_flood(ot_u16 flood_duration);


/** @brief  Begins a DASH7 dialog onto the top session, without a flood.
  * @retval ot_u16          0/1 on failure/success of the dialog initialization
  * @ingroup OTAPI_c
  * @sa otapi_new_session()
  * @sa otapi_new_request()
  * @sa otapi_start_flood()
  *
  * Call this when you want to kick-off a request that has been already built
  * using the normal request-building process.
  *
  * If you are using a flood prior to the request, use otapi_start_flood() and 
  * not this function.  It will automatically kick-off the request dialog when 
  * the flood is complete.
  *
  * If you are not using a flood prior to the request, then use this function.
  */
ot_u16 otapi_start_dialog();



/******************************************************************************
  * Session API Functions (implemented in session.c)
  * The session API is special-purpose and does not follow the standard form.
  *                                                                           
  * @note   Session management is generally automatic.  These functions just  
  *         allow future exploration at the API/App level                     
  *****************************************************************************/

#define OTAPI_SESSION_FUNCTIONS     3

/** @brief Returns a 16 bit value uniquely corresponding to the top session
  * @param  none
  * @retval ot_u16      The 16 bit session value
  * @ingroup OTAPI_c
  *
  * The session value is actually just a concatenation of the 8 bit "channel"
  * element (channel ID) and the 8 bit "dialog_id" element (random dialog num)
  * that are part of a session structure.  The session stack may contain only
  * one scheduled channel for each of the supported channels at any given time,
  * so the session value will always be unique.
  *
  * The return value is always 0 for the case when the stack is empty.
  */
ot_u16 otapi_session_number();


/** @brief Deletes all expired sessions in the session stack
  * @param  none
  * @retval ot_u16      The size of the session stack after flushing
  * @ingroup OTAPI_c
  */
ot_u16 otapi_flush_sessions();


/** @brief Indicates if a given channel is already in the session stack.
  * @param  chan_id     (ot_u8) channel ID to check for blocking
  * @retval ot_u16      0/1 if supplied channel ID is unblocked/blocked
  * @ingroup OTAPI_c
  *
  * The session stack can only contain one session of a given channel at any
  * given time.  Sessions are not typically very long, so this feature should
  * not be a hinderance to DASH7 operation.  On the other hand, it does allow
  * simplicity by removing needs for priorities and such in session mgmt.
  */
ot_u16 otapi_is_session_blocked(ot_u8 chan_id);




/******************************************************************************
  * M2QP API Functions (implemented in M2QP.c)
  * The M2QP API follows the standard form.  Future API extensions will follow
  * the form: ot_u16 otapi_function(ot_u8* status, void* data_type)
  *****************************************************************************/

#define OTAPI_M2QP_FUNCTIONS    11

/** @brief Writes M2QP command parameters onto the request TX queue
  * @param status       (ot_u8*) returns a status code (0 = error)
  * @param command      (command_tmpl*) command input parameter template
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  * 
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  *
  */
ot_u16 otapi_put_command_tmpl(ot_u8* status, command_tmpl* command);


/** @brief Write A2P/NA2P dialog parameters onto the request TX queue
  * @param status       (ot_u8*) returns a status code (0 = error)
  * @param dialog       (dialog_tmpl*) dialog input parameter template
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd code == 0x02
  * 
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  *
  * One spec-driven usage note is that, by setting rx_channels = 0, the chanlist
  * argument will be ignored and the pre-existing settings (from the request TX)
  * will be used automatically.
  */
ot_u16 otapi_put_dialog_tmpl(ot_u8* status, dialog_tmpl* dialog);


/** @brief Write M2QP Query parameters onto the end of the TX queue
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  query       (query_tmpl*) query input parameter template
  * @retval ot_u16       post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x03
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  *
  * query->length param: the query token and mask are the same length, which is
  * the number of bytes set in this parameter.
  *
  * query->code param: b7 is 0/1 if the mask is disabled/enabled.
  *                    (see Mode 2 spec for further definition)
  */
ot_u16 otapi_put_query_tmpl(ot_u8* status, query_tmpl* query);


/** @brief  Write a device ack list onto the end of the TX queue
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  ack         (ack_tmpl*) ack input parameter template
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x04
  */
ot_u16 otapi_put_ack_tmpl(ot_u8* status, ack_tmpl* ack);


/** @brief  Writes an error tmpl to a response.  Not currently implemented.
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  error       (error_tmpl*) error input parameter template
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x05
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  */
ot_u16 otapi_put_error_tmpl(ot_u8* status, error_tmpl* error);


/** @brief  Writes ISF comparison data to the request queue.
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  isfcomp     (comp_tmpl*) isf comparison data for request
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x06
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  */
ot_u16 otapi_put_isf_comp(ot_u8* status, isfcomp_tmpl* isfcomp);


/** @brief  Writes ISF call data to the request queue.
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  isfcomp     (comp_tmpl*) isf call data for request
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x07
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  */
ot_u16 otapi_put_isf_call(ot_u8* status, isfcall_tmpl* isfcall);


/** @brief "Calls" ISF or ISF series and writes the return data to the TX Queue 
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  isfcall     (isfcall_tmpl*) ISF call template (matches typedef)
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x08
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  */
ot_u16 otapi_put_isf_return(ot_u8* status, isfcall_tmpl* isfcall);


/** @brief  Writes the request datastream command, including read directives
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  dsq         (Queue*) Queue where the request datastream is stored
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x09
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  *
  * The request datastream must be non-null, and point to a datastream that
  * carries one or more application subprotocol read directives. The request 
  * datastream (read directives) must be able to fit inside the request frame 
  * of this initial request.
  *
  * The remainder of the datastream handshaking and transfer process is managed
  * automatically.  The complete, received datastream will be loaded into the
  * internal datastream queue, and it can be logged if desired.
  */
ot_u16 otapi_put_reqds(ot_u8* status, Queue* dsq);


/** @brief  Writes the propose datastream command, including optional write directives
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  dsq         (Queue*) Queue where the propose [write] datastream is stored
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x0A
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  *
  * If the proposed datastream is too long to fit inside the initial request
  * frame, it will be placed inside a subsequent datastream transfer.
  *
  * The remainder of the datastream handshaking and transfer process is managed
  * automatically.  The complete, transmitted datastream will be loaded into an
  * internal datastream queue prior to transmission.  The recipient of the 
  * datastream typically writes it to veelite.
  */
ot_u16 otapi_put_propds(ot_u8* status, Queue* dsq);


/** @brief  Writes shell data to the request queue.
  * @param  status      (ot_u8*) returns a status code (0 = error)
  * @param  shell       (shell_tmpl*) Shell template
  * @retval ot_u16      post-op length of the TX queue
  * @ingroup OTAPI_c
  *
  * API dir_cmd == 0x0B
  *
  * This function is implemented in a way that matches a portion of the DASH7
  * Mode 2 spec. To understand the data I/O completely, refer to the spec.
  */
ot_u16 otapi_put_shell_tmpl(ot_u8* status, shell_tmpl* shell);
opentag/otlib/otapi.txt · Last modified: 2012/03/25 20:49 by jpnorair