
#ifndef __LLCP_H__
#define __LLCP_H__

#include "PN532/PN532/mac_link.h"

#define LLCP_DEFAULT_TIMEOUT  20000
#define LLCP_DEFAULT_DSAP     0x04
#define LLCP_DEFAULT_SSAP     0x20

class LLCP {
  public:
    LLCP(PN532Interface& interface) : link(interface) {
        headerBuf = link.getHeaderBuffer(&headerBufLen);
        ns = 0;
        nr = 0;
    };

    /**
        @brief    Actiave PN532 as a target
        @param    timeout max time to wait, 0 means no timeout
        @return   > 0     success
                = 0     timeout
                < 0     failed
    */
    int8_t activate(uint16_t timeout = 0);

    int8_t waitForConnection(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);

    int8_t waitForDisconnection(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);

    int8_t connect(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);

    int8_t disconnect(uint16_t timeout = LLCP_DEFAULT_TIMEOUT);

    /**
        @brief    write a packet, the packet should be less than (255 - 2) bytes
        @param    header  packet header
        @param    hlen    length of header
        @param    body    packet body
        @param    blen    length of body
        @return   true    success
                false   failed
    */
    bool write(const uint8_t* header, uint8_t hlen, const uint8_t* body = 0, uint8_t blen = 0);

    /**
        @brief    read a  packet, the packet will be less than (255 - 2) bytes
        @param    buf     the buffer to contain the packet
        @param    len     lenght of the buffer
        @return   >=0     length of the packet
                <0      failed
    */
    int16_t read(uint8_t* buf, uint8_t len);

    uint8_t* getHeaderBuffer(uint8_t* len) {
        uint8_t* buf = link.getHeaderBuffer(len);
        len -= 3;       // I PDU header has 3 bytes
        return buf;
    };

  private:
    MACLink link;
    uint8_t mode;
    uint8_t ssap;
    uint8_t dsap;
    uint8_t* headerBuf;
    uint8_t headerBufLen;
    uint8_t ns;         // Number of I PDU Sent
    uint8_t nr;         // Number of I PDU Received

    static uint8_t SYMM_PDU[2];
};

#endif // __LLCP_H__
