//
//  bt_spec_l2cap.h
//
//  Bluetooth Protocol Stack - L2CAP Specification definition
//  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/>
//
//
//  Reference:
//      Bluetooth SIG (www.bluetooth.com)
//          BLUETOOTH SPECIFICATION Version 4.2
//          Volume 3: Core System Package [Host volume]
//          Part A: Logical Link Control and Adaptation Protocol Specification
//
//  Update history
//  ---------- ----- -------------------------------------------
//  2013.01.21 v0.0  First cording
//  2013.04.21 v0.1  Commit
//  2015.02.11 v0.3a Bug fix
//  2016.04.21 v0.3d Bug fix (L2CAP_PDU_Fixed_channel_support~)
//  2017.01.03 v0.3e BT spec 4.2
//
#ifndef BT_SPEC_L2CAP_H_
#define BT_SPEC_L2CAP_H_

#include <stdint.h>

struct bt_l2cap_Data_Packet {
    uint8_t     Length[2];
    uint8_t     CID[2];
    union {
        struct bt_l2cap_b_frame {        // Connection-oriented user data packet
            uint8_t     Payload[0];
        }       b_frame;

        struct bt_l2cap_g_frame {        // Connection less user data packet
            uint8_t     PSM[2];
            uint8_t     Payload[48];
        }       g_frame;

        struct bt_l2cap_s_frame {        // Flow controld user data packet
            uint8_t     Control[2];
            uint8_t     FCS[2];
        }       s_frame;

        struct bt_l2cap_i_frame {        // Flow controld user data packet
            uint8_t     Control[2];
            uint8_t     Payload_SDUlen_FCS[2];
        }        i_frame;

        struct bt_l2cap_c_frame {        // Connection control packet
            uint8_t     Code;
            uint8_t     Identifier;
            uint8_t     Length[2];
            union {
                struct {
                    uint8_t     Reason[2];
                    uint8_t     Data[];
                }           Command_Reject;
                struct {
                    uint8_t     PSM[2];
                    uint8_t     SourceCID[2];
                }           Connection_Request;
                struct {
                    uint8_t     DistinationCID[2];
                    uint8_t     SourceCID[2];
                    uint8_t     Result[2];
                    uint8_t     Status[2];
                }           Connection_Response;
                struct {
                    uint8_t     DistinationCID[2];
                    uint8_t     Flags[2];
                    uint8_t     Configuration_Options[0];
                }           Configuration_Request;
                struct {
                    uint8_t     SourceCID[2];
                    uint8_t     Flags[2];
                    uint8_t     Result[2];
                    uint8_t     Config[0];
                }           Configuration_Response;
                struct {
                    uint8_t     DistinationCID[2];
                    uint8_t     SourceCID[2];
                }           Disconnection_Request;
                struct {
                    uint8_t     DistinationCID[2];
                    uint8_t     SourceCID[2];
                }           Disconnection_Response;
                struct {
                    uint8_t     Data[0];
                }           Echo_Request;
                struct {
                    uint8_t     Data[0];
                }           Echo_Response;
                struct {
                    uint8_t     Info_Type[2];
                }           Information_Request;
                struct {
                    uint8_t     Info_Type[2];
                    uint8_t     Result[2];
                    uint8_t     Data[0];
                }           Information_Response;
                                        // ADD START 2017.01.03
                struct {
                    uint8_t     PSM[2];
                    uint8_t     SourceCID[2];
                    uint8_t     ControllerID;
                }           Create_Channel_Request;
                struct {
                    uint8_t     DistinationCID[2];
                    uint8_t     SourceCID[2];
                    uint8_t     Result[2];
                    uint8_t     Status[2];
                }           Create_Channel_Response;
                struct {
                    uint8_t     InitiatorCID[2];
                    uint8_t     DestControllerID;
                }           Move_Channel_Request;
                struct {
                    uint8_t     InitiatorCID[2];
                    uint8_t     Result[2];
                }           Move_Channel_Response;
                struct {
                    uint8_t     InitiatorCID[2];
                    uint8_t     Result[2];
                }           Move_Channel_Confirmation;
                struct {
                    uint8_t     InitiatorCID[2];
                }           Move_Channel_Confirmation_Response;
                struct {
                    uint8_t     IntervalMin[2];
                    uint8_t     IntervalMax[2];
                    uint8_t     SlaveLatency[2];
                    uint8_t     TimeoutMultiplier[2];
                }           Connection_Parameters_Update_Request;
                struct {
                    uint8_t     Result[2];
                }           Connection_Parameters_Update_Response;
                struct {
                    uint8_t     LE_PSM[2];
                    uint8_t     SourceCID[2];
                    uint8_t     MTU[2];
                    uint8_t     MPS[2];
                    uint8_t     InitialCredits[2];
                }           LE_Credit_Based_Connection_Request;
                struct {
                    uint8_t     DestinationCID[2];
                    uint8_t     MTU[2];
                    uint8_t     MPS[2];
                    uint8_t     InitialCredits[2];
                    uint8_t     Result[2];
                }           LE_Credit_Based_Connection_Response;
                struct {
                    uint8_t     CID[2];
                    uint8_t     Credits[2];
                }           LE_Flow_Control_Credit;
                                        // ADD END 2017.01.03
            }           Data;
        }       c_frame;                // CID=0x0001 or 0x0005

                                        // ADD START 2017.01.03
        struct bt_l2cap_le_frame {      // LE Credit Based Flow Control packet
            uint8_t     Length[2];
            uint8_t     Payload[0];
        }       le_frame;               //
                                        // ADD END 2017.01.03

    };
}  __attribute__ ((packed));

#define L2CAP_Data_Packet_HeadSize          4   // Length + CID
#define L2CAP_Data_Packet_C_Frame_HeadSize  4   // Code + ID + Length

//#define L2CAP_CID_C_Frame                            0x0001
//#define L2CAP_CID_G_Frame                            0x0002
//#define L2CAP_CID_B_Frame                            0x0040

#define L2CAP_CID_L2CAP_Signaling_channel               0x0001  // ACL-U
#define L2CAP_CID_Connectionless_channel                0x0002  // ACL-U
#define L2CAP_CID_AMP_Manager_Protocol                  0x0003  // ACL-U
#define L2CAP_CID_Attribute_Protocol                    0x0004  // LE-U
#define L2CAP_CID_Low_Energy_L2CAP_Signaling_channel    0x0005  // LE-U
#define L2CAP_CID_Security_Manager_Protocol             0x0006  // LE-U
#define L2CAP_CID_BR_EDR_Security_Manager               0x0007  // ACL-U  ADD 2016.04.21
#define L2CAP_CID_AMP_Test_Manager                      0x003f  // ACL-U
#define L2CAP_CID_Dynamically_allocated                 0x0040  // ACL-U,AMP-U

#define L2CAP_PDU_Code_Command_reject                   0x01
#define L2CAP_PDU_Code_Connection_request               0x02
#define L2CAP_PDU_Code_Connection_response              0x03
#define L2CAP_PDU_Code_Configure_request                0x04
#define L2CAP_PDU_Code_Configure_response               0x05
#define L2CAP_PDU_Code_Disconnection_request            0x06
#define L2CAP_PDU_Code_Disconnection_response           0x07
#define L2CAP_PDU_Code_Echo_request                     0x08
#define L2CAP_PDU_Code_Echo_response                    0x09
#define L2CAP_PDU_Code_Information_request              0x0a
#define L2CAP_PDU_Code_Information_response             0x0b
#define L2CAP_PDU_Code_Create_Channel_request               0x0c    // ADD 2017.01.03  AMP
#define L2CAP_PDU_Code_Create_Channel_response              0x0d    // ADD 2017.01.03  AMP
#define L2CAP_PDU_Code_Move_Channel_request                 0x0e    // ADD 2017.01.03  AMP
#define L2CAP_PDU_Code_Move_Channel_response                0x0f    // ADD 2017.01.03  AMP
#define L2CAP_PDU_Code_Move_Channel_Confirmation            0x10    // ADD 2017.01.03  AMP
#define L2CAP_PDU_Code_Move_Channel_Confirmation_response   0x11    // ADD 2017.01.03  AMP
#define L2CAP_PDU_Code_Connection_Parameter_Update_request  0x12    // ADD 2017.01.03  LE
#define L2CAP_PDU_Code_Connection_Parameter_Update_response 0x13    // ADD 2017.01.03  LE
#define L2CAP_PDU_Code_LE_Credit_Based_Connection_request   0x14    // ADD 2017.01.03  LE
#define L2CAP_PDU_Code_LE_Credit_Based_Connection_response  0x15    // ADD 2017.01.03  LE
#define L2CAP_PDU_Code_LE_Flow_Control_Credit               0x16    // ADD 2017.01.03  LE

#define L2CAP_PDU_Reason_Command_not_understood         0x0000
#define L2CAP_PDU_Reason_Signalling_MTU_exceeded        0x0001
#define L2CAP_PDU_Reason_invalid_CID_in_request         0x0002

#define L2CAP_PDU_PSM_Service_Discovery_Protocol        0x0001
#define L2CAP_PDU_PSM_RFCOMM                            0x0003
#define L2CAP_PDU_PSM_Telephony_Control_Protocol        0x0005
#define L2CAP_PDU_PSM_TCS_cordless                      0x0007
#define L2CAP_PDU_PSM_BNEP                              0x000F
#define L2CAP_PDU_PSM_HID_Control                       0x0011
#define L2CAP_PDU_PSM_HID_Interrupt                     0x0013
#define L2CAP_PDU_PSM_UPnP_ESDP                         0x0015
#define L2CAP_PDU_PSM_AVCTP                             0x0017
#define L2CAP_PDU_PSM_AVDTP                             0x0019
#define L2CAP_PDU_PSM_AVCTP_Browsing                    0x001b
#define L2CAP_PDU_PSM_UDI_C_Plane                       0x001d
#define L2CAP_PDU_PSM_ATT                               0x001f

#define L2CAP_PDU_Result_Connection_successful                                  0x0000
#define L2CAP_PDU_Result_Connection_pending                                     0x0001
#define L2CAP_PDU_Result_Connection_refused_PSM_not_supported                   0x0002
#define L2CAP_PDU_Result_Connection_refused_security_block                      0x0003
#define L2CAP_PDU_Result_Connection_refused_no_resources_available              0x0004
#define L2CAP_PDU_Result_Connection_refused_Controller_ID_not_supported         0x0005  // ADD 2017.01.03
#define L2CAP_PDU_Result_Connection_refused_Invalid_Source_CID                  0x0006  // ADD 2017.01.03
#define L2CAP_PDU_Result_Connection_refused_Source_CID_already_allocated        0x0007  // ADD 2017.01.03
#define L2CAP_PDU_Result_Connection_refused_LE_PSM_not_supported                0x0002  // ADD 2017.01.03  LE
#define L2CAP_PDU_Result_Connection_refused_LE_insufficient_authentication      0x0005  // ADD 2017.01.03  LE
#define L2CAP_PDU_Result_Connection_refused_LE_insufficient_authorization       0x0006  // ADD 2017.01.03  LE
#define L2CAP_PDU_Result_Connection_refused_LE_insufficient_encryption_key_size 0x0007  // ADD 2017.01.03  LE
#define L2CAP_PDU_Result_Connection_refused_LE_insufficient_encryption          0x0008  // ADD 2017.01.03  LE
#define L2CAP_PDU_Result_Connection_refused_LE_Invalid_Source_CID               0x0009  // ADD 2017.01.03  LE
#define L2CAP_PDU_Result_Connection_refused_LE_Source_CID_already_allocated     0x000a  // ADD 2017.01.03  LE
#define L2CAP_PDU_Result_Move_success                                           0x0000  // ADD 2017.01.03
#define L2CAP_PDU_Result_Move_failure                                           0x0001  // ADD 2017.01.03
#define L2CAP_PDU_Result_Move_Pending                                           0x0001  // ADD 2017.01.03
#define L2CAP_PDU_Result_Move_refused_Controller_ID_not_supported               0x0002  // ADD 2017.01.03
#define L2CAP_PDU_Result_Move_refused_new_Controller_ID_is_same_as_old_Controller_ID  0x0003  // ADD 2017.01.03
#define L2CAP_PDU_Result_Move_refused_Configuration_not_supported               0x0004  // ADD 2017.01.03
#define L2CAP_PDU_Result_Move_refused_Move_Channel_collision                    0x0005  // ADD 2017.01.03
#define L2CAP_PDU_Result_Move_refused_Channel_not_allowed_to_be_moved           0x0006  // ADD 2017.01.03
#define L2CAP_PDU_Result_Configuration_Success                                  0x0000
#define L2CAP_PDU_Result_Configuration_Failure_unacceptable_parameters          0x0001
#define L2CAP_PDU_Result_Configuration_Failure_rejected                         0x0002
#define L2CAP_PDU_Result_Configuration_Failure_unknown_options                  0x0003
#define L2CAP_PDU_Result_Configuration_Pending                                  0x0004
#define L2CAP_PDU_Result_Configuration_Failure_flow_spec_rejected               0x0005
#define L2CAP_PDU_Result_Success                                    0x0000
#define L2CAP_PDU_Result_Failure_unacceptable_parameters            0x0001
#define L2CAP_PDU_Result_Failure_rejected                           0x0002
#define L2CAP_PDU_Result_Failure_unknown_options                    0x0003
        
#define L2CAP_PDU_Status_No_further_information_available           0x0000
#define L2CAP_PDU_Status_Authentication_pending                     0x0001
#define L2CAP_PDU_Status_Authorization_pending                      0x0002


#define L2CAP_PDU_Info_Type_Connectionless_MTU                      0x0001
#define L2CAP_PDU_Info_Type_Extended_features_supported             0x0002
#define L2CAP_PDU_Info_Type_Fixed_Channels_Supported                0x0003

#ifdef DEL                              // DEL START 2016.04.21
#define L2CAP_PDU_Extended_feature_Flow_control_mode                        0x00000001
#define L2CAP_PDU_Extended_feature_Retransmission_mode                      0x00000002
#define L2CAP_PDU_Extended_feature_Bi_directional_QoS1                      0x00000004
#define L2CAP_PDU_Extended_feature_Enhanced_Retransmission_Mode             0x00000008
#define L2CAP_PDU_Extended_feature_Streaming_Mode                           0x00000010
#define L2CAP_PDU_Extended_feature_FCS_Option                               0x00000020
#define L2CAP_PDU_Extended_feature_Extended_Flow_Specification_for_BR_EDR   0x00000040
#define L2CAP_PDU_Extended_feature_Fixed_Channels                           0x00000080
#define L2CAP_PDU_Extended_feature_Extended_Window_Size                     0x00000100
#define L2CAP_PDU_Extended_feature_Unicast_Connectionless_Data_Reception    0x00000200

#define L2CAP_PDU_Fixed_channel_support_Null_identifier                     0x00000001
#define L2CAP_PDU_Fixed_channel_support_L2CAP_Signaling_channel             0x00000002
#define L2CAP_PDU_Fixed_channel_support_Connectionless_reception            0x00000004
#define L2CAP_PDU_Fixed_channel_support_AMP_Manager_Protocol_Channel        0x00000008
#define L2CAP_PDU_Fixed_channel_support2_AMP_Test_Manager                   0x80000000

#else                                   // DEL ADD  2016.02.21 
#define L2CAP_PDU_Extended_feature_Flow_control_mode                        (1UL << 0)
#define L2CAP_PDU_Extended_feature_Retransmission_mode                      (1UL << 1)
#define L2CAP_PDU_Extended_feature_Bi_directional_QoS1                      (1UL << 2)
#define L2CAP_PDU_Extended_feature_Enhanced_Retransmission_Mode             (1UL << 3)
#define L2CAP_PDU_Extended_feature_Streaming_Mode                           (1UL << 4)
#define L2CAP_PDU_Extended_feature_FCS_Option                               (1UL << 5)
#define L2CAP_PDU_Extended_feature_Extended_Flow_Specification_for_BR_EDR   (1UL << 6)
#define L2CAP_PDU_Extended_feature_Fixed_Channels                           (1UL << 7)
#define L2CAP_PDU_Extended_feature_Extended_Window_Size                     (1UL << 8)
#define L2CAP_PDU_Extended_feature_Unicast_Connectionless_Data_Reception    (1UL << 9)

#define L2CAP_PDU_Fixed_channel_support_Null_identifier                     (1ULL << 0)
#define L2CAP_PDU_Fixed_channel_support_L2CAP_Signaling_channel             (1ULL << 1)
#define L2CAP_PDU_Fixed_channel_support_Connectionless_reception            (1ULL << 2)
#define L2CAP_PDU_Fixed_channel_support_AMP_Manager_Protocol_Channel        (1ULL << 3)
#define L2CAP_PDU_Fixed_channel_support_BR_EDR_Security_Manager             (1ULL << 7)
#define L2CAP_PDU_Fixed_channel_support_AMP_Test_Manager                    (1ULL << 63)
#endif                                  // ADD END 2016.04.21

                                        // ADD START 2017.01.03
struct bt_l2cap_Configuration_Option {
    uint8_t Type;
    uint8_t Length;
    union {
        uint8_t Data[1];
        struct {
            uint8_t MTU[2];
        } MTU;
        struct {
            uint8_t Flush_Timeout[2];
        } Flush_Timeout;
        struct {
            uint8_t Flags;
            uint8_t Service_Type;
            uint8_t Token_Rate[2];
            uint8_t Token_Bucket_Size[4];
            uint8_t Peak_Bandwidth[4];
            uint8_t Latency[4];
            uint8_t Delay_Variation[4];
        } QoS;
        struct {
            uint8_t Mode;
            uint8_t TxWindow_size;
            uint8_t Max_Transmit;
            uint8_t Retransmission_TimeOut[2];
            uint8_t Monitor_TimeOut[2];
            uint8_t Maximum_PDU_size[2];
        } Retransmission;
        struct {
            uint8_t FCS_Type;
        } FCS;
        struct {
            uint8_t Identifier;
            uint8_t Service_Type;
            uint8_t Maximum_SDU_Size[2];
            uint8_t SDU_InterArrival_Time[4];
            uint8_t Access_Latency[4];
            uint8_t Flush_Timeout[4];
        } Extended_Flow;
        struct {
            uint8_t Max_Window_Size[2];
        } Extended_Window_Size;
    }   Option;
}  __attribute__ ((packed));

#define L2CAP_Configuration_Option_HeadSize          2   // Length + Type

#define L2CAP_PDU_Configuration_option_Type_MTU                     0x01
#define L2CAP_PDU_Configuration_option_Type_Flush_Timeout           0x02
#define L2CAP_PDU_Configuration_option_Type_QoS                     0x03
#define L2CAP_PDU_Configuration_option_Type_Retransmission          0x04
#define L2CAP_PDU_Configuration_option_Type_FCS                     0x05
#define L2CAP_PDU_Configuration_option_Type_Extended_Flow           0x06
#define L2CAP_PDU_Configuration_option_Type_Extended_Window_Size    0x07

#define L2CAP_PDU_Configuration_option_QoS_Service_Type_No_traffic  0x00
#define L2CAP_PDU_Configuration_option_QoS_Service_Type_Best_effort 0x01
#define L2CAP_PDU_Configuration_option_QoS_Service_Type_Guaranteed  0x02
#define L2CAP_PDU_Configuration_option_Retransmission_L2CAP_Basic_Mode              0x00
#define L2CAP_PDU_Configuration_option_Retransmission_Retransmission_mode           0x01
#define L2CAP_PDU_Configuration_option_Retransmission_Flow_control_mode             0x02
#define L2CAP_PDU_Configuration_option_Retransmission_Enhanced_Retransmission_mode  0x03
#define L2CAP_PDU_Configuration_option_Retransmission_Streaming_mode                0x04
#define L2CAP_PDU_Configuration_option_FCS_Types_No_FCS             0x00
#define L2CAP_PDU_Configuration_option_FCS_Types_No_16bit           0x01
                                        // ADD END 2017.01.03


//
//  Implement tool
//
// Byte order normalize
#ifdef DELETE                           // DEL START 2015.02.11
#define L2CAP_UINT16(a)       (uint16_t)(a[0] | (a[1] << 8))
#define L2CAP_UINT24(a)       (uint32_t)(a[0] | (a[1] << 8) | (a[2] << 16))
#define L2CAP_UINT32(a)       (uint32_t)(a[0] | (a[1] << 8) | (a[2] << 16) | (a[3] << 24))
#define L2CAP_STORE16(d,s)    (d[0] = (uint8_t)(s), d[1] = (uint8_t)((s) >> 8))
#define L2CAP_STORE24(d,s)    (d[0] = (uint8_t)(s), d[1] = (uint8_t)((s) >> 8), d[2] = (uint8_t)((s) >> 16))
#define L2CAP_STORE32(d,s)    (d[0] = (uint8_t)(s), d[1] = (uint8_t)((s) >> 8), d[2] = (uint8_t)((s) >> 16), d[3] = (uint8_t)((s) >> 24))
#else                                   // DEL END / ADD START 2015.02.11
#define L2CAP_UINT16(a)       (uint16_t)((a)[0] | ((a)[1] << 8))
#define L2CAP_UINT24(a)       (uint32_t)((a)[0] | ((a)[1] << 8) | ((a)[2] << 16))
#define L2CAP_UINT32(a)       (uint32_t)((a)[0] | ((a)[1] << 8) | ((a)[2] << 16) | ((a)[3] << 24))
#define L2CAP_STORE16(d,s)    ((d)[0] = (uint8_t)(s), (d)[1] = (uint8_t)((s) >> 8))
#define L2CAP_STORE24(d,s)    ((d)[0] = (uint8_t)(s), (d)[1] = (uint8_t)((s) >> 8), (d)[2] = (uint8_t)((s) >> 16))
#define L2CAP_STORE32(d,s)    ((d)[0] = (uint8_t)(s), (d)[1] = (uint8_t)((s) >> 8), (d)[2] = (uint8_t)((s) >> 16), (d)[3] = (uint8_t)((s) >> 24))
#define L2CAP_STORE64(d,s)    ((d)[0] = (uint8_t)(s), (d)[1] = (uint8_t)((s) >> 8), (d)[2] = (uint8_t)((s) >> 16), (d)[3] = (uint8_t)((s) >> 24), (d)[4] = (uint8_t)((s) >> 32), (d)[5] = (uint8_t)((s) >> 40), (d)[6] = (uint8_t)((s) >> 48), (d)[7] = (uint8_t)((s) >> 56))   // ADD 2016.04.21
#endif                                  // ADD END 2015.02.11
#endif /* BT_SPEC_L2CAP_H_ */
