//
//  bt_l2cap_cb_channel.h
//
//  Bluetooth Protocol Stack - Logical channel management control block operation
//  Copyright (C) 2013-2017 Toyohiko Togashi tog001@nifty.com
//
//
//  This program is free software; you can redistribute it and/or modify it under the terms of the
//  GNU General Public License as published by the Free Software Foundation; either version 3
//  of the License, or (at your option) any later version.
//
//  This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
//  without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
//  See the GNU General Public License for more details.
//
//  You should have received a copy of the GNU General Public License along with this program.
//  If not, see <http://www.gnu.org/licenses/>
//
//
//  Update history
//  ---------- ----- -------------------------------------------
//  2013.01.21 v0.0  First cording
//  2013.04.21 v0.1  Commit
//  2013.05.08 v0.1  Changed a control block structure, bt_l2capChannelGetNext argument
//  2015.02.03 v0.3  Supported the PIC32
//  2017.01.03 v0.3e Changed a argument (handle -> cb_channel, psm -> cb_service)
//  2017.01.03 v0.3e Added a API (bt_l2capChannelFindByLink,bt_l2capChannelAddByLink)
//  2017.01.08 v0.3e Appended a authentication function for the classic services
//  2017.01.08 v0.3e Renamed scid,dcid -> peerCid,myCid
//  2017.01.18 v0.3f Appended a authentication function for the SM
//
#ifndef BT_L2CAP_CB_CHANNEL_H_
#define BT_L2CAP_CB_CHANNEL_H_

#include <string.h>
#include <time.h>                       // ADD 2017.01.08
#include "bt_l2cap_cb_link.h"
#include "bt_l2cap_cb_service.h"        // ADD 2017.01.03

//
//  Control block
//
struct bt_l2capChannel {
    struct bt_l2capChannel *next;
    struct bt_l2capLink    *link;       // handle,...
    struct bt_l2capService *service;    // psm,serviceProg                                                                                      // ADD START 2017.01.03
    unsigned short          peerCid;
    unsigned short          myCid;
//  unsigned short          psm;                                                                                                                // DEL START 2017.01.03
//  size_t                  (*serviceProg)(unsigned short handle, unsigned char *inBuff, size_t inLen, unsigned char *outBuff, size_t outSize); // DEL START 2017.01.03

#ifdef DELETE                           // DEL START 2017.01.08
    enum {
        CLOSED = 0,
        WAIT_CONNECT,
        WAIT_CONFIG,
        WAIT_CONFIG_REQ_RSP,
        WAIT_CONFIG_REQ,
        WAIT_SEND_CONFIG,
        WAIT_CONFIG_RSP,
        OPEN,
        WAIT_DISCONNECT,
        WAIT_CONNECT_RSP
    }                       state;
    enum {
        NONE = 0,
        DATA_RECIEVE,
        SEND_REQUEST,
        DISCONNECT_REQUEST
    }                       event;
    long                    try;                // Timeout counter
    unsigned char           id;                 // Message identifier counter
    unsigned char           userArea[8];        // Application work
#else                                           // DEL END - ADD START 2017.01.08
    union {
        struct { // L2CAP Signaling channel
            struct bt_l2capChannel   *now;      // Idle process
            unsigned char   lastId;             // Identifier sequence
        }   signaling;

        struct { // Attribute protocol channel
            ;
        }   att;

        struct { // Security Manager channel
                                                // ADD START 2017.01.18
            enum {
                SM_IDLE = 0,
                SM_PHASE1,
                SM_PHASE2,
                SM_PHASE3,
                SM_PHASE3_SEND_LTK,
                SM_PHASE3_SEND_EDIV,
                SM_PHASE3_SEND_ID,
                SM_PHASE3_SEND_ADDR,
                SM_PHASE3_SEND_SIG,
                SM_PHASE3_IDLE,
            }               state;
            time_t          timeOut;
            unsigned char   mconfirm[16];
            unsigned char   pres[7];
            unsigned char   preq[7];
            unsigned char   action;
            long            passKey;
                                                // ADD END 2017.01.18
        }   sm;

        struct { // Dynamically allocated(Communicated using L2CAP configuration mechanism)
            enum {
                CLOSED = 0,
                WAIT_CONNECT,
                CONFIG,
                OPEN,
                WAIT_DISCONNECT,
                WAIT_CONNECT_RSP
            }               state;
            enum {
                WAIT_CONFIG = 0,
                WAIT_SEND_CONFIG,
                WAIT_CONFIG_REQ_RSP,
                WAIT_CONFIG_RSP,
                WAIT_CONFIG_REQ,
                WAIT_IND_FINAL_RSP,
                WAIT_FINAL_RSP,
                WAIT_CONTROL_IND
            }               configState;
            enum {
                NONE = 0,
                RECONFIGURE_REQUEST,
                DISCONNECT_REQUEST
            }               event;
            time_t          timeOut;            // time() value
            unsigned char   connectionId;       // Checking a identifier for "request,response" pair
            unsigned char   configurationId;    //
            unsigned char   disconnectionId;    //
            unsigned char   configured;         // Configuration complete
            struct bt_l2capChannel *creater;    // Signaling channel

            // Proper information of "user application"
            unsigned char   userArea[8];

        }   dynamic;
    };
#endif                                          // ADD END 2017.01.08
};

//
//  API
//
extern struct bt_l2capChannel  *bt_l2capChannelGetNext(struct bt_l2capChannel **id);
extern struct bt_l2capChannel  *bt_l2capChannelFind(unsigned short handle, unsigned short peerCid, unsigned short myCid);
extern struct bt_l2capChannel  *bt_l2capChannelAdd(unsigned short handle, unsigned short peerCid, unsigned short myCid);
extern struct bt_l2capChannel  *bt_l2capChannelFindByLink(struct bt_l2capLink *link, unsigned short peerCid, unsigned short myCid); // ADD 2017.01.03
extern struct bt_l2capChannel  *bt_l2capChannelAddByLink(struct bt_l2capLink *link, unsigned short peerCid, unsigned short myCid);  // ADD 2017.01.03
extern void                     bt_l2capChannelDelete(struct bt_l2capChannel *p);
extern void                     bt_l2capChannelClear(void);                         // ADD 2015.02.03

#endif /* BT_L2CAP_CB_CHANNEL_H_ */
