Indigresso Wiki

Open Source Stuff for DASH7

User Tools

Site Tools


opentag:capi

Differences

This shows you the differences between two versions of the page.

Link to this comparison view

opentag:capi [2011/09/30 20:11] (current)
jpnorair created
Line 1: Line 1:
 +====== C API ======
 +The C API is just callable C functions, each of which is a simplified wrapper for a sequence lower-level OTlib functions. ​ The C API can be used to build requests, create events, and do some other sandboxed features that are part of OpenTag'​s standard OTlib functionality (in other words, if you are an OpenTag kung-fu master, you can just call the OTlib low-level functions directly to get the same effect). ​ That said, the C API functions are cleaner and simpler to use, and just as good if you don't need the deepest level of functionality.
 +
 +===== Relevant Files =====
 +To use the C API, you need to include OTAPI.h in your code.  OTAPI.h will automatically include the appropriate sub-components,​ based on how OT_config.h is configured. ​ The C API functions are defined in the OTAPI_c.h file.  Many of these functions use templates as input. ​ The templates are defined in OTAPI_tmpl.h. ​ These are the two most important OTAPI headers to read in order to learn about the C API.  The C API functions are implemented within the .c modules that best match their featureset. ​ For example, the otapi_system functions are implemented in system.c and the otapi_session functions in session.c.
 +
 +===== Using Low Level Functions =====
 +Experts might want to bypass the C API entirely, in favor of using the low level OpenTag functions themselves. ​ The low level function architecture is not documented as much as the API architecture,​ but you can get an idea of how it works by seeing howe the OTAPI functions are implemented.
 +
 +===== Extensibility =====
 +New OTAPI C functions can be added very easily, if new functionality is desired. ​ Hypothetically,​ you could add as many new OTAPI C functions as can fit on your platform. ​ Realistically,​ there are some limitations due to the linkages to other APIs (DASHForth and ALP).
 +
 +=== General Form ===
 +The general form of a C API function is:\\
 +''​ot_u16 otapi_function_name(ot_u8* status, void* tmpl)''​\\
 +  * The ''​status''​ parameter should be OR'ed or added when there is some sort of problem with the input template.
 +  * The ''​tmpl''​ parameter is a pointer to some data-structure type that contains relevant input data.  In the actual function prototype (defined in OTAPI_c.h), it should not use "​void*"​ type unless the input template is variadic.
 +  * The ot_u16 return value is an unsigned integer. ​ It can have different values, but in all cases "​0"​ means that nothing happened. ​ In most usages, the return value corresponds to a number of bytes present on the TX queue.
 +
 +=== Special Form ===
 +Some C API functions do not obey the General Form.  However, all C API functions return an ''​ot_u16''​ value. ​ Special Form functions typically are Session or System functions that do not do any queue-based data processing.
 +
 +=== Linking to DASHForth ===
 +C API functions can be easily linked to DASHForth words if they are written in the general form (above). ​ The practical limit for DASHForth words is something like 1024, and currently 20 API words are reserved.  ​
 +
 +  * DASHForth can ignore the status input (production) or use it to generate error messages (debug). ​ The production/​debug classification is controllable at a pseudo-runtime level (Forth is a unique language, check it out).
 +  * The template input is Loaded onto the Forth data stack in reverse, to comply with Forth'​s postfix architecture.
 +  * One thing to consider is the return value of the otapi function. ​ This 16 bit value it is what gets pushed onto the Forth data stack after the word is processed.
 +
 +=== Linking to ALP ===
 +Linking a C API function to ALP is easy.  All C API functions are attributed with a two byte identifier, including a class identifier (Directive ID) and a command identifier (Directive Command). ​ In the documentation below, the [class:​command] is presented in the heading for each C API function.
 +
 +  * The practical limit for ALP-API is 16 classes and 127 commands per class.  ​
 +  * The status value is returned via the ALP message pipe (MPipe), preceeding the 16 bit return value
 +  * The template input shall be streamed onto the message pipe.  Any strings/​arrays that the template requires shall be inlined into the ALP directive data.  Data containers are always transported as BIG ENDIAN.
 +
 +
 +
 +===== Some Examples =====
 +Using the C API is like "​building with Legos." ​ In the future, API subroutines will probably be made available that serve as simplified templates. ​ However, the maximum level of functionality can only be achieved through usage of the full C API.
 +
 +One thing you might notice about the design of the C API is that it uses a message-based function call method (using data structures to load parameters) instead of a pure C stack method. ​ The benefit of this method is that C API functions can be directly ported to any type of messaging architecture (which allows direct translation of the application layer).
 +
 +=== Setting up a dialog using broadcast announcement (a beacon) ===
 +<​code>​
 +session_tmpl s_tmpl;
 +command_tmpl cmd;
 +dialog_tmpl dialog;
 +isfcall_tmpl filedata;
 +ot_u8 dialog_chanlist[4];​
 +ot_u8 protocol_status;​
 +
 +s_tmpl.channel ​   = 0x01;    //use channel 01, 
 +s_tmpl.subnet ​    = 0x0F;    //use subnet 0F (universal)
 +s_tmpl.subnetmask = 0x0F;    //use subnet mask 0F (universal)
 +s_tmpl.flags ​     = 0;       //use default network frame flags
 +s_tmpl.flagmask ​  = 0;       //use default network frame flags
 +s_tmpl.timeout ​   = 0;       //Run this session immediately (no delay)
 +
 +cmd.opcode ​       = CMD_announcement_of_file;​
 +cmd.type ​         = 0;       //​Type is only important for Multicasting
 +cmd.extension ​    = 0;       //Not using extension (extension includes advanced features)
 +
 +dialog.timeout ​   = 100;     //100 tick response timeout (97.7 ms)
 +dialog.channels ​  = 1;       //​Allow responses on 1 channel
 +dialog_chanlist[0]= 0x02;    //Hop to channel 02 to receive responses
 +dialog.chanlist ​  = dialog_chanlist;​
 +
 +filedata.is_series= 0;       //​Include data from a single ISF file
 +filedata.isf_id ​  = 0x01;    //Use ISF File 0x01 (Device Parameters)
 +filedata.offset ​  = 0;       //​Start data at beginning of file (0 bytes offset)
 +
 +otapi_new_session(&​s_tmpl);​
 +otapi_open_request(BROADCAST,​ NULL);
 +otapi_put_command_tmpl(&​protocol_status,​ &cmd);
 +otapi_put_dialog_tmpl(&​protocol_status,​ &​dialog);​
 +otapi_put_isf_return(&​protocol_status,​ &​filedata);​
 +otapi_close_request();​
 +
 +// If protocol_status != 1, something was done incorrectly. ​ In that case, we will
 +// log an error message (there is no standard for error messages, so you could put
 +// in whatever you want). ​ If no error, then send the request.
 +if (protocol_status == 1) {
 +    otapi_start_dialog();​
 +}
 +else {
 +    otapi_log_msg(7,​ "​ERR_API",​ 30, "​Command was built incorrectly"​);​
 +}
 +</​code>​
 +
 +
 +===== C API Function Manifest =====
 +
 +==== Session Functions ====
 +The session C API functions create sessions and give information about the session status. ​ The system module does most of these things automatically,​ but you can use the session API if you are cooking up some type of enhanced server-side application. ​ The session C API functions are declared in OTAPI_c.h and implemented in session.c.
 +
 +=== About the Session Stack ===
 +Sessions are stored in a volatile stack. ​ It is volatile, because old sessions are replaced by newly added sessions when the stack gets full.  The stack is insertion-sorted whenever a new session is added. ​ A typical stack is 4 sessions deep, which is more than enough for 99% of use-cases (you can increase of decrease the size of the stack via OT_config.h).
 +
 +=== About Sessions ===
 +Sessions are scheduled dialogs, or currently ongoing dialogs. ​ Dialogs/​Sessions have certain attributes that are maintained throughout the duration of the session. ​ These attributes are stored in the session stack.
 +
 +=== otapi_session_number() [0x80:01] ===
 +Returns a 16 bit value uniquely corresponding to the top session\\
 +arguments: none\\
 +returns: The 16 bit session value
 +Dir Cmd: 0x01
 +
 +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.
 +
 +=== otapi_flush_sessions() [0x80:02] ===
 +Deletes all expired sessions in the session stack\\
 +arguments: none\\
 +returns: The size of the session stack after flushing
 +Dir Cmd: 0x02
 +
 +=== otapi_is_session_blocked(ot_u8 chan_id) [0x80:03] ===
 +Indicates if a given channel is already in the session stack.\\
 +arguments: chan_id (ot_u8) channel ID to check for blocking\\
 +returns: 0/1 if supplied channel ID is unblocked/​blocked
 +Dir Cmd: 0x03
 +
 +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.
 +
 +==== System Functions ====
 +System API functions control the System Module, which itself is responsible for managing the Session Module (therefore, direct access to the Session API is purely optional). ​ The System Module also is responsible for managing the flow of protocol data into and out-of OpenTag. ​ Much of this I/O is automatic. ​ However, API-users are able to manually invoke DASH7 dialogs via the System API.
 +
 +
 +=== otapi_sysinit() - [0x81:01] === 
 +Initializes the system module from the configuration file in veelite.\\
 +Arguments: none\\
 +Returns: (ot_u16) 0/1 on failure/​success\\
 +
 +There are some configuration files in the ISF data that control the way the the system works. ​ When calling this function, data from these files are buffered into the system control matrix. ​ Considering this, you should call this function anytime the matrix is cleared or anytime you want to reset the configuration of the device to the configuration file parameters.
 +
 +
 +=== otapi_new_session(session_tmpl* s_tmpl) - [0x81:02] ===
 +Manually creates a new ad-hoc session and prepares system.\\
 +Arguments: ​ (session_tmpl*) Session parameters\\
 +Returns: (ot_u16) The session number (see otapi_session_number)\\
 +
 +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.
 +
 +
 +=== otapi_open_request(addr_type addr) - [0x81:03] ===
 +Manually creates (and opens) a request frame in the top session\\
 +Arguments: (addr_type) enumerated addressing method (unicast, broadcast, etc)\\
 +Returns: (ot_u16) The post-op length of the TX queue in bytes\\
 +
 +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.
 +
 +
 +=== otapi_close_request() - [0x81:04] === 
 +Manually finishes a request frame in the top session\\
 +Returns: (ot_u16) The post-op length of the TX queue in bytes\\
 +
 +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)
 +
 +
 +=== otapi_start_flood(ot_u16 flood_duration) - [0x81:05] === 
 +Begins a DASH7 M2AdvP flood onto the top session.\\
 +Arguments: ​ flood_duration ​ (ot_u16) Number of ticks for the flood duration\\
 +Returns: (ot_u16) 0/1 on failure/​success of the flood initialization\\
 +
 +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()).
 +
 +
 +=== otapi_start_dialog() - [0x81:06] === 
 +Begins a DASH7 dialog onto the top session, without a flood.\\
 +Returns: (ot_u16) 0/1 on failure/​success of the dialog initialization\\
 +
 +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.
 +
 +
 +==== Query Functions ====
 +After a Dialog is created with the System API, the Dialog is populated with the Query API.  The user should be familiar with the basic templating design of the Mode 2 Protocols (particularly M2QP).
 +
 +
 +=== otapi_put_command_tmpl(ot_u8* status, command_tmpl* cmd) - [0x82:01] ===
 +Write M2QP Command parameters onto the end of the TX queue\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument cmd: (command_tmpl*) command input parameter template\\
 +Returns: (ot_u16) ​ post-op length of the TX queue
 +
 +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. 
 +
 +
 +=== otapi_put_dialog_tmpl(ot_u8* status, dialog_tmpl* dialog) - [0x82:02] ===
 +Write A2P/NA2P dialog parameters onto the request TX queue\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument dialog: (dialog_tmpl*) dialog input parameter template\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
 +
 +
 +=== otapi_put_query_tmpl(ot_u8* status, query_tmpl* query) - [0x82:03] ===
 +Write M2QP Query parameters onto the end of the TX queue\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument query: (query_tmpl*) query input parameter template\\
 +Returns: (ot_u16) ​ post-op length of the TX queue
 +
 +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)
 +
 +
 +=== otapi_put_ack_tmpl(ot_u8* status, ack_tmpl* ack) - [0x82:04] ===
 +Write a device ack list onto the end of the TX queue\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument ack: (ack_tmpl*) ack input parameter template\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +
 +=== otapi_put_error_tmpl(ot_u8* status, error_tmpl* error) - [0x82:05] ===
 +Writes an error tmpl to a response. ​ Not currently implemented.\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument error: (error_tmpl*) error input parameter template\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
 +
 +
 +=== otapi_put_isf_comp(ot_u8* status, isfcomp_tmpl* isfcomp) - [0x82:06] ===
 +Writes ISF comparison data to the request queue.\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument isfcomp: (comp_tmpl*) isf comparison data for request\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
 +
 +
 +=== otapi_put_isf_call(ot_u8* status, isfcall_tmpl* isfcall) - [0x82:07] ===
 +Writes ISF call data to the request queue.\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument isfcomp: (comp_tmpl*) isf call data for request\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
 +  ​
 +
 +=== otapi_put_isf_return(ot_u8* status, isfcall_tmpl* isfcall) - [0x82:08] ===
 +"​Calls"​ ISF or ISF series and writes the return data to the TX Queue\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument isfcall: (isfcall_tmpl*) ISF call template (matches typedef)\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
 +
 +
 +=== otapi_put_reqds(ot_u8* status, Queue* dsq) - [0x82:09] ===
 +Writes the request datastream command, including read directives\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument dsq: (Queue*) Queue where the request datastream is stored\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
 +
 +
 +=== otapi_put_propds(ot_u8* status, Queue* dsq) - [0x82:0A] ===
 +Writes the propose datastream command, including optional write directives\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument dsq: (Queue*) Queue where the propose [write] datastream is stored\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
 +
 +
 +=== otapi_put_shell_tmpl(ot_u8* status, shell_tmpl* shell) - [0x82:0B] ===
 +Writes shell data to the request queue.\\
 +Argument status: (ot_u8*) returns a status code (nonzero = error)\\
 +Argument shell: (shell_tmpl*) Shell template\\
 +Returns: (ot_u16) post-op length of the TX queue
 +
 +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.
  
opentag/capi.txt ยท Last modified: 2011/09/30 20:11 by jpnorair