Exportable version of WizziLab's modem driver.

Dependents:   modem_ref_helper

include/modem_ref.h

Committer:
Jeej
Date:
2021-02-19
Revision:
60:08efaaca0e83
Parent:
59:3b38b5f499db
Child:
61:820395fc5572

File content as of revision 60:08efaaca0e83:

/// @copyright
/// ========================================================================={{{
/// Copyright (c) 2013-2016 WizziLab                                           /
/// All rights reserved                                                        /
/// =========================================================================}}}
/// @endcopyright

//  =======================================================================
/// @file       modem_ref.h
/// @brief      Wizzilab Modem Reference Driver Implementation
///             Source code should be disclosable and easily portable to
///             any architecture.
//  =======================================================================

#ifndef __MODEM_REF_H__
#define __MODEM_REF_H__

#include "mbed.h"
#include "hal_types.h"

#include "alp_spec.h"
#include "alp_helpers.h"
#include "alp_payload.h"

// Stuff depending on implementation
#ifdef _ARCH_WIZZILAB_
    // Map debug features on Wizzilab's kernel
    #include "kal.h"
    #define L_API           (1 << 1)
    #define L_URC           (1 << 2)
    #define L_SER           (1 << 3)
    #define ASSERT(c,...)   kal_dbg_assert(c, ##__VA_ARGS__)
    #define DPRINT(l,...)   do {kal_dbg_cprintf(TLEV(7,l), ##__VA_ARGS__);} while(0)
    #define MALLOC(s)       kal_malloc(s)
    #define FREE(s)         kal_free(s)
#else
    // TODO Map on host architecture
#endif

// Maximum number of concurrent 'users'
#define MAX_USER_NB     (8)

// Depending on Host needs/capacities, choose variable-size buffer allocation style
#if 1 // Auto stack alloc
    #define MAX_CMD_BUFFER_SIZE             256
    #define ALLOC_BUFFER(_t,_b,_size)       _t _b[MAX_CMD_BUFFER_SIZE];
    //#define ALLOC_BUFFER(_t,_b,_size)     _t _b[_size]; // If VLA available...
    #define DEALLOC_BUFFER(_b)
#else // Dynamic alloc
    #define ALLOC_BUFFER(_t,_b,_size)       _t* _b = MALLOC(_size);
    #define DEALLOC_BUFFER(_b)              FREE(_b);
#endif

//======================================================================
// Modem Serial Link input/output functions
//==================================================================={{{
// ALP protocol is conveyed on serial link encapsulated in WizziCom (WC)
// packets.
// WC Serial protocol:
// +--------------+--------+--------+--------+---- - - - - - - - - - - --------+
// |     SYNC     |   LEN  |   SEQ  | FLOWID |             PAYLOAD             |
// +--------------+--------+--------+--------+---- - - - - - - - - - - --------+
// |    2 bytes   | 1 byte | 1 byte | 1 byte |            LEN bytes            |
// |<------------>|<------>|<------>|<------>|<--- - - - - - - - - - - ------->|
#define WC_SYNC_BYTE_0          0x01
#define WC_SYNC_BYTE_1          0x1F
#define WC_HEADER_SIZE          5

#define WC_SYNC0_OFFSET         0
#define WC_SYNC1_OFFSET         1
#define WC_LEN_OFFSET           2
#define WC_SEQ_OFFSET           3
#define WC_FLOWID_OFFSET        4

// =======================================================================
// wm_cfg_t
// -----------------------------------------------------------------------
/// Modem Configuration
// ===================================================================={{{
TYPEDEF_STRUCT_PACKED
{
    /// Automatic openning of D7A stack
    u8  autostart_d7a;
    /// Automatic 'Join' of LoRaWAN stack
    u8  autostart_lwan;
    /// Automatic procedure start time (sec)
    u16 autostart_delay_s;
    /// Debug COM port number (N/A:KAL_COM_NULL)
    u8  dbg_com;
} wm_cfg_t;
//}}}

// Input:Serial-traffic coming from Modem must be packetized in WC chuncks
// before being sent to modem-driver through 'modem_input'.
// An example deserializer can be found in "wc_deserialized.c".
//======================================================================
// modem_ref_input
//----------------------------------------------------------------------
/// @brief  Parse packets and handles calls to relevant callbacks.
/// @param  flowid      : WizziCom FlowID.
/// @param  payload     : pointer to payload buffer.
/// @param  size        : payload size in bytes.
//======================================================================
void modem_ref_input(u8 flowid, u8* payload, u8 size);

// Output:Modem-driver sends data to Modem through calls to the 'send'
// function passed in 'modem_ref_open'.
// 'send' must be provided by the host application.
//======================================================================
// fx_serial_send_t
//----------------------------------------------------------------------
/// @brief  Send concatenation of 2 buffers of given size over serial link.
/// @param  buffer1     : Pointer to the 1st data buffer to be sent
/// @param  size1       : Size in bytes of the 1st buffer to be sent
/// @param  buffer2     : Pointer to the 2nd data buffer to be sent
/// @param  size2       : Size in bytes of the 2nd buffer to be sent
/// @return               number of bytes sent.
/// @note                 either buffers can be of size zero.
/// @note                 buffer1 is used for WC header
/// @note                 buffer2 is used actual payload
//======================================================================
typedef int  (fx_serial_send_t)     (u8 type, u8* buffer2, u8 size2);

//======================Low-Level-API================================}}}

//======================================================================
// High-level API that must be provided by the host application
//==================================================================={{{

//======================================================================
// fx_read_t
//----------------------------------------------------------------------
/// @brief  Called when ALP-Read is requested by the modem.
///         Function must perform required actions to fullfil the request
///         then should call 'respond_read' (or 'respond' in case of error)
/// @param  fid         : File ID
/// @param  offset      : Access Offset in bytes
/// @param  length      : Access Size in bytes
/// @param  id          : ID of the request
//======================================================================
typedef void (fx_read_t)            (u8 action, u8 fid, u32 offset, u32 length, int id);

//======================================================================
// fx_write_t
//----------------------------------------------------------------------
/// @brief  Called when ALP-Write is requested by the modem.
///         Function must perform required actions to fullfil the request
///         then should call 'respond'
/// @param  fid         : File ID
/// @param  data        : Pointer to the destination data buffer
/// @param  offset      : Access Offset in bytes
/// @param  length      : Access Size in bytes
/// @param  id          : ID of the request
//======================================================================
typedef void (fx_write_t)           (u8 action, u8 fid, void* data, u32 offset, u32 length, int id);

//======================================================================
// fx_read_fprop_t
//----------------------------------------------------------------------
/// @brief  Called when ALP-Read-file-properties is requested by the modem.
///         Function must perform required actions to fullfil the request
///         then should call 'respond_fprop' (or 'respond' in case of error)
/// @param  fid         : File ID
/// @param  id          : ID of the request
//======================================================================
typedef void (fx_read_fprop_t)      (u8 action, u8 fid, int id);

//======================================================================
// fx_flush_t
//----------------------------------------------------------------------
/// @brief  Called when ALP-Flush is requested by the modem.
///         Function must perform required actions to fullfil the request
///         then should call 'respond'
/// @param  fid         : File ID
/// @param  id          : ID of the request
//======================================================================
typedef void (fx_flush_t)           (u8 action, u8 fid, int id);

//======================================================================
// fx_delete_t
//----------------------------------------------------------------------
/// @brief  Called when ALP-Delete is requested by the modem.
///         Function must perform required actions to fullfil the request
///         then should call 'respond'
/// @param  fid         : File ID
/// @param  id          : ID of the request
//======================================================================
typedef void (fx_delete_t)          (u8 action, u8 fid, int id);

//======================================================================
// fx_udata_t
//----------------------------------------------------------------------
/// @brief  Called when Unsollicited Data is received by the Modem (i.e.
///         peer notifications etc).
/// @param  data        : Pointer to the data buffer
/// @param  length      : Data Size in bytes
//======================================================================
typedef void (fx_udata_t)           (alp_payload_t*);

//======================================================================
// fx_lqual_t
//----------------------------------------------------------------------
/// @brief  Called when LQUAL URC is generated by the modem.
///         LQUAL URC is setup by the user through 'modem_ref_enable_urc'.
///         LQUAL gives percentage of successfully sent packets on a
///         particular interface (IFID).
/// @param  ifid        : Interface File ID from which LQUAL is issued
/// @param  per         : Packet Error Rate in %
//======================================================================
typedef void (fx_lqual_t)           (u8 ifid, int per);

//======================================================================
// fx_ldown_t
//----------------------------------------------------------------------
/// @brief  Called when LDOWN URC is generated by the modem.
///         LDOWN URC is setup by the user through 'modem_ref_enable_urc'
///         LDOWN is generated for a particular interface (IFID) after
///         a (configurable) number of consecutive transmission have failed.
/// @param  ifid        : Interface File ID from which LDOWN is issued
//======================================================================
typedef void (fx_ldown_t)           (u8 ifid);

//======================================================================
// fx_reset_t
//----------------------------------------------------------------------
/// @brief  Called when RESET URC is generated by the modem.
///         LDOWN URC is setup by the user through 'modem_ref_enable_urc'
/// @param  ifid        : Interface File ID from which LDOWN is issued
//======================================================================
typedef void (fx_reset_t)           (void);

//======================================================================
// fx_boot_t
//----------------------------------------------------------------------
/// @brief  Called when BOOT URC is generated by the modem.
/// @param  cause       : Cause of the boot 'H':Pin/Hardware reset
///                                         'P':POR reset
///                                         'S':Software reset
///                                         'L':Low-power reset
///                                         'W':Watchdog reset
/// @param  nb_boot     : Number of boots since last POR
//======================================================================
typedef void (fx_boot_t)            (u8 cause, u16 nb_boot);

//======================================================================
// fx_busy_t
//----------------------------------------------------------------------
/// @brief  Called when BUSY URC is generated by the modem.
/// @param  busy       : 0 if not busy, else busy
//======================================================================
typedef void (fx_busy_t)            (u8 busy);

//======================================================================
// fx_itf_busy_t
//----------------------------------------------------------------------
/// @brief  Called when BUSY URC is generated by the modem.
/// @param  ifid       : interface file id
/// @param  busy       : busy time in seconds
//======================================================================
typedef void (fx_itf_busy_t)        (u8 ifid, u32 busy);

// Set of functions passed together at modem openning
typedef struct {
    // ALP File 'Action' callbacks
    fx_read_t*          read;
    fx_write_t*         write;
    fx_read_fprop_t*    read_fprop;
    fx_flush_t*         flush;
    fx_delete_t*        remove;
    // 'URC' callbacks
    fx_udata_t*         udata;
    fx_lqual_t*         lqual;
    fx_ldown_t*         ldown;
    fx_reset_t*         reset;
    fx_boot_t*          boot;
    fx_busy_t*          busy;
    fx_itf_busy_t*      itf_busy;
} modem_ref_callbacks_t;


// LWAN
typedef void (fx_packet_sent_t)         (void);
typedef void (fx_lwan_itf_busy_t)       (u32 busy_time);
typedef void (fx_join_failed_t)         (void);

typedef struct {
    fx_packet_sent_t*       packet_sent;
    fx_lwan_itf_busy_t*     itf_busy;
    fx_join_failed_t*       join_failed;
} modem_lwan_callbacks_t;


//======================High-Level-API===============================}}}

//======================================================================
// action_callback_t
//----------------------------------------------------------------------
/// @brief  Type of function called on response(s) generated by an
///         'action' function. Different functions of this kind can be
///         associated to different IDs through 'get_id'.
///         'Action' function are subsequently called with relevant ID.
/// @param  terminal    : '1' at the last call for this ID, '0' otherwise
/// @param  err         : ALP Error code
/// @param  id          : ID of the request
//======================================================================
typedef void (action_callback_t)  (u8 terminal, s8 err, u8 id);

//======================================================================
// modem_ref_open
//----------------------------------------------------------------------
/// @brief  Open Wizzilab Modem Driver
/// @param  send        : User function implementing serial output.
/// @param  callbacks   : Set of functions called by the driver upon
///                       reception of commands
/// @return 0
//======================================================================
void modem_ref_open(fx_serial_send_t* send, modem_ref_callbacks_t* callbacks);
void modem_ref_close(void);
void modem_ref_set_lwan_cb(modem_lwan_callbacks_t* callbacks);

//======================================================================
// modem_ref_get_id
//----------------------------------------------------------------------
/// @brief  Request an ID to perform modem operations
/// @param  cb          : Function called on responses generated for
///                       this ID.
/// @return Positive ID value, -1 if no more IDs available.
//======================================================================
int modem_ref_get_id(action_callback_t* cb);

//======================================================================
// modem_ref_free_id
//----------------------------------------------------------------------
/// @brief  Release an ID
/// @param  id          : ID to release.
/// @return ID value, -1 if ID was not in use.
//======================================================================
int modem_ref_free_id(u8 id);

//======================================================================
// "Action" functions performing requests to the modem
//==================================================================={{{

void modem_ref_alp(void* itf, alp_payload_t* alp_user, alp_payload_t** alp_rsp, int id);

//==========================Action===================================}}}

//======================================================================
// "Response" functions to be called-back on requests from the modem
//==================================================================={{{
void modem_ref_respond(u8 action, s8 status, int id);
void modem_ref_respond_fprop(u8 fid, alp_file_header_t* hdr, int id);
void modem_ref_respond_read(u8 fid, void* data, u32 offset, u32 length, int id);
//==========================Response=================================}}}


//=======================================================================
// Modem File IDs are mapped from 64 to 127
// These files are mandatory when building an application that
// uses Wizzilab's D7A Stack, so it will be included in all "Modem"
// applications.
//=======================================================================
// Modem Config/Status
#define FID_WM_REV                      2 // aka D7A_FID_FIRMWARE_VERSION
#define FID_WM_RFU_64                  64
#define FID_HOST_REV                   65
#define FID_WM_SCRATCH                 66
#define FID_WM_STATUS                  67
#define FID_WM_CFG                     68
#define FID_WM_HWCFG                   69
#define FID_WM_CTRL                    70
#define FID_WM_LED_CFG                 71
#define FID_WM_DEBUG                   72
#define FID_WM_POWER_STATUS            73 // For GW power supervisor reporting
#define FID_WM_TLEV                    74 // Trace levels
#define FID_WM_USER_STORAGE            75 // Big generic file for APPs to store data since we can't create permanent files on NRF52.
#define FID_WM_INVT                    76 // Inventory commands
#define FID_WM_RFU_77                  77
#define FID_WM_RFU_78                  78
#define FID_WM_RFU_79                  79

// LORAWAN Stack
#define FID_LWAN_CFG                   96
#define FID_LWAN_NLS                   97
#define FID_LWAN_ITF                   98 // XXX useless
#define FID_LWAN_STATUS                99

// Action files
#define FID_ACTP_RPT_FULL             100
#define FID_ACTP_RPT_PART             101

// Unallocated FIDs
#define FID_UNUSED_102                102
#define FID_UNUSED_103                103
#define FID_UNUSED_104                104
#define FID_UNUSED_105                105
#define FID_UNUSED_106                106
#define FID_UNUSED_107                107
#define FID_UNUSED_108                108
#define FID_UNUSED_109                109

#define IFID_REPORT                   110

// Unallocated FIDs
#define FID_UNUSED_111                111
#define FID_UNUSED_112                112
#define FID_UNUSED_113                113
#define FID_UNUSED_114                114
#define FID_UNUSED_115                115
#define FID_UNUSED_116                116
#define FID_UNUSED_117                117
#define FID_UNUSED_118                118
#define FID_UNUSED_119                119
#define FID_UNUSED_120                120
#define FID_UNUSED_121                121
#define FID_UNUSED_122                122
#define FID_UNUSED_123                123

// Modem Security protocols
#define FID_WM_CHALLENGE              124

// Modem CUP
#define FID_CUP_CFG_BCAST             125
#define FID_CUP_CFG                   126
#define FID_CUP_CODE                  127

// HST CUP
#define FID_APP_CUP_CFG_BCAST         252
#define FID_APP_CUP_CFG               253
#define FID_APP_CUP_CODE              254

// System status
#define FID_SYS_STATUS                255

#endif

// vim:fdm=marker:fdc=2