Exportable version of WizziLab's modem driver.

Dependents:   modem_ref_helper

include/alp_spec.h

Committer:
Jeej
Date:
2019-02-20
Revision:
45:6a4c373e1178
Parent:
42:87bf0654cb7b
Child:
47:cf4519ba56d9

File content as of revision 45:6a4c373e1178:

/// @copyright
/// ========================================================================={{{
/// Copyright (c) 2012-2018 WizziLab                                           /
/// All rights reserved                                                        /
///                                                                            /
/// IMPORTANT: This Software may not be modified, copied or distributed unless /
/// embedded on a WizziLab product. Other than for the foregoing purpose, this /
/// Software and/or its documentation may not be used, reproduced, copied,     /
/// prepared derivative works of, modified, performed, distributed, displayed  /
/// or sold for any purpose. For the sole purpose of embedding this Software   /
/// on a WizziLab product, copy, modification and distribution of this         /
/// Software is granted provided that the following conditions are respected:  /
///                                                                            /
/// *  Redistributions of source code must retain the above copyright notice,  /
///    this list of conditions and the following disclaimer                    /
///                                                                            /
/// *  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.    /
///                                                                            /
/// *  The name of WizziLab can not 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.               /
/// WIZZILAB HAS NO OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES,       /
/// ENHANCEMENTS OR MODIFICATIONS.                                             /
///                                                                            /
/// Should you have any questions regarding your right to use this Software,   /
/// contact WizziLab at www.wizzilab.com.                                      /
///                                                                            /
/// =========================================================================}}}
/// @endcopyright

//  =======================================================================
/// @file           alp_spec.h
/// @defgroup       ALP
/// @brief          ALP definitions from D7A specification
//  =======================================================================

#ifndef __ALP_SPEC_H__
#define __ALP_SPEC_H__

#include "hal_types.h"

// Opcode Modifiers / Preemption flags
#define ALP_OPCODE_RESP                 0x40
#define ALP_OPCODE_GROUP                0x80
#define ALP_OPCODE_ERR                  0x40
#define ALP_OPCODE_EOP                  0x80
#define ALP_OPCODE_ITF                  0x40
#define ALP_OPCODE_INDIRECT             0x40
#define ALP_OPCODE_OVERLOAD             0x80

typedef enum {
//      OPCODE                                  | OPERAND
    ALP_OPCODE_NOP                      = 0,  //|   -

    ALP_OPCODE_F_RD_DATA                = 1,  //|  FDR
    ALP_OPCODE_F_RD_PROP                = 2,  //|  FID

    ALP_OPCODE_F_WR_DATA                = 4,  //|  FD
    ALP_OPCODE_F_WR_FLUSH               = 5,  //|  FD
    ALP_OPCODE_F_WR_PROP                = 6,  //|  FD
    ALP_OPCODE_F_TOUCH                  = 7,  //|  FD

    ALP_OPCODE_QUERY                    = 8,  //|   Q
    ALP_OPCODE_QBREAK                   = 9,  //|   Q
    ALP_OPCODE_PERM_REQ                 = 10, //|   P

    ALP_OPCODE_CRC_CHECK                = 11, //|  Q

    ALP_OPCODE_F_EXIST                  = 16, //|  FID
    ALP_OPCODE_F_CREATE                 = 17, //|  FD
    ALP_OPCODE_F_DELETE                 = 18, //|  FID
    ALP_OPCODE_F_RESTORE                = 19, //|  FID
    ALP_OPCODE_F_FLUSH                  = 20, //|  FID
    ALP_OPCODE_F_DECLARE                = 21, //|  FH XXX Deprecated DO NOT USE !!!
    ALP_OPCODE_F_CLOSE                  = 22, //|  FID
    ALP_OPCODE_F_COPY                   = 23, //|  2xFID
    ALP_OPCODE_F_EXECUTE                = 31, //|  FID

    ALP_OPCODE_RSP_F_DATA               = 32, //|  FD
    ALP_OPCODE_RSP_F_PROP               = 33, //|  FH
    ALP_OPCODE_RSP_STATUS               = 34, //|  S
    ALP_OPCODE_RSP_ISTATUS              = ALP_OPCODE_RSP_STATUS + ALP_OPCODE_ITF, //|   SI
    ALP_OPCODE_RSP_EOPISTATUS           = ALP_OPCODE_RSP_STATUS + ALP_OPCODE_ITF + ALP_OPCODE_EOP, //|   SI
    ALP_OPCODE_RSP_TAG                  = 35, //|  PID
    ALP_OPCODE_RSP_EOPTAG               = ALP_OPCODE_RSP_TAG + ALP_OPCODE_EOP, //|   PID
    ALP_OPCODE_RSP_ERRTAG               = ALP_OPCODE_RSP_TAG + ALP_OPCODE_ERR, //|   PID
    ALP_OPCODE_RSP_URC                  = 36, //|

    ALP_OPCODE_CHUNK                    = 48, //|  -
    ALP_OPCODE_LOGIC                    = 49, //|  -
    ALP_OPCODE_FORWARD                  = 50, //|  I
    ALP_OPCODE_IFORWARD                 = 51, //|  IFID
    ALP_OPCODE_TAG                      = 52, //|  PID
    ALP_OPCODE_URCC                     = 53, //|

    ALP_OPCODE_EXT                      = 63, //| OP |ARGC| ARGS       |
                                              //| 1B | 1B | ARGC-bytes |
} alp_opcodes_t;
#define ALP_OPCODE_UNKNOWN              (-1)

typedef enum {
    ALP_ITF_TYPE_HOST                   = 0x00,
    ALP_ITF_TYPE_BLE                    = 0xB0,
    ALP_ITF_TYPE_COM                    = 0xC0,
    ALP_ITF_TYPE_D7A                    = 0xD7, // Only this one actually in D7A Spec
    ALP_ITF_TYPE_LWAN                   = 0x10,

    ALP_ITF_TYPE_NONE                   = 0xFF
} alp_itf_type_t;

// EXTOpcode Modifiers / Preemption flags
#define ALP_EXTOPCODE_DISTANT           0x40 // Used w/ EXTOPCODE_F_DECLARE

typedef enum {
//  WIZZILAB OPCODE EXTENSION
    ALP_EXTOPCODE_ITF_START             = 0,  //|   'ITF' activation operations:
    ALP_EXTOPCODE_ITF_STOP              = 1,  //| TYPE | DEVQ | IFID | FLAGS |
    ALP_EXTOPCODE_ITF_PAUSE             = 2,  //|  1B  |  1B  |  1B  |  1B   |
                                             //| TYPE: ITF Type (D7A,LWAN,BLE...)
                                             //| DEVQ: ITF Max Device number if applicable
                                             //| IFID: ITF Config file if applicable
                                             //| FLAG: Additional configuration flags if applicable
    ALP_EXTOPCODE_F_DECLARE             = 21, //| FH
} alp_ext_opcodes_t;

typedef enum
{
    ALP_ERR_ITF_FULL                    =  2, // 0x02: For interfaces supporting buffering, indicates buffer reached maximum capacity (no data loss)
    ALP_ERR_PARTIAL_COMPLETION          =  1, // 0x01: Action received and partially completed at response.  To be completed after response

    ALP_ERR_NONE                        =  0, // 0x00: Action completed (OK)
    ALP_ERR_FILE_NOT_FOUND              = -1, // 0xFF: Error access file: File ID does not exist
    ALP_ERR_FILE_EXIST                  = -2, // 0xFE: Error create file: File ID already exists
    ALP_ERR_FILE_NOT_RESTORABLE         = -3, // 0xFD: Error restore file: File is not restorable
    ALP_ERR_PERMISSION_DENIED           = -4, // 0xFC: Error access file: Insufficient permissions
    ALP_ERR_LENGTH_OVERFLOW             = -5, // 0xFB: Error create file: Supplied length (in header) is beyond file limits
    ALP_ERR_ALLOC_OVERFLOW              = -6, // 0xFA: Error create file: Supplied allocation (in header) is beyond file limits
    ALP_ERR_OFFSET_OVERFLOW             = -7, // 0xF9: Error write: Supplied start offset is out of bounds of file allocation
    ALP_ERR_WRITE_OVERFLOW              = -8, // 0xF8: Error complete write: Supplied data goes beyond file allocation
    ALP_ERR_WRITE_ERROR                 = -9, // 0xF7: Error write: impossible to write in storage location
    ALP_ERR_OPERATION_UNKNOWN           = -10,// 0xF6: Error unknown Operation
    ALP_ERR_OPERAND_INCOMPLETE          = -11,// 0xF5: Error incomplete Operand
    ALP_ERR_OPERAND_WRONG_FORMAT        = -12,// 0xF4: Error wrong Operand format
    ALP_ERR_ITF_INVALID                 = -13,// 0xF3: Error invalid interface
    ALP_ERR_ITF_OVERFLOW                = -14,// 0xF2: Error interface overflown (i.e. resources exhausted, buffer full with data discarded)
    ALP_ERR_QUERY_FAIL                  = -15,// 0xF1: (Group of) Query result was false (Informative error code).
    ALP_ERR_ITF_NOT_READY               = -16,// 0xF0: Error interface is not ready

    ALP_ERR_ITF_START                   = -64,// 0xC0: Interface specific error, start range
    ALP_ERR_ITF_END                     = -96,// 0xA0: Interface specific error, end range
    ALP_ERR_ITF_NOT_SPECIFIED           = ALP_ERR_ITF_END, // Not specified internal interface error.

    ALP_ERR_UNKNOWN                     = -128,// 0x80: Unknown error
    ALP_ERR_FS_TIMEOUT,                       // 0x81: Internal FS Error
    ALP_ERR_ITF_UNKNOWN,                      // 0x82: Unknown Interface
    ALP_ERR_ITF_TIMEOUT,                      // 0x83: Internal ITF Error

} alp_errors_t;

typedef enum {
    ALP_QCOMP_NE                        = 0,
    ALP_QCOMP_EQ                        = 1,
    ALP_QCOMP_LT                        = 2,
    ALP_QCOMP_LTE                       = 3,
    ALP_QCOMP_GT                        = 4,
    ALP_QCOMP_GTE                       = 5
} alp_q_comp_t;
#define ALP_QCOMP(v)                   (((v) & 7) << 0)

typedef enum {
    // This is not matching ALP's spec on purpose...
    ALP_QLOGIC_AND                      = 0,
    ALP_QLOGIC_OR                       = 1,
    ALP_QLOGIC_XOR                      = 2,
    ALP_QLOGIC_NOR                      = 3,
    ALP_QLOGIC_NAND                     = 4,
} alp_q_logic_t;

typedef enum {
    ALP_QDATA_SIGNED                    = 0,
    ALP_QDATA_UNSIGNED                  = 1
} alp_q_data_t;
#define ALP_QDATA(v)                    (((v) & 1) << 3)
#define ALP_QMASK(v)                    (((v) & 1) << 4)

typedef enum {
    ALP_QTYPE_NONVOID                   = 0, // This is better done by "EXIST"
    ALP_QTYPE_ACOMP_ZERO                = 1,
    ALP_QTYPE_ACOMP_IMMEDIATE           = 2,
    ALP_QTYPE_ACOMP_FILE                = 3,
    ALP_QTYPE_INRANGE                   = 4,
    ALP_QTYPE_STR_TOKEN                 = 7  //
}alp_q_type_t;
#define ALP_QTYPE(v)                   (((v) & 7) << 5)

typedef enum {
    /// Disable all URCs on requesting ITF
    ALP_URC_TYPE_NONE                   = 0xFF,
    /// Enable Link Quality (on IFID) URCs on requesting ITF
    ALP_URC_TYPE_LQUAL                  = 0,
    /// Enable Link Down (on IFID) URCs on requesting ITF
    ALP_URC_TYPE_LDOWN                  = 1,
    /// Enable system/modem URC 
    /// XXX Could enable subtypes, but API does not allow it
    ALP_URC_TYPE_BUSY                   = 2,
    /// Enable Interface BUSY messages
    ALP_URC_TYPE_ITF_BUSY               = 3,
    /// XXX system/modem URC with parameter
    // ALP_URC_TYPE_SYS

    ALP_URC_TYPE_QTY,

} alp_urc_type_t;

TYPEDEF_STRUCT_PACKED {
    u8                  perm;
    u8                  prop;
    u8                  afid;
    u8                  ifid;
    u32                 size; // XXX Big Endian
    u32                 alloc;// XXX Big Endian
} alp_file_header_t;
#define ALP_FILE_HEADER_SIZE    (sizeof(alp_file_header_t))

// RESPONSES Building helpers
// ======================================================================
#define ALP_RSP_STATUS_SIZE         (3)     // OPCODE + ACTION_ID + ERR
#define ALP_RSP_F_PROP_SIZE         (2+ALP_FILE_HEADER_SIZE)    // OPCODE + FID + 12xDATA
#define ALP_LFIELD_SIZE(a)          (((a) <= 0x3F)      ? 1 : \
                                    (((a) <= 0x3FFF)    ? 2 : \
                                    (((a) <= 0x3FFFFF)  ? 3 : 4)))

// ACTIONS Building helpers
// ----------------------------------------------------------------------
// Usual arguments:
// _p   : pointer to the output string buffer (incremented by the macro)
// _r   : ALP response Flag (true/false)
// _fid : File ID
// _o   : Access Offset
// _l   : Access Length
// _m   : Mask
// _v   : Immediate value
// ======================================================================
#define ALP_ACTION_NOP_SIZE                     (1)
#define ALP_ACTION_NOP(_p,_r)   do {\
    *(p)++ = (_r)?ALP_OPCODE_NOP+ALP_OPCODE_RESP:ALP_OPCODE_NOP;\
    } while(0)

#define ALP_ACTION_TAG_SIZE                     (2)
#define ALP_ACTION_TAG(p,tag,eop) do {\
    *(p)++ = (eop)?ALP_OPCODE_TAG+ALP_OPCODE_EOP:ALP_OPCODE_TAG;\
    *(p)++ = (tag);\
    } while(0)

#define ALP_ACTION_F_RD_DATA_SIZE(_o,_l)        (2+ALP_LFIELD_SIZE(_o)+ALP_LFIELD_SIZE(_l))
#define ALP_ACTION_F_RD_DATA_SIZE_MAX           (2+4+4)
#define ALP_ACTION_F_RD_DATA(_p,_r,_fid,_o,_l) do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_RD_DATA+ALP_OPCODE_RESP:ALP_OPCODE_F_RD_DATA;\
    *(_p)++ = (_fid);\
    (_p) += alp_encode_length(_p,_o);\
    (_p) += alp_encode_length(_p,_l);\
    } while(0)

#define ALP_ACTION_F_RD_PROP_SIZE               (2)
#define ALP_ACTION_F_RD_PROP(_p,_r,_fid) do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_RD_PROP+ALP_OPCODE_RESP:ALP_OPCODE_F_RD_PROP;\
    *(_p)++ = (_fid);\
    } while(0)

#define ALP_ACTION_F_WR_DATA_SIZE(_o,_l)        (2+ALP_LFIELD_SIZE(_o)+ALP_LFIELD_SIZE(_l)+(_l))
#define ALP_ACTION_F_WR_DATA_SIZE_MAX(_l)       (2+4+4+(_l))
#define ALP_ACTION_F_WR_DATA(_p,_r,_fid,_o,_l,_data) do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_WR_DATA+ALP_OPCODE_RESP:ALP_OPCODE_F_WR_DATA;\
    *(_p)++ = (_fid);\
    (_p) += alp_encode_length(_p,_o);\
    (_p) += alp_encode_length(_p,_l);\
    memcpy((_p),_data,_l);(_p) += (_l);\
    } while(0)

#define ALP_ACTION_F_WR_FLUSH_SIZE(_o,_l)       (2+ALP_LFIELD_SIZE(_o)+ALP_LFIELD_SIZE(_l)+(_l))
#define ALP_ACTION_F_WR_FLUSH_SIZE_MAX(_l)      (2+4+(_l))
#define ALP_ACTION_F_WR_FLUSH(_p,_r,_fid,_o,_l,_data) do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_WR_FLUSH+ALP_OPCODE_RESP:ALP_OPCODE_F_WR_FLUSH;\
    *(_p)++ = (_fid);\
    (_p) += alp_encode_length(_p,_o);\
    (_p) += alp_encode_length(_p,_l);\
    memcpy((_p),_data,_l);(_p) += (_l);\
    } while(0)

#define ALP_ACTION_F_WR_PROP_SIZE_MAX           (2+2+sizeof(alp_file_header_t))
#define ALP_ACTION_F_WR_PROP(_p,_r,_fid,_o,_l,_data)  do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_WR_PROP+ALP_OPCODE_RESP:ALP_OPCODE_F_WR_PROP;\
    *(_p)++ = (_fid);\
    *(_p)++ = (_o);\
    *(_p)++ = (_l);\
    memcpy((_p),(u8*)(_data),(_l));(_p) += (_l);\
    } while(0)

#define ALP_ACTION_F_TOUCH_SIZE(_o,_l)          (2+ALP_LFIELD_SIZE(_o)+ALP_LFIELD_SIZE(_l))
#define ALP_ACTION_F_TOUCH_SIZE_MAX             (2+4+4)
#define ALP_ACTION_F_TOUCH(_p,_r,_fid,_o,_l)   do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_TOUCH+ALP_OPCODE_RESP:ALP_OPCODE_F_TOUCH;\
    *(_p)++ = (_fid);\
    (_p) += alp_encode_length(_p,_o);\
    (_p) += alp_encode_length(_p,_l);\
    } while(0)

#define ALP_ACTION_F_EXIST_SIZE                 (2)
#define ALP_ACTION_F_EXIST(_p,_r,_fid)   do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_EXIST+ALP_OPCODE_RESP:ALP_OPCODE_F_EXIST;\
    *(_p)++ = (_fid);\
    } while(0)

#define ALP_ACTION_F_DELETE_SIZE                (2)
#define ALP_ACTION_F_DELETE(_p,_r,_fid)  do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_DELETE+ALP_OPCODE_RESP:ALP_OPCODE_F_DELETE;\
    *(_p)++ = (_fid);\
    } while(0)

#define ALP_ACTION_F_FLUSH_SIZE                 (2)
#define ALP_ACTION_F_FLUSH(_p,_r,_fid)   do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_FLUSH+ALP_OPCODE_RESP:ALP_OPCODE_F_FLUSH;\
    *(_p)++ = (_fid);\
    } while(0)

#define ALP_ACTION_F_CREATE_SIZE                (2+sizeof(alp_file_header_t))
#define ALP_ACTION_F_CREATE(_p,_r,_fid,_hdr)  do {\
    *(_p)++ = (_r)?ALP_OPCODE_F_CREATE+ALP_OPCODE_RESP:ALP_OPCODE_F_CREATE;\
    *(_p)++ = (_fid);\
    memcpy((_p),(u8*)(_hdr),sizeof(alp_file_header_t));(_p) += sizeof(alp_file_header_t);\
    } while(0)

#define ALP_PERM_REQ_USER                       0
#define ALP_PERM_REQ_ROOT                       1

// Wizzilab's specific Authentication-Protocol-Id
#define ALP_WIZZILAB_AUTH_PROTOCOL_ID           42
#define ALP_WIZZILAB_AUTH_PROTOCOL_TOKEN_SIZE   8
#define ALP_ACTION_PERM_REQ_OFFSET              (3+ALP_WIZZILAB_AUTH_PROTOCOL_TOKEN_SIZE)
#define ALP_ACTION_PERM_REQ_SIZE(_l)            (ALP_ACTION_PERM_REQ_OFFSET+(_l))
#define ALP_ACTION_PERM_REQ(_p,_r,_role)   do {\
    *(_p)++ = (_r)?ALP_OPCODE_PERM_REQ+ALP_OPCODE_RESP:ALP_OPCODE_PERM_REQ;\
    *(_p)++ = (_role);\
    *(_p)++ = ALP_WIZZILAB_AUTH_PROTOCOL_ID;\
    } while(0)

// Wizzilab's specific Challenge-Encryption-Authentication-Protocol-Id
#define ALP_WIZZILAB_CHAL_PROTOCOL_ID           43
#define ALP_WIZZILAB_CHAL_PROTOCOL_TOKEN_SIZE   ALP_WIZZILAB_AUTH_PROTOCOL_TOKEN_SIZE

#define ALP_ACTION_URCC_SIZE(t)                 ((t==ALP_URC_TYPE_NONE)?2:4)
#define ALP_ACTION_URCC_EN(_p,_r,_type,_ifid,_cfg)  do {\
    *(_p)++ = (_r)?ALP_OPCODE_URCC+ALP_OPCODE_GROUP+ALP_OPCODE_RESP:ALP_OPCODE_URCC+ALP_OPCODE_GROUP;\
    *(_p)++ = (_type);\
    if((_type)==ALP_URC_TYPE_LQUAL || (_type)==ALP_URC_TYPE_LDOWN)\
    {\
        *(_p)++ = (_ifid);\
        *(_p)++ = (_cfg);\
    }\
    else if((_type)==ALP_URC_TYPE_ITF_BUSY)\
    {\
        *(_p)++ = (_ifid);\
    }\
    } while(0)

#define ALP_ACTION_URCC_DIS(_p,_r,_type,_ifid,_cfg)  do {\
    *(_p)++ = (_r)?ALP_OPCODE_URCC+ALP_OPCODE_RESP:ALP_OPCODE_URCC;\
    *(_p)++ = (_type);\
    if((_type)==ALP_URC_TYPE_LQUAL || (_type)==ALP_URC_TYPE_LDOWN)\
    {\
        *(_p)++ = (_ifid);\
        *(_p)++ = (_cfg);\
    }\
    else if((_type)==ALP_URC_TYPE_ITF_BUSY)\
    {\
        *(_p)++ = (_ifid);\
    }\
    } while(0)

#define ALP_ACTION_FORWARD_SIZE(s)         (1+(s))
#define ALP_ACTION_FORWARD(p,itf,itfs)    do {\
    *(p)++ = ALP_OPCODE_FORWARD;\
    memcpy((p),(itf),(itfs));(p) += (itfs);\
    } while(0)

#define ALP_ACTION_RSP_F_DATA_SIZE(_o,_l)           (2+ALP_LFIELD_SIZE(_o)+ALP_LFIELD_SIZE(_l)+(_l))
#define ALP_ACTION_RSP_F_DATA_SIZE_MAX(_l)          (2+4+4+(_l))
#define ALP_ACTION_RSP_F_DATA(_p,_fid,_o,_l,_data)  do {\
    *(_p)++ = ALP_OPCODE_RSP_F_DATA;\
    *(_p)++ = (_fid);\
    (_p) += alp_encode_length(_p,_o);\
    (_p) += alp_encode_length(_p,_l);\
    memcpy((_p),(u8*)(_data),(_l));(_p) += (_l);\
    } while(0)

#define ALP_ACTION_RSP_F_PROP_SIZE                  (2+ALP_FILE_HEADER_SIZE)
#define ALP_ACTION_RSP_F_PROP(_p,_fid,_hdr)  do {\
    *(_p)++ = ALP_OPCODE_RSP_F_PROP;\
    *(_p)++ = (_fid);\
    memcpy((_p),(u8*)(_hdr),ALP_FILE_HEADER_SIZE);(_p) += ALP_FILE_HEADER_SIZE;\
    } while(0)

#define ALP_ACTION_RSP_STATUS_SIZE                  (3)
#define ALP_ACTION_RSP_STATUS(_p,_a,_s)  do {\
    *(_p)++ = ALP_OPCODE_RSP_STATUS;\
    *(_p)++ = (_a);\
    *(_p)++ = (_s);\
    } while(0)

#define ALP_ACTION_RSP_TAG_SIZE                     (2)
#define ALP_ACTION_RSP_TAG(_p,_val,_eop,_err)  do {\
    u8 tmp = ALP_OPCODE_RSP_TAG;\
    tmp += (_eop)?ALP_OPCODE_EOP:0;\
    tmp += (_err)?ALP_OPCODE_ERR:0;\
    *(_p)++ = tmp;\
    *(_p)++ = (_val);\
    } while(0)

#define ALP_ACTION_EXT_SIZE(_argc)                  (3+(_argc))
#define ALP_ACTION_EXT(_p,_r,_op,_argc)    do {\
    *(_p)++ = (_r)?ALP_OPCODE_EXT+ALP_OPCODE_RESP:ALP_OPCODE_EXT;\
    *(_p)++ = (_op);\
    *(_p)++ = (_argc);\
    } while(0)

// WIZZILAB Specific Extensions
#define _ALP_ACTION_ACTIVATE_ITF_SIZE               (4)
#define ALP_ACTION_ACTIVATE_ITF_SIZE                (ALP_ACTION_EXT_SIZE(_ALP_ACTION_ACTIVATE_ITF_SIZE))
#define ALP_ACTION_ACTIVATE_ITF(_p,_r,_en,_type,_dev,_ifid,_flag)    do {\
    ALP_ACTION_EXT(_p,_r,(_en)?ALP_EXTOPCODE_ITF_START:ALP_EXTOPCODE_ITF_STOP,_ALP_ACTION_ACTIVATE_ITF_SIZE);\
    *(p)++ = _type;\
    *(p)++ = _dev;\
    *(p)++ = _ifid;\
    *(p)++ = _flag;\
    } while(0)

#define _ALP_ACTION_F_DECLARE_SIZE                  (1+sizeof(alp_file_header_t))
#define ALP_ACTION_F_DECLARE_SIZE                   (ALP_ACTION_EXT_SIZE(_ALP_ACTION_F_DECLARE_SIZE))
#define ALP_ACTION_F_DECLARE(_p,_r,_fid,_hdr,_dist) do {\
    ALP_ACTION_EXT(_p,_r,(_dist)?ALP_EXTOPCODE_F_DECLARE+ALP_EXTOPCODE_DISTANT:ALP_EXTOPCODE_F_DECLARE,_ALP_ACTION_F_DECLARE_SIZE);\
    *(_p)++ = (_fid);\
    memcpy((_p),(u8*)(_hdr),sizeof(alp_file_header_t));(_p) += sizeof(alp_file_header_t);\
    } while(0)


// Simple "report/notify" actions. For both, FID,Offset and size will be
// substituted thanks to specific Offset-Operand token
#define ALP_ACTION_REPORT_FULL_FILE { \
    ALP_OPCODE_F_RD_DATA | ALP_OPCODE_RESP,\
    0, HAL_U16_BE_DEPOSIT(0x4000), 0 }

#define ALP_ACTION_REPORT_PART_FILE { \
    ALP_OPCODE_F_RD_DATA | ALP_OPCODE_RESP,\
    0, HAL_U16_BE_DEPOSIT(0x8000), 0 }

// Simple Query actions
/// Match immediate value to file value
#define ALP_ACTION_QUERY_EQVAL_SIZE(_o,_l,_mbit)    (4+ALP_LFIELD_SIZE(_o)+(1+(_mbit))*(_l))
#define ALP_ACTION_QUERY_EQVAL(_p,_m,_v,_fid,_o,_l)   do {\
    u8 _mbit = (_m) ? 1 : 0;\
    *(_p)++ = ALP_OPCODE_QUERY;\
    *(_p)++ = ALP_QCOMP(ALP_QCOMP_EQ) | ALP_QDATA(ALP_QDATA_UNSIGNED) | ALP_QMASK(_mbit) | ALP_QTYPE(ALP_QTYPE_ACOMP_IMMEDIATE);\
    *(_p)++ = _l;\
    if (_mbit) {memcpy((_p),&(_m),_l);(_p) += (_l);}\
    memcpy((_p),&(_v),_l);(_p) += (_l);\
    *(_p)++ = _fid;\
    (_p) += alp_encode_length(_p,_o);\
    } while(0)

// Query with break actions
/// Match immediate value to file value
#define ALP_ACTION_QBREAK_EQVAL_SIZE(_o,_l,_mbit)    (4+ALP_LFIELD_SIZE(_o)+(1+(_mbit))*(_l))
#define ALP_ACTION_QBREAK_EQVAL(_p,_m,_v,_fid,_o,_l)   do {\
    u8 _mbit = (_m) ? 1 : 0;\
    *(_p)++ = ALP_OPCODE_QBREAK;\
    *(_p)++ = ALP_QCOMP(ALP_QCOMP_EQ) | ALP_QDATA(ALP_QDATA_UNSIGNED) | ALP_QMASK(_mbit) | ALP_QTYPE(ALP_QTYPE_ACOMP_IMMEDIATE);\
    *(_p)++ = _l;\
    if (_mbit) {memcpy((_p),&(_m),_l);(_p) += (_l);}\
    memcpy((_p),&(_v),_l);(_p) += (_l);\
    *(_p)++ = _fid;\
    (_p) += alp_encode_length(_p,_o);\
    } while(0)

#endif // __ALP_SPEC_H__