//
//  bt_l2cap_resource_manager.c
//
//  Bluetooth Protocol Stack - L2CAP Resource Manager
//  Copyright (C) 2013-2018 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/>
//
//
//  Summary:
//      Bluetooth controller link keeping
//      Message send/receive
//      Message segmentation/reassemble
//      Root task
//      Server function support only
//
//  Reference:
//      Bluetooth SIG (www.bluetooth.com)
//          BLUETOOTH SPECIFICATION Version 4.0
//          [Vol 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
//  2014.02.23 v0.1a Supported the Security Manager
//  2014.03.05 v0.2  Change the USB process calling
//  2015.02.03 v0.3  Supported the PIC32
//  2015.02.06 v0.3a Supported the Secure Simple Pairing
//  2015.02.11 v0.3a Supported the Class of Device Specification definition
//  2015.02.20 v0.3b Bug fix (Service UUID is un-match)
//  2016.02.12 v0.3c Appended a return code, Supported the XC32 v1.40
//  2016.02.19 v0.3c+ Change of the PIN response(HCI command/event)
//  2016.04.21 v0.3d Appended a API for SSP
//  2017.01.03 v0.3e argument handle -> cb_link
//  2017.01.08 v0.3e Appended a authentication function for the classic services
//  2017.01.18 v0.3f Appended a authentication function for the SM
//  2017.02.06 v0.3g Supported a 16bit UUID
//  2017.02.11 v0.3h The new "bt_config.h"
//  2017.02.12 v0.3i Appended a Advertise on/off control and Disconnect request
//  2017.02.16 v0.3j Supported an advertise configure
//  2017.03.10 v0.4  Supported an AVDTP
//  2017.04.26 v0.4  Bug fix
//  2018.02.10 v0.4a Bug fix, SSP sequence
//
#include <stddef.h>
#include <string.h>
#include <time.h>                       // ADD 2014.03.05
#include "bt_hci.h"                     // HCI Access API
#include "bt_spec_hci.h"                // HCI Message format
#include "bt_spec_gap.h"                // Generic Access Profile
#include "bt_spec_l2cap.h"              // ADD 2017.03.10
#include "bt_l2cap_cb_common.h"         //
#include "bt_l2cap_cb_service.h"        // ADD 2015.02.03
#include "bt_l2cap_cb_device.h"         //
#include "bt_l2cap_cb_link.h"           //
#include "bt_l2cap_cb_channel.h"        // ADD 2015.02.03
#include "bt_l2cap_channel_manager.h"   //
#include "bt_l2cap_resource_manager.h"  //
//#include "bt_spec_att.h"              // DEL 2015.02.20  Service UUID
//#include "bt_att_db.h"                // DEL 2017.02.11  Service UUID
#include "bt_spec_cod.h"                // Class of device
#include "bt_security_manager.h"        // ADD 2017.01.18
#include "bt_config.h"                  // ADD 2017.02.11

// Configure
//#define BT_PIN_CODE           "0000"  // DEL 2016.04.21
#define BT_SEND_TIMEOUT         3       // CHG 2014.03.05  [sec]
#define BT_RECIEVE_TIMEOUT      3       // CHG 2014.03.05  [sec]
//#define BT_INIT_TIMEOUT       100000  // DEL 2014.03.05
#define BT_CONFIRM_TIMEOUT      30      // ADD 2016.04.21  [sec]
#define BT_PASSKEY_TIMEOUT      30      // ADD 2016.04.21  [sec]
//#define BT_INIT_DETECT_ENABLE         // DEL 2017.02.11  BR/EDR Inquiry scan enable
//#define BT_INIT_LE_DETECT_ENABLE      // DEL 2017.02.11  LE advertise enable
//#define DEBUG                         // Debug mode = on
//#define DEBUG2                  32    // ACL message dump maximum bytes size
//#define DEBUG3                        // State

// Inline functions
#define MIN(a,b)        ((a)<(b)?(a):(b))
//#define INIT_UU16(a)    ATT_INITUUID16TO128(a)// DEL 2015.02.20 Alias
//#define INIT_UU128(a)   ATT_INITUUID128(a)    // DEL 2015.02.20 Alias
//#define INIT_HANDLE(a)  ATT_INIT16(a)         // DEL 2015.02.20 Alias
#define UU128(a)        HCI_UUID128_DATA(a)     // ADD 2015.02.20 Alias
#define MEMCPY(d,s)     memcpy(d, s, sizeof(d)) // ADD 2014.02.23
#define MEMCMP(d,s)     memcmp(d, s, sizeof(d)) // ADD 2017.01.18
#define MEMSET(d,c)     memset(d, c, sizeof(d)) // ADD 2017.01.18

// Debugging tools
#ifdef DEBUG
#include <stdio.h>                        // Debug
void bt_l2capResourceManagerDumpStr(char *t, unsigned char *p, int l){
    int i;

    printf(t);
    for(i = 0; i < l; i++) {
        if (((i % 4) == 0) && (i > 0)) {
            printf(",");
        }
        printf("%02x", *p++);
    }
    printf("\n");
}
void bt_l2capResourceManagerDumpNum(char *t, unsigned char *p, int l){
    printf(t);
    while(--l >= 0) {
        if (((l % 4) == 0) && (l > 0)) {
            printf(",");
        }
        printf("%02x", *(p+l));
    }
    printf("\n");
}
#define DEBUGP(...)     printf(__VA_ARGS__)
//#define DUMP(t,p)     bt_l2capResourceManagerDumpStr(t,p,sizeof(p))
#define DUMP(t,p)       bt_l2capResourceManagerDumpNum(t,p,sizeof(p))
#define DUMPS(t,p)      bt_l2capResourceManagerDumpStr(t,p,sizeof(p))
#define DUMPN(t,p)      bt_l2capResourceManagerDumpNum(t,p,sizeof(p))
#else
#define DEBUGP(...)
#define DUMP(...)
#define DUMPS(...)
#define DUMPN(...)
#endif

//
//    Global area
//
#ifdef DELETE                                           // DEL START 2017.01.18
//struct bt_l2capCommon    bt_l2capCommon;              // DEL 2016.04.21
                                                        // ADD START 2016.04.21
struct bt_l2capCommon    bt_l2capCommon = {
    .myIoCapability   = HCI_Parm_IO_Capability_NoInputNoOutput,
    .myAuthentication = HCI_Parm_Authentication_Requirements_General_Bonding_Numeric_Comparison,
    .myOobDataPresent = HCI_Parm_OOB_Data_Present_Not,
};
                                                        // ADD END 2016.04.21
#endif                                                  // DEL END 2017.01.18

//
//  Internal routines  
//

// User own code (default)                              // ADD START 2016.04.21
int _bt_l2capResourceManagerPinCodeRequest(struct bt_l2capDevice *dev, unsigned char pinCode[16]) {
    memcpy(pinCode, "0000", 5);
    return(4);
}
int _bt_l2capResourceManagerNumericComparison(struct bt_l2capDevice *dev, long numericValue) {
    return(0);       // OK
}
long _bt_l2capResourceManagerPasskeyEntryInput(struct bt_l2capDevice *dev) {
    return(123456);  // Passkey = 000000 .. 999999
}
void _bt_l2capResourceManagerPasskeyEntryDisplay(struct bt_l2capDevice *dev, long numericValue) {
    return;
}
int  bt_l2capResourceManagerPinCodeRequest()        __attribute__ ((weak, alias ("_bt_l2capResourceManagerPinCodeRequest")));
int  bt_l2capResourceManagerNumericComparison()     __attribute__ ((weak, alias ("_bt_l2capResourceManagerNumericComparison")));
long bt_l2capResourceManagerPasskeyEntryInput()     __attribute__ ((weak, alias ("_bt_l2capResourceManagerPasskeyEntryInput")));
void bt_l2capResourceManagerPasskeyEntryDisplay()   __attribute__ ((weak, alias ("_bt_l2capResourceManagerPasskeyEntryDisplay")));
                                                        // ADD END 2016.04.21

//
//  Run loop
//
//int bt_l2capResourceManager(void){                    // CHG 2014.03.05
int bt_l2capResourceManager(int init){                  // CHG 2014.03.05
    static struct bt_hci_Command_Packet     cmd;
    static struct bt_hci_Event_Packet       evt;
    static struct bt_hci_ACL_Data_Packet    aclIn;
    static struct bt_hci_ACL_Data_Packet    aclOut;
    static size_t                           aclInSize;
    static size_t                           aclOutSize;

//  static int                              init = 0;   // DEL 2014.03.05
//  static long                             try;        // DEL 2014.03.05
    static time_t                           timeo;      // ADD 2014.03.05
    static unsigned char                   *ci;
    static int                              send_len;
    static struct bt_l2capDevice           *nowDev;
    static struct bt_l2capLink             *nowLnk;

    static enum {
        UNPLUGED = 0,
        PLUGED,
        WAIT_UNPLUG,                    // ADD 2015.02.06
        INIT_COMMAND_SEND,
        INIT_COMMAND_STATUS,
        LE_INIT_COMMAND_SEND,
        LE_INIT_COMMAND_STATUS,
        EVENT_WAIT,
        DISCONNECT_SEND,                // ADD 2017.02.12
        ACCEPT_CONNECT_SEND,
        REJECT_CONNECT_SEND,
        AUTH_REQ_SEND,					// ADD 2018.02.10
        LINK_KEY_REP_SEND,
        LINK_KEY_NEG_SEND,
        PIN_CODE_REP_SEND,
        PIN_CODE_NEG_SEND,
        IO_CAP_REP_SEND,                // ADD 2015.02.06
        IO_CAP_NEG_SEND,                // ADD 2015.02.06
        USER_CNF_REP_SEND,              // ADD 2015.02.06
        USER_CNF_NEG_SEND,              // ADD 2015.02.06
        USER_PASS_REP_SEND,             // ADD 2015.02.06
        USER_PASS_NEG_SEND,             // ADD 2015.02.06
        LE_ADV_START_SEND,
        LE_ADV_STOP_SEND,
        LE_LE_LTK_REP_SEND,
        LE_LE_LTK_NEG_SEND,
        PROCESS,
        DATA_RECIEVE,					// ADD 2017.03.10
        DATA_SEND
    }        state;
    static enum {
        LE_DISABLE = 0,
        LE_STANDBY,
        LE_ADVERTISING,
        LE_SCANNING,
        LE_INITIATING,
        LE_CONNECTION_MASTER_ROLE,
        LE_CONNECTION_SLAVE_ROLE
    }        leState;
    int        rc;

//#define HCI_OPCODE_DATA(a)        (unsigned char)a,(unsigned char)(a >> 8)
//#define HCI_UINT16_DATA(a)        (unsigned char)a,(unsigned char)(a >> 8)
    const static unsigned char initCmds[] = {
        HCI_OPCODE_DATA(HCI_Reset),
        0,          // Len

        HCI_OPCODE_DATA(HCI_Set_Event_Mask),        // ADD 2015.02.06 bug
        8,          // Len                          // ADD 2015.02.06
        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x1f,    // ADD 2015.02.06 Except LE Meta-Event

        HCI_OPCODE_DATA(HCI_Read_Local_Version_Information),
        0,          // Len

        HCI_OPCODE_DATA(HCI_Read_Local_Supported_Commands),
        0,          // Len

        HCI_OPCODE_DATA(HCI_Read_Local_Supported_Features),
        0,          // Len

        HCI_OPCODE_DATA(HCI_Read_Local_Extended_Features),
        1,          // Len
        0,          // Page#

//      HCI_OPCODE_DATA(HCI_Read_Buffer_Size),	// DEL 2017.03.10
//      0,          // Len						// DEL 2017.03.10

        HCI_OPCODE_DATA(HCI_Read_BD_ADDR),
        0,          // Len

        HCI_OPCODE_DATA(HCI_Host_Buffer_Size),
        7,          // Len
        HCI_UINT16_DATA(sizeof(aclIn)), // Host_ACL_Data_Packet_Length
        0,                              // Host_Synchronous_Data_Packet_Length -> not use
        HCI_UINT16_DATA(1),             // Host_Total_Num_ACL_Data_Packets
        HCI_UINT16_DATA(0),             // Host_Total_Num_Synchronous_Data_Packets -> not use

        HCI_OPCODE_DATA(HCI_Read_Buffer_Size),	// ADD 2017.03.10
        0,          // Len						// ADD 2017.03.10

#ifdef BT_DEVICE_CLASS                                                          // ADD 2017.03.10
        HCI_OPCODE_DATA(HCI_Write_Class_of_Device),
        3,          // Len
        HCI_UINT24_DATA(BT_DEVICE_CLASS),                                       // ADD 2017.03.10
//      HCI_UINT24_DATA(COS_MAJOR_Capturing | COD_Peripheral_Sensing_device),   // ADD 2015.02.11  DEL 2017.03.10
//      0x12, 0x01, 0x80,                                                       // DEL 2015.02.11
#endif                                                                          // ADD 2017.03.10

#ifdef BT_LOCAL_NAME                                        // ADD 2017.02.11
        HCI_OPCODE_DATA(HCI_Write_Local_Name),
        BT_LOCAL_NAME,                                      // ADD 2017.02.11
//      12,         // Len                                  // DEL 2017.02.11
//      'B','l','u','e','t','o','o','t','h','4','P','\0',   // DEL 2017.02.11
#endif                                                      // ADD 2017.02.11

        HCI_OPCODE_DATA(HCI_Write_Simple_Pairing_Mode),     // ADD 2015.02.06
        1,          // Len                                  // ADD 2015.02.06
        HCI_Parm_Simple_Pairing_Mode_Enable,                // ADD 2015.02.06

#ifdef BT_INIT_DETECT_ENABLE
        HCI_OPCODE_DATA(HCI_Write_Scan_Enable),
        1,          // Len
        HCI_Parm_Scan_Enable_Inquiry_Scan | HCI_Parm_Scan_Enable_Page_Scan,
#endif

        0xff        // Terminate
    };

    const static unsigned char initLECmds[] = {
        HCI_OPCODE_DATA(HCI_Read_Local_Supported_Features),
        0,          // Len

        HCI_OPCODE_DATA(HCI_Set_Event_Mask),
        8,          // Len
        0xff,0xff,0xff,0xff,0xff,0xff,0xff,0x3f,    // All enable

        HCI_OPCODE_DATA(HCI_LE_Set_Event_Mask),
        8,          // Len
        0x1f,0x00,0x00,0x00,0x00,0x00,0x00,0x00,    // All enable

        HCI_OPCODE_DATA(HCI_LE_Read_Buffer_Size),
        0,          // Len

        HCI_OPCODE_DATA(HCI_LE_Read_Local_Supported_Features),
        0,          // Len

        HCI_OPCODE_DATA(HCI_LE_Read_White_List_Size),
        0,          // Len

        HCI_OPCODE_DATA(HCI_LE_Clear_White_List),
        0,          // Len

        HCI_OPCODE_DATA(HCI_LE_Set_Advertising_Parameters),
        15,         // Len
        0x00, 0x08, // Advertising_Interval_Min=1.28s
        0x00, 0x08, // Advertising_Interval_Max=1.28s
        0x00,       // Advertising_Type=ADV_IND
        0x00,       // Own_Address_Type=public
        0x00,       // Direct_Address_Type=public
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,    // Direct_Address
        0b00000111, // Advertising_Channel_Map all(37-39)
        0x00,       // Advertising_Filter_Policy=any

        HCI_OPCODE_DATA(HCI_LE_Read_Advertising_Channel_TX_Power),
        0,          // Len

        HCI_OPCODE_DATA(HCI_LE_Set_Advertising_Data),
        BT_LE_ADVERTISING,
#ifdef DELETE                           // DEL START 2017.02.16
        32,         // Len
        21,         // Advertising_Data_Length
                    // Advertising_Data start
         2, GAP_AD_Type_Flags,
            GAP_AD_Flags_Simultaneous_LE_BR_EDR_Host | GAP_AD_Flags_Simultaneous_LE_BR_EDR_Controller | GAP_AD_Flags_LE_General_Discoverable_Mode,
//#ifdef ATT_DATA_SERVICE_UUID128       // ADD 2017.01.18 DEL 2017.02.11
#ifdef BT_ATT_SERVICE_UUID128           //                ADD 2017.02.11
        17, GAP_AD_Type_128bit_Service_UUIDs_Complete,
//          UU128(ATT_DATA_SERVICE_UUID128),            // DEL 2017.02.11
            UU128(BT_ATT_SERVICE_UUID128),              // ADD 2017.02.11
#else                                   // ADD START 2017.01.18
         3, GAP_AD_Type_16bit_Service_UUIDs_Complete,
//          HCI_UINT16_DATA(ATT_DATA_SERVICE_UUID16),   // DEL 2017.02.11
            HCI_UINT16_DATA(BT_ATT_SERVICE_UUID16),     // ADD 2017.02.11
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
#endif                                  // ADD END 2017.01.18
        0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
        0x00, 0x00,
                    // Advertising_Data end
#endif                                  // DEL END 2017.02.16

#ifdef BT_LE_SCAN_RESPONSE                                  // ADD 2017.02.11
        HCI_OPCODE_DATA(HCI_LE_Set_Scan_Response_Data),
        BT_LE_SCAN_RESPONSE,                                // ADD 2017.02.11
//      32,         // Len                                  // DEL 2017.02.11
//      14,         // Scan_Response_Data_Length,           // DEL 2017.02.11
//                  // Scan_Response_Data                   // DEL 2017.02.11
//      12,  GAP_AD_Type_Shortened_local_name,              // DEL 2017.02.11
//              'B','l','u','e','t','o','o','t','h','4','P',// DEL 2017.02.11
//      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     // DEL 2017.02.11
//      0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,     // DEL 2017.02.11
//      0x00, 0x00,                                         // DEL 2017.02.11
#endif                                                      // ADD 2017.02.11

        HCI_OPCODE_DATA(HCI_LE_Set_Scan_Parameters),
        7,           // Len
        0x00,        // LE_Scan_Type=passive
        0x10, 0x00,  // LE_Scan_Interval=10ms
        0x10, 0x00,  // LE_Scan_Window=10ms
        0x00,        // Own_Address_Type=public
        0x00,        // Scanning_Filter_Policy=all

        HCI_OPCODE_DATA(HCI_Write_LE_Host_Supported),
        2,           // Len
        0x01,        // LE_Supported_Host=enable
        0x00,        // Simultaneous_LE_Host=disable

                     // ADD START 2017.01.18
        HCI_OPCODE_DATA(HCI_LE_Rand),
        0,           // Len
        HCI_OPCODE_DATA(HCI_LE_Rand),
        0,           // Len
                     // ADD END 2017.01.18

#ifdef BT_INIT_LE_DETECT_ENABLE
        HCI_OPCODE_DATA(HCI_LE_Set_Advertise_Enable),
        1,           // Len
        0x01,        // Advertising_Enable=enable
#endif

        0xff
    };

    //
    // main
    //
    if (init == 0) {
//      init = 1;                       // DEL 2014.03.05
        bt_setHCIcommandBuf((unsigned char *)&cmd,    sizeof(cmd));
        bt_setHCIeventBuf(  (unsigned char *)&evt,    sizeof(evt));
        bt_setACLoutBuf(    (unsigned char *)&aclOut, sizeof(aclOut));  // bt_hci.c
        bt_setACLinBuf(     (unsigned char *)&aclIn,  sizeof(aclIn));   //
        aclInSize  = sizeof(aclIn);
        aclOutSize = sizeof(aclOut);
        state      = UNPLUGED;
        leState    = LE_DISABLE;        // ADD 2014.03.05
        nowDev     = NULL;              // ADD 2014.03.05
        nowLnk     = NULL;              // ADD 2014.03.05
        bt_l2capChannelClear();         // ADD 2015.02.03
        bt_l2capLinkClear();            // ADD 2014.03.05
//      bt_l2capDeviceClear();          // ADD 2015.02.03 DEL 2017.01.18
//      bt_l2capServiceClear();         // ADD 2015.02.03 DEL 2017.01.18
#ifdef DEBUG3
    } else {
        static int    s = 0;

        if (s != state) {
            s = state;
            DEBUGP("L2CAP-RM: New state=%d\n", state);
        }
#endif
    }

    // state machine
    rc = 0;
    switch(state) {
    case UNPLUGED:                      // Phisical device removed
        if (bt_isAliveHCI()) {
            state = PLUGED;
        }
        break;

    case PLUGED:                        // Phisical device pluged in
//      try   = 0;                              // DEL 2014.03.05
        timeo = time(NULL) + BT_SEND_TIMEOUT;   // ADD 2014.03.05
        ci    = (unsigned char *)initCmds;
        state = INIT_COMMAND_SEND;
        break;

    case WAIT_UNPLUG:                           // ADD 2015.02.06
        if (!bt_isAliveHCI()) {                 // ADD 2015.02.06
            state = UNPLUGED;                   // ADD 2015.02.06
        }                                       // ADD 2015.02.06
        break;                                  // ADD 2015.02.06

    case INIT_COMMAND_SEND:
        if (*ci == 0xff) {
            DEBUGP("L2CAP-RM: init end aclOutSize=%d aclInSize=%d\n", aclOutSize, aclInSize);
            if (bt_l2capCommon.hciVersion >= HCI_Parm_HCI_Version_4_0) {
                timeo   = time(NULL) + BT_SEND_TIMEOUT;    // ADD 2014.03.05
                ci      = (unsigned char *)initLECmds;
                leState = LE_STANDBY;
                state   = LE_INIT_COMMAND_SEND;
            } else {
                leState = LE_DISABLE;
                state   = EVENT_WAIT;
            }
            break;
        }
        if (bt_isIdleHCIcommand()) {
            memcpy(&cmd, ci, HCI_Command_Packet_HeadSize + *(ci+2));
            bt_sendHCIcommand();
//          try   = 0;                                  // DEL 2014.03.05
            timeo = time(NULL) + BT_RECIEVE_TIMEOUT;    // ADD 2014.03.05
            state = INIT_COMMAND_STATUS;
//      } else if (try++ > BT_INIT_TIMEOUT) {           // DEL 2014.03.05
        } else if (time(NULL) > timeo) {                // ADD 2014.03.05
            DEBUGP("L2CAP-RM: INIT_COMMAND_SEND timeout\n");
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
//          state = UNPLUGED;                           // DEL 2015.02.06
            state = WAIT_UNPLUG;                        // ADD 2015.02.06
        }
        break;

    case INIT_COMMAND_STATUS:
        if (!bt_isAliveHCI()) {
            state = UNPLUGED;
        } else if (bt_recieveHCIevent()) {
            if ((evt.Event_Code == HCI_Event_Command_Status) &&
                (evt.Event_Parameter.Command_Status.Command_Opcode[0] == ci[0]) &&
                (evt.Event_Parameter.Command_Status.Command_Opcode[1] == ci[1])) {
                if (evt.Event_Parameter.Command_Status.Status != 0) {   // ADD 2015.02.06
                    rc    = BT_L2CAP_ERR_HCI_COMPATIBILITY;             // ADD 2015.02.06
                    state = WAIT_UNPLUG;                                // ADD 2015.02.06
                    break;                                              // ADD 2015.02.06
                }                                                       // ADD 2015.02.06
                ci   += (HCI_Command_Packet_HeadSize + *(ci+2));
                state = INIT_COMMAND_SEND;
            } else if ((evt.Event_Code == HCI_Event_Command_Complete) &&
                       (evt.Event_Parameter.Command_Complete.Command_Opcode[0] == ci[0]) &&
                       (evt.Event_Parameter.Command_Complete.Command_Opcode[1] == ci[1])) {
                ci   += (HCI_Command_Packet_HeadSize + *(ci+2));
                state = INIT_COMMAND_SEND;

                switch(HCI_UINT16(evt.Event_Parameter.Command_Complete.Command_Opcode)){
                case HCI_Read_Local_Version_Information:
                    if (evt.Event_Parameter.Command_Complete.Return_Parameter.Read_Local_Version_Information.Status == 0) {
                        bt_l2capCommon.hciVersion = evt.Event_Parameter.Command_Complete.Return_Parameter.Read_Local_Version_Information.HCI_Version;
                    } else {
                        DEBUGP("L2CAP-RM: Read_Local_Version_Information error=0x%x\n", evt.Event_Parameter.Command_Complete.Return_Parameter.Read_Local_Version_Information.Status);
                        rc    = BT_L2CAP_ERR_HCI_READ_LOCAL_VER;
                        state = WAIT_UNPLUG;        // ADD 2015.02.06
                    }
                    break;
                case HCI_Read_Buffer_Size:
                    if (evt.Event_Parameter.Command_Complete.Return_Parameter.Read_Buffer_Size.Status == 0) {
                        size_t    l;

                        l = HCI_UINT16(evt.Event_Parameter.Command_Complete.Return_Parameter.Read_Buffer_Size.HC_ACL_Data_Packet_Length);
                        if (l > sizeof(aclOut)) {
                            aclOutSize = sizeof(aclOut);
                        } else {
                            aclOutSize = l;
                        }
                    } else {
                        DEBUGP("L2CAP-RM: Read_Buffer_Size error=0x%x\n", evt.Event_Parameter.Command_Complete.Return_Parameter.Read_Buffer_Size.Status);
                        rc    = BT_L2CAP_ERR_HCI_READ_BUFF_SIZE;
                        state = WAIT_UNPLUG;        // ADD 2015.02.06
                    }
                    break;
                case HCI_Read_BD_ADDR:
                    if (evt.Event_Parameter.Command_Complete.Return_Parameter.Read_BD_ADDR.Status == 0) {
                        memcpy(bt_l2capCommon.myBdAddr, evt.Event_Parameter.Command_Complete.Return_Parameter.Read_BD_ADDR.BD_ADDR, sizeof(bt_l2capCommon.myBdAddr));
                    } else {
                        DEBUGP("L2CAP-RM: Read_BD_ADDR error=0x%x\n", evt.Event_Parameter.Command_Complete.Return_Parameter.Read_BD_ADDR.Status);
                        rc    = BT_L2CAP_ERR_HCI_READ_BDADDR;
                        state = WAIT_UNPLUG;        // ADD 2015.02.06
                   }
                    break;
                default:
                    if (evt.Event_Parameter.Command_Complete.Return_Parameter.general.Status != 0) {    // ADD 2015.02.06
                        rc    = BT_L2CAP_ERR_HCI_COMPATIBILITY;                                         // ADD 2015.02.06
                        state = WAIT_UNPLUG;                                                            // ADD 2015.02.06
                    }                                                                                   // ADD 2015.02.06
                    break;
                }
            }
//      } else if (try++ > BT_INIT_TIMEOUT) {       // DEL 2014.03.05
        } else if (time(NULL) > timeo) {            // ADD 2014.03.05
            DEBUGP("L2CAP-RM: INIT_COMMAND_STATUS timeout\n");
            rc    = BT_L2CAP_ERR_HCI_STAT_RECV_TIMEOUT;
//          state = UNPLUGED;                       // DEL 2015.02.06
            state = WAIT_UNPLUG;                    // ADD 2015.02.06
        }
        break;

    case LE_INIT_COMMAND_SEND:
        if (*ci == 0xff) {
            DEBUGP("L2CAP-RM: LE init end aclOutSize=%d aclInSize=%d\n", aclOutSize, aclInSize);
#ifdef BT_INIT_LE_DETECT_ENABLE
            leState = LE_ADVERTISING;
#endif
            state = EVENT_WAIT;
            break;
        }
        if (bt_isIdleHCIcommand()) {
            memcpy(&cmd, ci, HCI_Command_Packet_HeadSize + *(ci+2));
            bt_sendHCIcommand();
//          try   = 0;                                  // DEL 2014.03.05
            timeo = time(NULL) + BT_RECIEVE_TIMEOUT;    // ADD 2014.03.05
            state = LE_INIT_COMMAND_STATUS;
//      } else if (try++ > BT_INIT_TIMEOUT) {           // DEL 2014.03.05
        } else if (time(NULL) > timeo) {                // ADD 2014.03.05
            DEBUGP("L2CAP-RM: LE_INIT_COMMAND_SEND timeout\n");
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
//          state = UNPLUGED;                           // DEL 2015.02.06
            state = WAIT_UNPLUG;                        // ADD 2015.02.06
        }
        break;

    case LE_INIT_COMMAND_STATUS:
        if (!bt_isAliveHCI()) {
            state = UNPLUGED;
        } else if (bt_recieveHCIevent()) {
            if ((evt.Event_Code == HCI_Event_Command_Status) &&
                (evt.Event_Parameter.Command_Status.Command_Opcode[0] == ci[0]) &&
                (evt.Event_Parameter.Command_Status.Command_Opcode[1] == ci[1])) {
                if (evt.Event_Parameter.Command_Status.Status != 0) {   // ADD 2015.02.06
                    rc    = BT_L2CAP_ERR_HCI_COMPATIBILITY;             // ADD 2015.02.06
                    state = WAIT_UNPLUG;                                // ADD 2015.02.06
                    break;                                              // ADD 2015.02.06
                }                                                       // ADD 2015.02.06
                ci += (HCI_Command_Packet_HeadSize + *(ci+2));
                state = LE_INIT_COMMAND_SEND;
            } else if ((evt.Event_Code == HCI_Event_Command_Complete) &&
                       (evt.Event_Parameter.Command_Complete.Command_Opcode[0] == ci[0]) &&
                       (evt.Event_Parameter.Command_Complete.Command_Opcode[1] == ci[1])) {
                ci += (HCI_Command_Packet_HeadSize + *(ci+2));
                state = LE_INIT_COMMAND_SEND;
//          }                                       // DEL 2015.02.06  bug
                switch(HCI_UINT16(evt.Event_Parameter.Command_Complete.Command_Opcode)){
                case HCI_LE_Read_Buffer_Size:
                    if (evt.Event_Parameter.Command_Complete.Return_Parameter.LE_Read_Buffer_Size.Status == 0) {
                        size_t    l;

                        l = HCI_UINT16(evt.Event_Parameter.Command_Complete.Return_Parameter.LE_Read_Buffer_Size.HC_LE_Data_Packet_Length);
                        if ((l != 0) && (l < aclOutSize)) {
                            aclOutSize = l;
                        }
                    } else {
                        DEBUGP("L2CAP-RM: LE Read_Buffer_Size error=0x%x\n", evt.Event_Parameter.Command_Complete.Return_Parameter.LE_Read_Buffer_Size.Status);
                        rc    = BT_L2CAP_ERR_HCI_READ_BUFF_SIZE;
                        state = WAIT_UNPLUG;        // ADD 2015.02.06
                    }
                    break;
                                                    // ADD START 2017.01.18
                case HCI_LE_Rand:
                    if (evt.Event_Parameter.Command_Complete.Return_Parameter.LE_Rand.Status == 0) {
                        if ((bt_l2capCommon.rand1[0] == 0) && (bt_l2capCommon.rand1[1] == 0)) {
                            MEMCPY(bt_l2capCommon.rand1, evt.Event_Parameter.Command_Complete.Return_Parameter.LE_Rand.Random_Number);
                        } else {
                            MEMCPY(bt_l2capCommon.rand2, evt.Event_Parameter.Command_Complete.Return_Parameter.LE_Rand.Random_Number);
                        }
                    }
                    break;
                                                    // ADD END 2017.01.18
                default:
                    if (evt.Event_Parameter.Command_Complete.Return_Parameter.general.Status != 0) {    // ADD 2015.02.06
                        rc    = BT_L2CAP_ERR_HCI_COMPATIBILITY;                                         // ADD 2015.02.06
                        state = WAIT_UNPLUG;                                                            // ADD 2015.02.06
                    }                                                                                   // ADD 2015.02.06
                    break;
                }
            }                                       // ADD 2015.02.06 bug
//      } else if (try++ > BT_INIT_TIMEOUT) {       // DEL 2014.03.05
        } else if (time(NULL) > timeo) {            // ADD 2014.03.05
            DEBUGP("L2CAP-RM: LE_INIT_COMMAND_STATUS timeout\n");
            rc    = BT_L2CAP_ERR_HCI_STAT_RECV_TIMEOUT;
//          state = UNPLUGED;                       // DEL 2015.02.06
            state = WAIT_UNPLUG;                    // ADD 2015.02.06
        }
        break;

    case EVENT_WAIT:        // Physical device active

        if (!bt_isAliveHCI()) {
            bt_l2capLinkClear();
            nowLnk = NULL;
            rc     = BT_L2CAP_ERR_HCI_DEAD;
            state  = UNPLUGED;

        // Event message from HCI
        } else if (bt_recieveHCIevent()) {

//          try = 0;                                // DEL 2014.03.05
            timeo = time(NULL) + BT_SEND_TIMEOUT;   // ADD 2014.03.05
            switch(evt.Event_Code){

//          case HCI_Event_Inquiry_Result:
//              break;

//          case HCI_Event_Inquiry_Complete:
//              break;

            case HCI_Event_Connection_Request:
                DEBUGP("L2CAP-RM: Connection request linkType=%d", evt.Event_Parameter.Connection_Request.Link_Type);
                DUMP(" BD_ADDR=", evt.Event_Parameter.Connection_Request.BD_ADDR);
                DUMP(" Class_of_Device=", evt.Event_Parameter.Connection_Request.Class_of_Device);
                state = ACCEPT_CONNECT_SEND;
                break;

            case HCI_Event_Connection_Complete:
                DEBUGP("L2CAP-RM: Connection complete stat=%d handle=0x%04x", evt.Event_Parameter.Connection_Complete.Status, HCI_UINT16(evt.Event_Parameter.Connection_Complete.Connection_Handle));
                DUMP(" BD_ADDR=", evt.Event_Parameter.Connection_Complete.BD_ADDR);
                if (evt.Event_Parameter.Connection_Complete.Status == 0) {
                    struct bt_l2capDevice   *p;
                    struct bt_l2capLink     *q;
                    unsigned short          h;

                    q = NULL;
                    p = bt_l2capDeviceAdd(evt.Event_Parameter.Connection_Complete.BD_ADDR);
                    if (p != NULL) {
                        h = HCI_UINT16(evt.Event_Parameter.Connection_Complete.Connection_Handle);
                        q = bt_l2capLinkAdd(p->bdAddr, h);
                        if (q != NULL) {
                            q->linkType   = evt.Event_Parameter.Connection_Complete.Link_Type;
                            q->encryption = evt.Event_Parameter.Connection_Complete.Encryption_Mode;
                            q->role       = HCI_Parm_Role_Unknown;
                            q->buffSize   = sizeof(q->buff);
                            q->nowSize    = 0;
                            q->sendedSize = 0;
                        } else {
                            rc = BT_L2CAP_ERR_NOMEMORY;     // ADD 2016.2.12
                            DEBUGP("L2CAP-RM: ENOMEM\n");
                        }
                    } else {
                        rc = BT_L2CAP_ERR_NOMEMORY;         // ADD 2016.2.12
                        DEBUGP("L2CAP-RM: ENOMEM\n");
                    }
//                  nowLnk = q;                             // DEL 2018.02.10
                    timeo = time(NULL) + BT_SEND_TIMEOUT;   // ADD 2018.02.10
                    state = AUTH_REQ_SEND;                  // ADD 2018.02.10
                }
                break;

            case HCI_Event_Disconnection_Complete:
                if (evt.Event_Parameter.Disconnection_Complete.Status == 0) {
                    unsigned short      h;
                    struct bt_l2capLink *l;

                    h = HCI_UINT16(evt.Event_Parameter.Disconnection_Complete.Connection_Handle);
                    DEBUGP("L2CAP-RM: Disconnection complete handle=0x%04x\n", h);
//                  l = bt_l2capLinkFind(NULL, h);          // DEL 2017.01.03
                    l = bt_l2capLinkFindByDevice(NULL, h);  // ADD 2017.01.03
                    bt_l2capLinkDelete(l);

                    if (leState == LE_ADVERTISING) {
                        state = LE_ADV_START_SEND;
                    }
                }
                break;

            case HCI_Event_Command_Complete:
                DEBUGP("L2CAP-RM: Command Complete\n");
                break;

            case HCI_Event_Command_Status:
                DEBUGP("L2CAP-RM: Command Status stat=0x%02x pkt=%d cmd=0x%04x\n", evt.Event_Parameter.Command_Status.Status, evt.Event_Parameter.Command_Status.Num_HCI_Command_Packets, HCI_UINT16(evt.Event_Parameter.Command_Status.Command_Opcode));
                break;

            case HCI_Event_Hardware_Error:
                DEBUGP("L2CAP-RM: Hardware error\n");
                bt_l2capLinkClear();
                nowLnk = NULL;
                rc     = BT_L2CAP_ERR_HCI_HARDWARE;
                state  = UNPLUGED;
                break;

            case HCI_Event_Number_Of_Completed_Packets:
//              DEBUGP("L2CAP-RM: Number Of Completed Packets #handle=%d\n", evt.Event_Parameter.Number_Of_Completed_Packets.Number_of_Handles);
                break;

            case HCI_Event_PIN_Code_Request:
                DEBUGP("L2CAP-RM: PIN_Code_Request\n");
#ifndef UPD20160421                      // DEL START 2016.04.21    REENABLE 2017.01.08
#ifndef UPD20160219                      //                         REENABLE 2017.01.08
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.PIN_Code_Request.BD_ADDR);
                if (nowDev != NULL) {
                    DEBUGP("L2CAP-RM: PIN_Code_Request -> OK\n");
                    state = PIN_CODE_REP_SEND;
                } else {
                    DEBUGP("L2CAP-RM: PIN_Code_Request -> skip\n");
                }
#else
                state = PIN_CODE_REP_SEND;  // Never
#endif
#else                                   // DEL,ADD 2016.04.21
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.PIN_Code_Request.BD_ADDR);
                if (nowDev != NULL) {
                    int r;

                    if (nowDev->pinCodeLen > 0) {
                        state = PIN_CODE_REP_SEND;
                        DEBUGP("L2CAP-RM: PIN_Code_Request -> OK1\n");
                    } else if ((r = bt_l2capResourceManagerPinCodeRequest(nowDev, nowDev->pinCode)) > 0) {     // Call back API
                        DEBUGP("L2CAP-RM: PIN_Code_Request -> OK2\n");
                        nowDev->pinCodeLen = r;
                        state = PIN_CODE_REP_SEND;
                    } else {
                        DEBUGP("L2CAP-RM: PIN_Code_Request -> NG\n");
                        state = PIN_CODE_NEG_SEND;
                    }
                } else {
                    DEBUGP("L2CAP-RM: PIN_Code_Request -> skip\n");
                }
#endif                                  // ADD END 2016.04.21
                break;

            case HCI_Event_Link_Key_Request:
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.Link_Key_Request.BD_ADDR);
                if ((nowDev != NULL) && (nowDev->linkKeyValid)) {
                    DEBUGP("L2CAP-RM: Link_Key_Request -> OK\n");
                    state = LINK_KEY_REP_SEND;
                } else {
                    DEBUGP("L2CAP-RM: Link_Key_Request -> NG\n");
                    state = LINK_KEY_NEG_SEND;
                }
                break;

            case HCI_Event_Link_Key_Notification:
                {
                    struct bt_l2capDevice    *p;

                    DEBUGP("L2CAP-RM: Link_Key_Notification keyType=%d\n", evt.Event_Parameter.Link_Key_Notification.Key_Type);
                    p = bt_l2capDeviceAdd(evt.Event_Parameter.Link_Key_Notification.BD_ADDR);
                    if (p != NULL) {
//                      memcpy(p->bdAddr,  evt.Event_Parameter.Link_Key_Notification.BD_ADDR,  sizeof(p->bdAddr));
                        memcpy(p->linkKey, evt.Event_Parameter.Link_Key_Notification.Link_Key, sizeof(p->linkKey));
                        p->keyType       = evt.Event_Parameter.Link_Key_Notification.Key_Type;
                        p->linkKeyValid  = 1;
                    } else {
                        rc = BT_L2CAP_ERR_NOMEMORY;     // ADD 2016.2.12
                        DEBUGP("L2CAP-RM: ENOMEM\n");
                    }
                }
                break;

                                        // ADD START 2015.02.06
            case HCI_Event_Authentication_Complete:
                if (evt.Event_Parameter.Authentication_Complete.Status == 0) {
                    unsigned short      h;
                    struct bt_l2capLink *l;

                    h = HCI_UINT16(evt.Event_Parameter.Authentication_Complete.Connection_Handle);
                    DEBUGP("L2CAP-RM: Authentication_Complete handle=0x%04x\n", h);
//                  l = bt_l2capLinkFind(NULL, h);                                                      // DEL 2017.01.08
//                  l->authValid = 1;                                                                   // DEL 2017.01.08
                    if ((l = bt_l2capLinkFindByDevice(NULL, h)) != NULL) {                              // ADD 2017.01.08
//                      if (l->device->keyType == HCI_Parm_Key_Type_Authenticated_Combination_Key) {    // ADD 2017.01.08 DEL 2018.02.10
                            l->authentication = 1;                                                      // ADD 2017.01.08
//                      }                                                                               // ADD 2017.01.08 DEL 2018.02.10
                    }                                                                                   // ADD 2017.01.08
                }
                break;

            case HCI_Event_Encryption_Key_Refresh_Complete:
                if (evt.Event_Parameter.Encryption_Key_Refresh_Complete.Status == 0) {
                    struct bt_l2capLink *cb;
                    unsigned short      h;

                    h = HCI_UINT16(evt.Event_Parameter.Encryption_Key_Refresh_Complete.Connection_Handle);
                    DEBUGP("L2CAP-RM: Enc key refresh complete-%04x\n", h);
//                  if ((cb = bt_l2capLinkFind(NULL, h)) != NULL) {         // DEL 2017.01.03
                    if ((cb = bt_l2capLinkFindByDevice(NULL, h)) != NULL) { // ADD 2017.01.03
                        cb->encryption = 1;
                        if (cb->device->keyType == HCI_Parm_Key_Type_Authenticated_Combination_Key) {   // ADD 2017.01.08
                            cb->authentication = 1;                                                     // ADD 2017.01.08
                        }                                                                               // ADD 2017.01.08
                    }
                }
                break;
                                        // ADD END 2014.02.23
            case HCI_Event_IO_Capability_Response:
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.IO_Capability_Response.BD_ADDR);
                if (nowDev != NULL) {
                    DEBUGP("L2CAP-RM: IO_Capability_Response -> OK (io=%02x,OOB=%02x,auth=%02x)\n",
                            evt.Event_Parameter.IO_Capability_Response.IO_Capability,
                            evt.Event_Parameter.IO_Capability_Response.OOB_Data_Present,
                            evt.Event_Parameter.IO_Capability_Response.Authentication_Requirements);
                    nowDev->ioCapability   = evt.Event_Parameter.IO_Capability_Response.IO_Capability;
                    nowDev->oobDataPresent = evt.Event_Parameter.IO_Capability_Response.OOB_Data_Present;
                    nowDev->authentication = evt.Event_Parameter.IO_Capability_Response.Authentication_Requirements;
                } else {
                    DEBUGP("L2CAP-RM: IO_Capability_Response -> skip\n");
                }
                break;

            case HCI_Event_IO_Capability_Request:
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.IO_Capability_Request.BD_ADDR);
                if (nowDev != NULL) {
                    DEBUGP("L2CAP-RM: IO_Capability_Request -> OK\n");
                    state = IO_CAP_REP_SEND;
                } else {
                    DEBUGP("L2CAP-RM: IO_Capability_Request -> skip\n");
                }
                break;

            case HCI_Event_User_Confirmation_Request:
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.User_Confirmation_Request.BD_ADDR);
                if (nowDev != NULL) {
                    nowDev->numericValue = HCI_UINT32(evt.Event_Parameter.User_Confirmation_Request.Numeric_Value);
                    DEBUGP("L2CAP-RM: User_Confirmation_Request -> OK %06d\n", (int)nowDev->numericValue);
//                  state = USER_CNF_REP_SEND;                              // DEL 2016.04.21
                    nowDev->numericInput = time(NULL) + BT_CONFIRM_TIMEOUT; // ADD 2016.04.21  Request
                } else {
                    DEBUGP("L2CAP-RM: User_Confirmation_Request -> skip\n");
                }
                break;

            case HCI_Event_User_Passkey_Request:
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.User_Passkey_Request.BD_ADDR);
                if (nowDev != NULL) {
                    DEBUGP("L2CAP-RM: User_Passkey_Request -> OK\n");
//                  state = USER_PASS_REP_SEND;                             // DEL 2016.04.21
                    nowDev->passkeyInput = time(NULL) + BT_PASSKEY_TIMEOUT; // ADD 2016.04.21  Request
                } else {
                    DEBUGP("L2CAP-RM: User_Passkey_Request -> skip\n");
                }
                break;
                                                // ADD START 2016.04.21
            case HCI_Event_User_Passkey_Notification:
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.User_Passkey_Notification.BD_ADDR);
                if (nowDev != NULL) {
                    DEBUGP("L2CAP-RM: User_Passkey_Notification -> ok %06d\n", (int)HCI_UINT32(evt.Event_Parameter.User_Passkey_Notification.Passkey));
                    bt_l2capResourceManagerPasskeyEntryDisplay(nowDev, HCI_UINT32(evt.Event_Parameter.User_Passkey_Notification.Passkey));
                } else {
                    DEBUGP("L2CAP-RM: User_Passkey_Notification -> skip\n");
                }
                break;
                                                // ADD END   2016.04.21
            case HCI_Event_Simple_Pairing_Complete:
                nowDev = bt_l2capDeviceFind(evt.Event_Parameter.Simple_Pairing_Complete.BD_ADDR);
                if (nowDev != NULL) {
                    if (evt.Event_Parameter.Simple_Pairing_Complete.Status == HCI_Error_None) {
                        DEBUGP("L2CAP-RM: Simple_Pairing_Complete(OK)\n");
//                      nowDev->sspValid = 1;	// DEL 2017.01.18
                    } else {
                        DEBUGP("L2CAP-RM: Simple_Pairing_Complete(NG=%d)\n", evt.Event_Parameter.Simple_Pairing_Complete.Status);
//                      nowDev->sspValid = 0;	// DEL 2017.01.18
                    }
                } else {
                    DEBUGP("L2CAP-RM: Simple_Pairing_Complete -> skip\n");
                }
                break;
                                        // ADD END 2015.02.06
            case HCI_Event_Max_Slots_Change:
                DEBUGP("L2CAP-RM: Max Slots Change-%04x %d\n",
                        HCI_UINT16(evt.Event_Parameter.Max_Slots_Change.Connection_Handle),
						evt.Event_Parameter.Max_Slots_Change.LMP_Max_Slots);
                break;

            case HCI_Event_Page_Scan_Repetition_Mode_Change:
                DEBUGP("L2CAP-RM: Page Scan Repetition Mode Change %d",
                		evt.Event_Parameter.Page_Scan_Repetition_Mode_Change.Page_Scan_Repetition_Mode);
                DUMP(  " BDADDR=", evt.Event_Parameter.Page_Scan_Repetition_Mode_Change.BD_ADDR);
                break;
                                        // ADD START 2014.02.23
            case HCI_Event_Link_Supervision_Timeout_Changed:
                DEBUGP("L2CAP-RM: Link Supervision Timeout Changed-%04x %d\n",
                        HCI_UINT16(evt.Event_Parameter.Link_Supervision_Timeout_Changed.Connection_Handle),
                        HCI_UINT16(evt.Event_Parameter.Link_Supervision_Timeout_Changed.Link_Supervision_Timeout));
            	break;

            case HCI_Event_Encryption_Change:
                DEBUGP("L2CAP-RM: Encryption_Change-%04x enc=%d stat=%d\n",
                        HCI_UINT16(evt.Event_Parameter.Encryption_Change.Connection_Handle),
                        evt.Event_Parameter.Encryption_Change.Encryption_Enable,
                        evt.Event_Parameter.Encryption_Change.Status);
                if (evt.Event_Parameter.Encryption_Change.Status == 0) {
                    struct bt_l2capLink *cb;

//                  if ((cb = bt_l2capLinkFind(NULL, HCI_UINT16(evt.Event_Parameter.Encryption_Change.Connection_Handle))) != NULL) {           // DEL 2017.01.03
                    if ((cb = bt_l2capLinkFindByDevice(NULL, HCI_UINT16(evt.Event_Parameter.Encryption_Change.Connection_Handle))) != NULL) {   // ADD 2017.01.03
                        cb->encryption = evt.Event_Parameter.Encryption_Change.Encryption_Enable;
                        if ((cb->encryption) &&                                                         // ADD 2017.01.08
                            (cb->device->keyType == HCI_Parm_Key_Type_Authenticated_Combination_Key)) { // ADD 2017.01.08
                            cb->authentication = 1;                                                     // ADD 2017.01.08
                        }                                                                               // ADD 2017.01.08
                    }
                }
                break;
                                        // ADD END 2014.02.23
            case HCI_Event_LE_Meta_Event:
                switch(evt.Event_Parameter.LE_Connection_Complete.Subevent_Code){
                case HCI_Event_LE_Connection_Complete:
                    if (evt.Event_Parameter.LE_Connection_Complete.Status == 0) {
                        struct bt_l2capDevice  *p;
                        struct bt_l2capLink    *q;
                        unsigned short          h;

                        DEBUGP("L2CAP-RM: LE-Connection role=%d\n", evt.Event_Parameter.LE_Connection_Complete.Role);
                        DEBUGP(" AddrType=%d", evt.Event_Parameter.LE_Connection_Complete.Peer_Address_Type);
                        DUMP(  " BDADDR=", evt.Event_Parameter.LE_Connection_Complete.Peer_Address);

                        p = bt_l2capDeviceAdd(evt.Event_Parameter.LE_Connection_Complete.Peer_Address);
                        if (p != NULL) {
//                          p->peerAddressType = evt.Event_Parameter.LE_Connection_Complete.Peer_Address_Type;  // DEL 2017.01.18
                            p->addrType = evt.Event_Parameter.LE_Connection_Complete.Peer_Address_Type;         // ADD 2017.01.18
                            h = HCI_UINT16(evt.Event_Parameter.LE_Connection_Complete.Connection_Handle);
                            q = bt_l2capLinkAdd(p->bdAddr, h);
                            if (q != NULL) {
                                q->role       = evt.Event_Parameter.LE_Connection_Complete.Role;
                                q->buffSize   = sizeof(q->buff);
                                q->nowSize    = 0;
                                q->sendedSize = 0;
                                                            // ADD START 2017.01.18
                                if ((p->ediv[0] != 0) || (p->ediv[1] != 0)) {   // Bonded keys
                                    MEMCPY(q->ediv, p->ediv);                   // Restore
                                    MEMCPY(q->rand, p->rand);
                                    bt_securityManagerKeyGeneration(q->ltk, q->irk, q->csrk, q->ediv, q->rand, NULL);
                                    q->authentication = p->auth;
//                                  MEMCPY(q->initEdiv, p->initEdiv);
//                                  MEMCPY(q->initRand, p->initRand);
//                                  MEMCPY(q->initLtk,  p->initLtk);
                                    MEMCPY(q->initIrk,  p->initIrk);
//                                  MEMCPY(q->initCsrk, p->initCsrk);
                                }
                                                            // ADD END 2017.01.18
                            } else {
                                rc = BT_L2CAP_ERR_NOMEMORY; // ADD 2016.2.12
                                DEBUGP("L2CAP-RM: ENOMEM\n");
                            }
                        } else {
                            rc = BT_L2CAP_ERR_NOMEMORY;     // ADD 2016.2.12
                            DEBUGP("L2CAP-RM: ENOMEM\n");
                        }
                    }
                    break;
//              case HCI_Event_LE_Advertising_Report:
//                  break;
//              case HCI_Event_LE_Connection_Update_Complete:
//                  break;
//              case HCI_Event_LE_Read_Remote_Used_Features_Complete:
//                  break;
                                        // ADD START 2014.02.23
                case HCI_Event_LE_Long_Term_Key_Request:
                {
                    struct bt_l2capLink *cb;
                    unsigned short      h;

                    DEBUGP("L2CAP-RM: LE_Long_Term_Key_Request %02x%02x\n", evt.Event_Parameter.LE_Long_Term_Key_Request.Connection_Handle[1], evt.Event_Parameter.LE_Long_Term_Key_Request.Connection_Handle[0]);
                    DEBUGP(" EDIV=%02x%02x", evt.Event_Parameter.LE_Long_Term_Key_Request.Encryption_Diversifier[1], evt.Event_Parameter.LE_Long_Term_Key_Request.Encryption_Diversifier[0]);
                    DUMP(  " Rand=", evt.Event_Parameter.LE_Long_Term_Key_Request.Random_Number);

                    h = HCI_UINT16(evt.Event_Parameter.LE_Long_Term_Key_Request.Connection_Handle);
//                  if ((cb = bt_l2capLinkFind(NULL, h)) != NULL) {         // DEL 2017.01.03
                    if ((cb = bt_l2capLinkFindByDevice(NULL, h)) != NULL) { // ADD 2017.01.03
#ifdef DELETE                                                               // DEL START 2017.01.18
                        MEMCPY(cb->encryptionDiversifier, evt.Event_Parameter.LE_Long_Term_Key_Request.Encryption_Diversifier);
                        MEMCPY(cb->randomNumber,          evt.Event_Parameter.LE_Long_Term_Key_Request.Random_Number);
                        nowLnk = cb;
                        state  = LE_LE_LTK_REP_SEND;
#else                                                                       // DEL END - ADD START 2017.01.18
                        nowLnk = cb;
                        if (cb->device->addrType == HCI_Parm_Address_Type_Public_Device_Address) {
                            if (MEMCMP(cb->ediv, evt.Event_Parameter.LE_Long_Term_Key_Request.Encryption_Diversifier) == 0 &&
                                MEMCMP(cb->rand, evt.Event_Parameter.LE_Long_Term_Key_Request.Random_Number         ) == 0 ) {
                                state  = LE_LE_LTK_REP_SEND;
                            } else {
    		                    DEBUGP("L2CAP-RM: Public device addr: Discord EDIV+Rand\n");
                                state  = LE_LE_LTK_NEG_SEND;
                            }

                        } else {     // addrType == HCI_Parm_Address_Type_Random
                            struct bt_l2capDevice *p;
                            struct bt_l2capDevice *real;
                            struct bt_l2capDevice *temp;

                            // Scan of all devices
                            p = NULL;
                            temp = cb->device;
                            while((real = bt_l2capDeviceGetNext(&p)) != NULL) {
                                if ((MEMCMP(real->ediv, evt.Event_Parameter.LE_Long_Term_Key_Request.Encryption_Diversifier) == 0) &&
                                    (MEMCMP(real->rand, evt.Event_Parameter.LE_Long_Term_Key_Request.Random_Number         ) == 0)) {
                                    break;
                                }
                            }
                            if (real) {
                                unsigned char	id;

                                DEBUGP(" Found dev %d", real->addrType);
                                DUMP(" ", real->bdAddr);
                                state  = LE_LE_LTK_REP_SEND;
                                id = temp->bdAddr[5] & 0xc0;
                                if (id == 0xc0) {           // GAP 10.8.1 Static Address
                                    if (real != temp) {
                                        DEBUGP(" Static Address: Changed\n");
                                        state  = LE_LE_LTK_NEG_SEND;
                                    }
                                } else if (id == 0x00) {    // GAP 10.8.2.1 Non-Resolvable Private Address
                                        ;
                                } else if (id == 0x40) {    // GAP 10.8.2.3 Resolvable Private Address
                                    if ((real->ediv[0] != 0) && (real->ediv[1] != 0)) { // !STK
                                        unsigned char out[16];
                                        unsigned char prand[16];

                                        MEMSET(prand, 0);
                                        prand[0] = temp->bdAddr[3];
                                        prand[1] = temp->bdAddr[4];
                                        prand[2] = temp->bdAddr[5];
                                        bt_securityManagerCrypt_ah(out, real->initIrk, prand);
                                        if (memcmp(temp->bdAddr, out, 3)) {
                                            DEBUGP(" Private Address: NG\n");
                                            DUMP("Bad Addr:", temp->bdAddr);
                                            DUMP("IRK=", real->initIrk);
                                            DUMP("pra=", prand);
                                            DUMP("Has=", out);
                                            state  = LE_LE_LTK_NEG_SEND;
                                        } else {
                                            DEBUGP(" Private Address: OK\n");
                                        }
                                    }
                                }
                                if (real != temp) {
                                    DEBUGP(" Real:%d", real->addrType); DUMP(" ", real->bdAddr);
                                    DEBUGP(" Temp:%d", temp->addrType); DUMP(" ", temp->bdAddr);
                                    cb->device = real;
                                    bt_l2capDeviceDelete(temp);
                                    if (state == LE_LE_LTK_REP_SEND) {
                                        MEMCPY(cb->ediv, real->ediv);    // Restore the keys from bonded value
                                        MEMCPY(cb->rand, real->rand);
                                        bt_securityManagerKeyGeneration(cb->ltk, cb->irk, cb->csrk, cb->ediv, cb->rand, NULL);
                                        cb->authentication = real->auth;
//                                      MEMCPY(cb->initEdiv, real->initEdiv);
//                                      MEMCPY(cb->initRand, real->initRand);
//                                      MEMCPY(cb->initLtk,  real->initLtk);
                                                                    MEMCPY(cb->initIrk,  real->initIrk);
//                                      MEMCPY(cb->initCsrk, real->initCsrk);
                                    }
                                }
                            } else {
                                DEBUGP("L2CAP-RM: Random device addr: discord EDIV+Rand\n");
                                state  = LE_LE_LTK_NEG_SEND;
                            }
                        }
#endif                                                                      // ADD END 2017.01.18
                    }
                    break;
                }
                                        // ADD END 2014.02.23
                default:
                    DEBUGP("L2CAP-RM: Undef LE-event: %02x\n", evt.Event_Parameter.LE_Connection_Complete.Subevent_Code);
                    rc = BT_L2CAP_ERR_HCI_UNDEF_EVENT;
                    break;
                }
                break;

            default:
                DEBUGP("L2CAP-RM: Undef event: %02x\n", evt.Event_Code);
                rc = BT_L2CAP_ERR_HCI_UNDEF_EVENT;
                break;
            }

        // ACL message
        } else if (bt_recieveACLin()) {
            unsigned short    h;
            unsigned short    boundary;
            size_t            len;
            unsigned short    handle;
            struct bt_l2capLink    *q;

            h = HCI_UINT16(aclIn.Connection_Handle);
            handle   = h & HCI_CONNECTION_HANDLE_MASK;
            boundary = h & HCI_PACKET_BOUNDARY_FLAG_MASK;
            len      = HCI_UINT16(aclIn.Data_Total_Length);

#ifdef DEL
        	DEBUGP("ACLin: %04x b=%d len=%d\n", handle, boundary, len);
#endif

            // Searching the buffer
//          q = bt_l2capLinkFind(NULL, handle);             // DEL 2017.01.03
            q = bt_l2capLinkFindByDevice(NULL, handle);     // ADD 2017.01.03
            if (q != NULL) {
                switch(boundary){
                case HCI_PACKET_BOUNDARY_FLAG_FIRST:
                case HCI_PACKET_BOUNDARY_FLAG_FIRST_NOFL:
                    if (len <= q->buffSize) {
                        struct bt_l2cap_Data_Packet	*d;							// ADD 2017.03.10
                        size_t            			t;							// ADD 2017.03.10

                        memcpy(q->buff, aclIn.Data, len);
                        q->nowSize = len;
                        														// ADD START 2017.03.10
                        d = (struct bt_l2cap_Data_Packet *)aclIn.Data;
                        t = HCI_UINT16(d->Length) + L2CAP_Data_Packet_HeadSize;
                        q->totalSize = t;
                    	nowLnk = q;
                        if (q->nowSize >= q->totalSize) {
                        	state = PROCESS;
                        } else {
                            timeo = time(NULL) + BT_RECIEVE_TIMEOUT;
                        	state = DATA_RECIEVE;
                        }
//                    	DEBUGP("ACLin:0x%04x len=%d %d %d %02x%02x%02x%02x%02x%02x\n", boundary, len, t, q->nowSize,
//                    			q->buff[4], q->buff[5], q->buff[6], q->buff[7], q->buff[8], q->buff[9]);
                    	                                                        // ADD END 2017.03.10
                    }
                    break;
                case HCI_PACKET_BOUNDARY_FLAG_CONTINUE:
                case HCI_PACKET_BOUNDARY_FLAG_COMPLETE:
#ifdef DELETE                                   // DEL START 2017.03.10
                    if ((len + q->nowSize) <= q->buffSize) {
                        memcpy(&(q->buff[q->nowSize]), aclIn.Data, len);
                        q->nowSize += len;
                    }
#endif                                          // DEL END 2017.03.10
                    break;
                default:
                    break;
                }
#ifdef DELETE                                   // DEL START 2017.03.10
                if (len < sizeof(aclIn.Data)) {
                    state  = PROCESS;
                    nowLnk = q;
                }
#endif                                          // DEL END 2017.03.10
                								// ADD START 2017.03.10
                if (state == PROCESS){
                    unsigned char   outBuff[BT_L2CAP_MTU_SIZE];

#ifdef DEBUG2
                    if (q->nowSize < DEBUG2) {
                    	bt_l2capResourceManagerDumpStr("ACLin:", q->buff, q->nowSize);
                    }
#endif
                    state = EVENT_WAIT;
                    send_len = bt_l2capChannelManager(q, q->buff, q->nowSize, outBuff, sizeof(outBuff));
                    if (send_len) {
                        memcpy(q->buff, outBuff, send_len);
                        state = DATA_SEND;
                        timeo = time(NULL) + BT_SEND_TIMEOUT;
                        q->sendedSize = 0;
#ifdef DEBUG2
                        if (q->nowSize < DEBUG2) {
                        	bt_l2capResourceManagerDumpStr("ACLout:", q->buff, send_len);
                        }
#endif
                    }
                }
                								// ADD END 2017.03.10
            }

        } else if (bt_l2capCommon.resourceManagerRequest) {
            ;
                                                    // ADD START 2017.02.12
            switch(bt_l2capCommon.resourceManagerRequest) {
            case BT_L2CAP_REQUEST_ADVERTISE_START:
                state = LE_ADV_START_SEND;
                break;
            case BT_L2CAP_REQUEST_ADVERTISE_STOP:
                state = LE_ADV_STOP_SEND;
                break;
            case BT_L2CAP_REQUEST_DISCONNECT:
                nowLnk = (struct bt_l2capLink *)bt_l2capCommon.resourceManagerRequestParameter;
                state  = DISCONNECT_SEND;
                break;
            default:
                break;
            }
            bt_l2capCommon.resourceManagerRequest = 0;
                                                    // ADD STOP 2017.02.12
        } else {    // Idle
            static struct bt_l2capLink  *l = NULL;

            // Channels task refresh
            if ((nowLnk = bt_l2capLinkGetNext(&l)) != NULL) {   // Round-robin scheduling
//              send_len = bt_l2capChannelManager(nowLnk->handle, NULL, 0, nowLnk->buff, nowLnk->buffSize); // DEL 2017.01.03
                send_len = bt_l2capChannelManager(nowLnk, NULL, 0, nowLnk->buff, nowLnk->buffSize);         // ADD 2017.01.03
                if (send_len > 0) {
                    state = DATA_SEND;
//                  try   = 0;                                  // DEL 2014.03.05
                    timeo = time(NULL) + BT_SEND_TIMEOUT;       // ADD 2014.03.05
                    nowLnk->sendedSize = 0;
#ifdef DEBUG2
					bt_l2capResourceManagerDumpStr("ACLout:", nowLnk->buff, send_len);
#endif
                }
            }            
                                                    // ADD START 2016.04.21
            // Device task
            if ((nowLnk != NULL) && (state != DATA_SEND)) {
                // Numeric comparison confirm
                if (nowLnk->device->numericInput != 0) {
                    int v;

                    v = bt_l2capResourceManagerNumericComparison(nowDev, nowDev->numericValue);  // Call back API
                    if ((nowLnk->device->numericInput < time(NULL)) || (v >= -1)) {
                        nowLnk->device->numericInput = 0;
                        if (v >= 0) {
                            state = USER_CNF_REP_SEND;
                        } else {
                            state = USER_CNF_NEG_SEND;
                        }
                    }
                // Passkey entry input
                } else if (nowLnk->device->passkeyInput != 0) {
                    long v;

                    v = bt_l2capResourceManagerPasskeyEntryInput(nowDev);  // Call back API
                    if ((nowLnk->device->passkeyInput < time(NULL)) || (v >= -1)) {
                        nowLnk->device->passkeyInput = 0;
                        if (v >= 0) {
                            state = USER_PASS_REP_SEND;
                        } else {
                            state = USER_PASS_NEG_SEND;
                        }
                    }
                }
            }
                                                    // ADD END 2016.04.21
        }
        break;
                                                    // ADD START 2017.02.12
    case DISCONNECT_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: DISCONNECT_SEND handle=0x%04x\n", nowLnk->handle);
            HCI_STORE16(cmd.Op_Code, HCI_Disconnect);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.Disconnect);
            HCI_STORE16(cmd.Parameter.Disconnect.Connection_Handle, nowLnk->handle);
            cmd.Parameter.Disconnect.Reason = nowLnk->reason;
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: DISCONNECT_SEND timeout handle=0x%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD END 2017.02.12
    case ACCEPT_CONNECT_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: ACCEPT_CONNECT_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_Accept_Connection_Request);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.Accept_Connection_Request);
            memcpy(cmd.Parameter.Accept_Connection_Request.BD_ADDR, evt.Event_Parameter.Connection_Request.BD_ADDR, sizeof(evt.Event_Parameter.Connection_Request.BD_ADDR));
            cmd.Parameter.Accept_Connection_Request.Role = HCI_Parm_Role_Remain_the_Slave;
            bt_sendHCIcommand();
            state = EVENT_WAIT;
//      } else if (try++ > BT_SEND_TIMEOUT) {       // CHG 2014.03.05
        } else if (time(NULL) > timeo) {            // CHG 2014.03.05
            DEBUGP("L2CAP-RM: ACCEPT_CONNECT_SEND timeout handle=0x%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD START 2018.02.10
    case AUTH_REQ_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: AUTH_REQ_SEND handle=0x%04x\n", HCI_UINT16(evt.Event_Parameter.Connection_Complete.Connection_Handle));
            HCI_STORE16(cmd.Op_Code, HCI_Authentication_Requested);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.Authentication_Requested);
            MEMCPY(cmd.Parameter.Authentication_Requested.Connection_Handle, evt.Event_Parameter.Connection_Complete.Connection_Handle);
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: AUTH_REQ_SEND timeout handle=0x%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                     // ADD END 2018.02.10

    case LINK_KEY_NEG_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: LINK_KEY_NEG_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_Link_Key_Request_Negative_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.Link_Key_Request_Negative_Reply);
            memcpy(cmd.Parameter.Link_Key_Request_Negative_Reply.BD_ADDR, evt.Event_Parameter.Link_Key_Request.BD_ADDR, sizeof(evt.Event_Parameter.Link_Key_Request.BD_ADDR));
            bt_sendHCIcommand();
            state = EVENT_WAIT;
//      } else if (try++ > BT_SEND_TIMEOUT) {       // CHG 2014.03.05
        } else if (time(NULL) > timeo) {            // CHG 2014.03.05
            DEBUGP("L2CAP-RM: LINK_KEY_NEG_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;

    case LINK_KEY_REP_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: LINK_KEY_REP_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_Link_Key_Request_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.Link_Key_Request_Reply);
            memcpy(cmd.Parameter.Link_Key_Request_Reply.BD_ADDR,  nowDev->bdAddr, sizeof(cmd.Parameter.Link_Key_Request_Reply.BD_ADDR));
            memcpy(cmd.Parameter.Link_Key_Request_Reply.Link_Key, nowDev->linkKey, sizeof(cmd.Parameter.Link_Key_Request_Reply.Link_Key));
            bt_sendHCIcommand();
            state = EVENT_WAIT;
//      } else if (try++ > BT_SEND_TIMEOUT) {       // CHG 2014.03.05
        } else if (time(NULL) > timeo) {            // CHG 2014.03.05
            DEBUGP("L2CAP-RM: LINK_KEY_REP_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;

    case PIN_CODE_REP_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: PIN_CODE_REP_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_PIN_Code_Request_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.PIN_Code_Request_Reply);
#ifdef UPDT20160421                                 // DEL START 2016.04.21
            memcpy(cmd.Parameter.PIN_Code_Request_Reply.BD_ADDR, evt.Event_Parameter.PIN_Code_Request.BD_ADDR, sizeof(cmd.Parameter.PIN_Code_Request_Reply.BD_ADDR));
            memset(cmd.Parameter.PIN_Code_Request_Reply.PIN_Code, 0, sizeof(cmd.Parameter.PIN_Code_Request_Reply.PIN_Code));
            memcpy(cmd.Parameter.PIN_Code_Request_Reply.PIN_Code, BT_PIN_CODE, sizeof(BT_PIN_CODE) - 1);
            cmd.Parameter.PIN_Code_Request_Reply.PIN_Code_Length = sizeof(BT_PIN_CODE) - 1;
#else                                               // DEL ADD  2016.04.21
            memcpy(cmd.Parameter.PIN_Code_Request_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.PIN_Code_Request_Reply.BD_ADDR));
//          memcpy(cmd.Parameter.PIN_Code_Request_Reply.PIN_Code, nowDev->pinCode, sizeof(cmd.Parameter.PIN_Code_Request_Reply.PIN_Code));                          // DEL 2017.01.08
//          cmd.Parameter.PIN_Code_Request_Reply.PIN_Code_Length = nowDev->pinCodeLen;                                                                              // DEL 2017.01.08
            cmd.Parameter.PIN_Code_Request_Reply.PIN_Code_Length = bt_l2capResourceManagerPinCodeRequest(nowDev, cmd.Parameter.PIN_Code_Request_Reply.PIN_Code);    // ADD 2017.01.08
#endif                                              // ADD END 2016.04.21
            bt_sendHCIcommand();
            state = EVENT_WAIT;
//      } else if (try++ > BT_SEND_TIMEOUT) {       // CHG 2014.03.05
        } else if (time(NULL) > timeo) {            // CHG 2014.03.05
            DEBUGP("L2CAP-RM: PIN_CODE_REP_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;

                                                    // ADD START 2016.04.21
    case PIN_CODE_NEG_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: PIN_CODE_NEG_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_PIN_Code_Request_Negative_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.PIN_Code_Request_Negative_Reply);
            memcpy(cmd.Parameter.PIN_Code_Request_Negative_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.PIN_Code_Request_Negative_Reply.BD_ADDR));
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: PIN_CODE_NEG_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD END 2016.04.21
                                                    // ADD START 2015.02.06
    case IO_CAP_REP_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: IO_CAP_REP_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_IO_Capability_Request_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.IO_Capability_Request_Reply);
            memcpy(cmd.Parameter.IO_Capability_Request_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.IO_Capability_Request_Reply.BD_ADDR));
//          cmd.Parameter.IO_Capability_Request_Reply.Authentication_Requirements = HCI_Parm_Authentication_Requirements_General_Bonding_Numeric_Comparison;    // DEL 2016.04.21
//          cmd.Parameter.IO_Capability_Request_Reply.IO_Capability               = HCI_Parm_IO_Capability_NoInputNoOutput;     // DEL 2016.04.21
//          cmd.Parameter.IO_Capability_Request_Reply.OOB_Data_Present            = HCI_Parm_OOB_Data_Present_Not;              // DEL 2016.04.21
            cmd.Parameter.IO_Capability_Request_Reply.Authentication_Requirements = bt_l2capCommon.myAuthentication;            // ADD 2016.04.21
            cmd.Parameter.IO_Capability_Request_Reply.IO_Capability               = bt_l2capCommon.myIoCapability;              // ADD 2016.04.21
            cmd.Parameter.IO_Capability_Request_Reply.OOB_Data_Present            = bt_l2capCommon.myOobDataPresent;            // ADD 2016.04.21
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: IO_CAP_REP_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD START 2016.04.21
    case IO_CAP_NEG_SEND:
        if (bt_isIdleHCIcommand()) {
            HCI_STORE16(cmd.Op_Code, HCI_IO_Capability_Request_Negative_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.IO_Capability_Request_Negative_Reply);
            memcpy(cmd.Parameter.IO_Capability_Request_Negative_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.IO_Capability_Request_Negative_Reply.BD_ADDR));
            cmd.Parameter.IO_Capability_Request_Negative_Reply.Reason = HCI_Error_Authentication_Failure;
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: IO_CAP_NEG_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD END 2016.04.21
    case USER_CNF_REP_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: USER_CNF_REP_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_User_Confirmation_Request_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.User_Confirmation_Request_Reply);
            memcpy(cmd.Parameter.User_Confirmation_Request_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.User_Confirmation_Request_Reply.BD_ADDR));
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: USER_CNF_REP_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD START 2016.04.21
    case USER_CNF_NEG_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: USER_CNF_NEG_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_User_Confirmation_Request_Negative_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.User_Confirmation_Request_Reply);
            memcpy(cmd.Parameter.User_Confirmation_Request_Negative_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.User_Confirmation_Request_Negative_Reply.BD_ADDR));
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: USER_CNF_NEG_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD END 2016.04.21
    case USER_PASS_REP_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: USER_PASS_REP_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_User_Passkey_Request_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.User_Passkey_Request_Reply);
            memcpy(cmd.Parameter.User_Passkey_Request_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.User_Passkey_Request_Reply.BD_ADDR));
            HCI_STORE32(cmd.Parameter.User_Passkey_Request_Reply.Numeric_Value, nowDev->numericValue);
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: USER_PASS_REP_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD END 2015.02.06
                                                    // ADD START 2016.04.21
    case USER_PASS_NEG_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: USER_PASS_NEG_SEND\n");
            HCI_STORE16(cmd.Op_Code, HCI_User_Passkey_Request_Negative_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.User_Passkey_Request_Negative_Reply);
            memcpy(cmd.Parameter.User_Passkey_Request_Negative_Reply.BD_ADDR, nowDev->bdAddr, sizeof(cmd.Parameter.User_Passkey_Request_Negative_Reply.BD_ADDR));
            bt_sendHCIcommand();
            state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("L2CAP-RM: USER_PASS_NEG_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD END 2016.04.21

    case PROCESS:
        state = EVENT_WAIT;
        if (nowLnk != NULL) {
            unsigned char   inBuff[BT_L2CAP_MTU_SIZE];                          // ADD 2015.02.06 Separated an output buffer

            memcpy(inBuff, nowLnk->buff, nowLnk->nowSize);                      // ADD 2015.02.06
//          send_len = bt_l2capChannelManager(nowLnk->handle, nowLnk->buff, nowLnk->nowSize, nowLnk->buff, nowLnk->buffSize);   // DEL 2015.02.06
//          send_len = bt_l2capChannelManager(nowLnk->handle,                   // DEL 2017.01.03  ADD 2015.02.06
            send_len = bt_l2capChannelManager(nowLnk,                           // ADD 2017.01.03
                                              inBuff,       nowLnk->nowSize,    // ADD 2015.02.06
                                              nowLnk->buff, nowLnk->buffSize);  // ADD 2015.02.06
            if (send_len) {
                state = DATA_SEND;
//              try = 0;                                // DEL 2014.03.05
                timeo = time(NULL) + BT_SEND_TIMEOUT;   // ADD 2014.03.05
                nowLnk->sendedSize = 0;
            }
        }
        break;
                                                        // ADD START 2017.03.10
    case DATA_RECIEVE:                                  // Continue messages

    	if (nowLnk == NULL) {
        	state = EVENT_WAIT;
        } else if (time(NULL) > timeo) {
            DEBUGP("DATA_RECV timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_DATA_RECV_TIMEOUT;
            state = EVENT_WAIT;
        } else if (bt_recieveACLin()) {
			unsigned short    h;
			unsigned short    boundary;
			size_t            len;
//			unsigned short    handle;
//			struct bt_l2capLink    *q;          // DEL 2017.04.26

			h = HCI_UINT16(aclIn.Connection_Handle);
//			handle   = h & HCI_CONNECTION_HANDLE_MASK;
			boundary = h & HCI_PACKET_BOUNDARY_FLAG_MASK;
			len      = HCI_UINT16(aclIn.Data_Total_Length);

            switch(boundary){
            case HCI_PACKET_BOUNDARY_FLAG_FIRST:
            case HCI_PACKET_BOUNDARY_FLAG_FIRST_NOFL:
                if (len <= nowLnk->buffSize) {
                    struct bt_l2cap_Data_Packet	*d;
                    size_t            			t;

                    d = (struct bt_l2cap_Data_Packet *)aclIn.Data;
                    t = HCI_UINT16(d->Length) + L2CAP_Data_Packet_HeadSize;
                    memcpy(nowLnk->buff, aclIn.Data, len);
                    nowLnk->nowSize = len;
                    nowLnk->totalSize = t;
                    if (nowLnk->nowSize >= nowLnk->totalSize) {
                    	state = PROCESS;
                    } else {
                        timeo = time(NULL) + BT_RECIEVE_TIMEOUT;
                    }
//                	printf("ACLin:0x%04x len=%d %d %d %02x%02x%02x%02x%02x%02x\n", boundary, len, t, nowLnk->nowSize,
//                			nowLnk->buff[4], nowLnk->buff[5], nowLnk->buff[6], nowLnk->buff[7], nowLnk->buff[8], nowLnk->buff[9]);
                }
                break;
            case HCI_PACKET_BOUNDARY_FLAG_CONTINUE:
            case HCI_PACKET_BOUNDARY_FLAG_COMPLETE:
                if ((len + nowLnk->nowSize) <= nowLnk->buffSize) {
                    memcpy(&(nowLnk->buff[nowLnk->nowSize]), aclIn.Data, len);
                    nowLnk->nowSize += len;
                    if (nowLnk->nowSize >= nowLnk->totalSize) {
                    	state = PROCESS;
                    } else {
                        timeo = time(NULL) + BT_RECIEVE_TIMEOUT;
                    }
                }
//            	printf("ACLin:0x%04x len=%d - %d %02x%02x%02x%02x%02x%02x\n", boundary, len, nowLnk->nowSize,
//            			nowLnk->buff[4], nowLnk->buff[5], nowLnk->buff[6], nowLnk->buff[7], nowLnk->buff[8], nowLnk->buff[9]);
                break;
            default:
                break;
            }
            if (state == PROCESS){
                unsigned char   outBuff[BT_L2CAP_MTU_SIZE];

                state = EVENT_WAIT;
                send_len = bt_l2capChannelManager(nowLnk, nowLnk->buff, nowLnk->nowSize, outBuff, sizeof(outBuff));
                if (send_len) {
                    memcpy(nowLnk->buff, outBuff, send_len);
                    state = DATA_SEND;
                    timeo = time(NULL) + BT_SEND_TIMEOUT;
//                  q->sendedSize = 0;         // DEL 2017.04.26
                    nowLnk->sendedSize = 0;    // ADD 2017.04.26
                }
            }
        }
        break;
                                                    // ADD END 2017.03.10

    case DATA_SEND:

//      if (try++ > BT_SEND_TIMEOUT) {              // CHG 2014.03.05
        if (time(NULL) > timeo) {                   // CHG 2014.03.05
            DEBUGP("DATA_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_DATA_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        if (bt_isIdleACLout() && (nowLnk != NULL)) {    // Message Segmentation
            size_t          l;
            unsigned short  h;

            h = nowLnk->handle;
            if (nowLnk->sendedSize == 0) {
                h |= HCI_PACKET_BOUNDARY_FLAG_FIRST;
            } else {
                h |= HCI_PACKET_BOUNDARY_FLAG_CONTINUE;
            }
            l = MIN((send_len - nowLnk->sendedSize), (aclOutSize - HCI_ACL_Data_Packet_HeadSize));

            HCI_STORE16(aclOut.Connection_Handle, h);
            HCI_STORE16(aclOut.Data_Total_Length, l);
            memcpy(aclOut.Data, &(nowLnk->buff[nowLnk->sendedSize]), l);

            nowLnk->sendedSize += l;

            // Send request
            bt_sendACLout();

            // Next fragment
            if (nowLnk->sendedSize >= send_len) {
                state = EVENT_WAIT;
            } else {
//              try = 0;                                // DEL 2014.03.05
                timeo = time(NULL) + BT_SEND_TIMEOUT;   // ADD 2014.03.05
            }
        }
        break;

    case LE_ADV_START_SEND:
    case LE_ADV_STOP_SEND:
        if (bt_isIdleHCIcommand()) {
            HCI_STORE16(cmd.Op_Code, HCI_LE_Set_Advertise_Enable);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.LE_Set_Advertise_Enable);
            cmd.Parameter.LE_Set_Advertise_Enable.Advertising_Enable = (state == LE_ADV_START_SEND) ? HCI_Parm_Advertising_Enabled : HCI_Parm_Advertising_Disabled;
            DEBUGP("L2CAP-RM: LE_ADV_START/STOP %d\n", cmd.Parameter.LE_Set_Advertise_Enable.Advertising_Enable);
            bt_sendHCIcommand();
            state = EVENT_WAIT;
//      } else if (try++ > BT_SEND_TIMEOUT) {       // CHG 2014.03.05
        } else if (time(NULL) > timeo) {            // CHG 2014.03.05
            DEBUGP("L2CAP-RM: LE_ADV_START_SEND timeout handle=%04x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;

                                                    // ADD START 2014.02.23
    case LE_LE_LTK_REP_SEND:
        if (bt_isIdleHCIcommand()) {
            HCI_STORE16(cmd.Op_Code, HCI_LE_Long_Term_Key_Request_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.LE_Long_Term_Key_Request_Reply);
            HCI_STORE16(cmd.Parameter.LE_Long_Term_Key_Request_Reply.Connection_Handle, nowLnk->handle);
#ifdef DEL                                          // DEL START 2017.01.18
            if ((nowLnk->encryptionDiversifier[0] == 0) && (nowLnk->encryptionDiversifier[1] == 0)) {
                MEMCPY(cmd.Parameter.LE_Long_Term_Key_Request_Reply.Long_Term_Key, nowLnk->shortTermKey);
                DEBUGP("L2CAP-RM: LE_LE_LTK_REP_SEND STK %x\n", nowLnk->handle);
            } else {
                MEMCPY(cmd.Parameter.LE_Long_Term_Key_Request_Reply.Long_Term_Key, nowLnk->longTermKey);
                DEBUGP("L2CAP-RM: LE_LE_LTK_REP_SEND LTK %x\n", nowLnk->handle);
            }
#else                                               // DEL END - ADD START 2017.01.18
            MEMCPY(cmd.Parameter.LE_Long_Term_Key_Request_Reply.Long_Term_Key, nowLnk->ltk);
            DEBUGP("L2CAP-RM: LE_LE_LTK_REP_SEND LTK %04x\n", nowLnk->handle);
            DUMP(" LTK=", nowLnk->ltk);
#endif                                              // ADD END 2017.01.18
            bt_sendHCIcommand();
            state = EVENT_WAIT;
//      } else if (try++ > BT_SEND_TIMEOUT) {       // CHG 2014.03.05
        } else if (time(NULL) > timeo) {            // CHG 2014.03.05
            DEBUGP("L2CAP-RM: LE_LE_LTK_REP_SEND timeout %x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;

    case LE_LE_LTK_NEG_SEND:
        if (bt_isIdleHCIcommand()) {
            DEBUGP("L2CAP-RM: LE_LE_LTK_NEG_SEND %04x\n", nowLnk->handle);
            HCI_STORE16(cmd.Op_Code, HCI_LE_Long_Term_Key_Requested_Negative_Reply);
            cmd.Parameter_Total_Length = sizeof(cmd.Parameter.LE_Long_Term_Key_Requested_Negative_Reply);
            HCI_STORE16(cmd.Parameter.LE_Long_Term_Key_Requested_Negative_Reply.Connection_Handle, nowLnk->handle);
            bt_sendHCIcommand();
            state = EVENT_WAIT;
//      } else if (try++ > BT_SEND_TIMEOUT) {       // CHG 2014.03.05
        } else if (time(NULL) > timeo) {            // CHG 2014.03.05
            DEBUGP("L2CAP-RM: LE_LE_LTK_NEG_SEND timeout %x\n", nowLnk->handle);
            rc    = BT_L2CAP_ERR_HCI_CMD_SEND_TIMEOUT;
            state = EVENT_WAIT;
        }
        break;
                                                    // ADD END 2014.02.23

    default:
        break;
    }

    return(rc);
}
