#ifndef _LL_CONN_H_
#define _LL_CONN_H_

#include "ll.h"
#include "utils\simple_buf.h"
#include "t1001_bt_timer.h"
#include <common/bt_buf.h>

struct ll_conn_set
{
    struct
    {
        uint32_t active: 1;
        uint32_t connected: 1;
        uint32_t master: 1;
        uint32_t link_made: 1;
        uint32_t rx_window: 1;
        uint32_t update_chmap: 1;
        uint32_t update_conn: 1;
        uint32_t update_phy: 1;
        uint32_t terminate: 1;
        uint32_t rcv_terminate: 1;
        uint32_t wait_process: 1;
        uint32_t last_rx_data: 1;
        uint32_t in_latency: 1;
        uint32_t enc: 1;
        uint32_t start_enc: 1;
        uint32_t pause_enc: 1;
        uint32_t refresh_enc: 1;
        uint32_t anchor: 1;
        uint32_t wait_ack: 1;
        uint32_t last_rx_ok: 1;
    } status;
    uint8_t handle;
    uint8_t  state;

    bt_addr_le_t own_addr;
    bt_addr_le_t peer_addr;

    // conn_ind packet, total 34 bytes
    uint32_t access;
    uint8_t crcinit[3];
    uint8_t win_size;
    uint16_t win_offset;
    uint16_t interval;
    uint16_t latency;
    uint16_t timeout;
    uint8_t map[5];
    uint8_t hopinc: 5;
    uint8_t sca: 3;

    // connection information
    uint8_t used_ch;
    uint8_t hop;
    uint8_t ch;
    uint32_t anchor;
    uint32_t sync_ts;

    uint32_t window_widening;
    union
    {
        uint8_t pdu[0];
        struct
        {
            uint8_t win_size;
            uint16_t win_offset;
            uint16_t interval;
            uint16_t latency;
            uint16_t timeout;
        } __packed conn_update_ind;
        struct
        {
            uint8_t  chm[5];
        } chan_map_ind;
    } uparam;
    struct
    {
        uint8_t tx_phy: 4; // 0: 1M, 1: 2M, 2: Coded S2, 3: Coded S8
        uint8_t rx_phy: 4; // 0: 1M, 1: 2M, 2: Coded S2, 3: Coded S8
    } mode;

    uint16_t evcnt;
    uint16_t instant;

    union
    {
        uint8_t val[0];
        struct
        {
            uint8_t ivm[4];
            uint8_t ivs[4];
        };
    } iv;
    union
    {
        uint8_t val[0];
        struct
        {
            uint8_t skdm[8];
            uint8_t skds[8];
        };
    } skd;
    uint8_t rand[8];
    uint8_t ediv[2];

    uint8_t key[16];           // should be 32bit aligned
    uint8_t ltk[16];

    uint8_t rctr[5];
    uint8_t tctr[5];

    BT_TIMER_HandleType sch_timer_handler;

    // hci acl data process
    sys_slist_t tx_acl_queue;
    simple_buf_t *tx_acl_buf;
    uint16_t tx_acl_len;

    // pkt send process
    sys_slist_t tx_queue;
    volatile struct node_tx_pdu *node_tx;

    struct pdu_data_header header;

#if defined(CONFIG_BT_CTRL_LE_PING)
    uint16_t apto_reload;
#endif // CONFIG_BT_CTRL_LE_PING

    int8_t rssi_latest;

    // connection spec.
    uint16_t connMaxTxOctets;
    uint16_t connMaxRxOctets;
    uint16_t connRemoteMaxTxOctets;
    uint16_t connRemoteMaxRxOctets;
    uint16_t connMaxTxTime;
    uint16_t connMaxRxTime;
    uint16_t connRemoteMaxTxTime;
    uint16_t connRemoteMaxRxTime;

    uint16_t connEffectiveMaxTxOctets;
    uint16_t connEffectiveMaxRxOctets;
    uint16_t connEffectiveMaxTxTime;
    uint16_t connEffectiveMaxRxTime;

    struct
    {
        uint32_t features_conn;
        uint32_t features_peer;
    } llcp_feature;
    struct
    {
        uint8_t req;
        uint8_t  version_number;
        uint16_t company_id;
        uint16_t sub_version_number;
    } llcp_version;
    struct
    {
        uint8_t reason_own;
        uint8_t reason_peer;
    } llcp_terminate;
    struct
    {
        uint8_t phy_c_to_p : 4; // bit0: 1M, bit1: 2M, bit2: Coded
        uint8_t phy_p_to_c : 4;
    } llcp_phyupd;

    struct
    {
        uint8_t req : 1;
        uint8_t flags : 1; // 0: prefer s2, prefer s8
        uint8_t tx_phys : 3; // bit0: 1M, bit1: 2M, bit2: Coded
        uint8_t rx_phys : 3;
    } hci_phy_req;
};

void ll_conn_tx_enqueue(struct ll_conn_set *conn, struct node_tx_pdu *node_tx);
void ll_conn_tx_enqueue_patch(struct ll_conn_set *conn, struct node_tx_pdu *node_tx);
struct ll_conn_set *ll_conn_set_get(uint8_t handle);

#ifdef OMW_EN_DEEP_SLEEP
void ll_conn_process_before_sleep();
uint32_t ll_conn_process_wake_up();
uint32_t ll_conn_is_connected_before_sleep();
#endif

#endif /* _LL_CONN_H_ */