Skip to content

When device is paired on reconnect of the device not working #464

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
JuanJoseMoralesCalvo opened this issue Oct 16, 2022 · 25 comments
Closed

Comments

@JuanJoseMoralesCalvo
Copy link

Hi im trying to create an HID Gamepad so when i first pair the device all works great but when i (for example) reset the module it doesnt work. Any suggestion on the connect CallBack?

@CybershoesVR
Copy link

CybershoesVR commented Oct 17, 2022

same here. On PC reconnect works, but on Quest2 does not work.
I also use the ESP32-BLE-Gamepad library https://github.com/lemmingDev/ESP32-BLE-Gamepad
It did work in summer, but now, not anymore.

@h2zero
Copy link
Owner

h2zero commented Oct 17, 2022

Can either of you share a debug log output when this occurs?

@JuanJoseMoralesCalvo
Copy link
Author

The workaround for me was to add security to the BLE, but honestly i dont know the reason :D

Attach to setup() after advertising:

NimBLESecurity *SECURITY_MANDATORY = new BLESecurity();
SECURITY_MANDATORY->setAuthenticationMode(ESP_LE_AUTH_BOND);

@CybershoesVR
Copy link

Thank you but this did not work. I tried a few other setting but decided it'll be better to go with debugging as @h2zero suggested.

from the log:
GamePadPlus V3 is a BT gamepad device that reconnects successful.
Cybershoes2 is our BT gamepad device that does reconnect but gamepad functionality fails upon reconnect.

Dear @h2zero, please can you hint at what makes the difference?

odh_logs_2022-10-18 13.55.53.833.txt

@h2zero
Copy link
Owner

h2zero commented Oct 18, 2022

Looks like you need to enable bonding. Try adding this after initialization:
`NimBLEDevice::setSecurityAuth(true, true, true);'

Have a look at the secure client/server examples.

@CybershoesVR
Copy link

CybershoesVR commented Oct 18, 2022

yes, I did that as you see below.
I am using NimBLE 1.38 with ESP32-BLE-Gamepad 0.5.1, because using NimBLE 1.40 makes my ESP32-C crash.

void BleGamepad::taskServer(void *pvParameter)
{
    BleGamepad *BleGamepadInstance = (BleGamepad *)pvParameter; // static_cast<BleGamepad *>(pvParameter);
    NimBLEDevice::init(BleGamepadInstance->deviceName);
    NimBLEServer *pServer = NimBLEDevice::createServer();
    pServer->setCallbacks(BleGamepadInstance->connectionStatus);

    BleGamepadInstance->hid = new NimBLEHIDDevice(pServer);
    BleGamepadInstance->inputGamepad = BleGamepadInstance->hid->inputReport(BleGamepadInstance->configuration.getHidReportId()); // <-- input REPORTID from report map
    BleGamepadInstance->connectionStatus->inputGamepad = BleGamepadInstance->inputGamepad;

    BleGamepadInstance->hid->manufacturer()->setValue(BleGamepadInstance->deviceManufacturer);

    BleGamepadInstance->hid->pnp(0x01, vid, pid, 0x0110);
    BleGamepadInstance->hid->hidInfo(0x00, 0x01);

    NimBLESecurity *SECURITY_MANDATORY = new BLESecurity();
    SECURITY_MANDATORY->setAuthenticationMode(ESP_LE_AUTH_BOND); // ESP_LE_AUTH_REQ_BOND_MITM,
    SECURITY_MANDATORY->setCapability(ESP_IO_CAP_NONE);

    /**
     * @brief Set the authorization mode for this device.
     * @param bonding If true we allow bonding, false no bonding will be performed.
     * @param mitm If true we are capable of man in the middle protection, false if not.
     * @param sc If true we will perform secure connection pairing, false we will use legacy pairing.
     */
    
    //NimBLEDevice::setSecurityAuth(bool bonding, bool mitm, bool sc);
    NimBLEDevice::setSecurityAuth(true, true, true);
    
    //NimBLEDevice::setSecurityAuth( BLE_SM_PAIR_AUTHREQ_MITM); // BEST must pair again each time but no need to unpair
    //NimBLEDevice::setSecurityAuth(BLE_SM_PAIR_AUTHREQ_SC);    //same as usual

    uint8_t *customHidReportDescriptor = new uint8_t[hidReportDescriptorSize];
    memcpy(customHidReportDescriptor, tempHidReportDescriptor, hidReportDescriptorSize);

    for (int i = 0; i < hidReportDescriptorSize; i++)
        Serial.printf("%02x", customHidReportDescriptor[i]);

    BleGamepadInstance->hid->reportMap((uint8_t *)customHidReportDescriptor, hidReportDescriptorSize);
    BleGamepadInstance->hid->startServices();

    BleGamepadInstance->onStarted(pServer);

    NimBLEAdvertising *pAdvertising = pServer->getAdvertising();
    pAdvertising->setAppearance(HID_GAMEPAD);
    pAdvertising->addServiceUUID(BleGamepadInstance->hid->hidService()->getUUID());
    pAdvertising->start();
    //https://github.com/h2zero/NimBLE-Arduino/issues/464
    //The workaround for me was to add security to the BLE, but honestly i dont know the reason :D
    //Attach to setup() after advertising:
    //NimBLESecurity *SECURITY_MANDATORY = new BLESecurity();
    //SECURITY_MANDATORY->setAuthenticationMode(ESP_LE_AUTH_BOND);
    //end of inserted code


    BleGamepadInstance->hid->setBatteryLevel(BleGamepadInstance->batteryLevel);

    ESP_LOGD(LOG_TAG, "Advertising started!");
    vTaskDelay(portMAX_DELAY); // delay(portMAX_DELAY);
}

In a variation I also tried without

    NimBLESecurity *SECURITY_MANDATORY = new BLESecurity();
    SECURITY_MANDATORY->setAuthenticationMode(ESP_LE_AUTH_BOND); // ESP_LE_AUTH_REQ_BOND_MITM,
    SECURITY_MANDATORY->setCapability(ESP_IO_CAP_NONE);

@CybershoesVR
Copy link

CybershoesVR commented Oct 18, 2022

reconnecting our Cybershoes gives an encryption failed:

15:55:28.310  1683  1704 D BluetoothGattServer: onConnectionUpdated() - Device=34:B4:72:00:A1:D6 interval=9 latency=0 timeout=600 status=0
15:55:28.356  1412  2092 W bt_btif       : btif_gatt_set_encryption_cb() - Encryption failed (1)
15:55:28.356  1412  2092 E bt_btif       : bta_hh_security_cmpl() - encryption failed; status=0x000e, reason=0x000a

reconnecting GamePadPlus

15:54:46.249  1683  1704 D BluetoothGattServer: onConnectionUpdated() - Device=20:21:03:07:B9:98 interval=12 latency=0 timeout=200 status=0
15:54:46.331  1412  2092 W bt_stack      : [WARNING:bta_gattc_api.cc(652)] notification already registered
15:54:46.332  1412  2092 I chatty        : uid=1002(bluetooth) bt_main_thread identical 1 line
15:54:46.332  1412  2092 W bt_stack      : [WARNING:bta_gattc_api.cc(652)] notification already registered
15:54:46.332  1412  2092 W bt_btif       : bta_hh_co_open: Found an existing device with the same handle dev_status=2, address=20:21:03:07:b9:98, attr_mask=0x0000, sub_class=0x00, app_id=255
15:54:46.332  1412  1662 W bt_btif       : btif_hh_upstreams_evt: BTA_HH_OPN_EVT: handle=16, status =0
15:54:46.332  1412  1662 W bt_btif       : BTA_HH_OPEN_EVT: Found device...Getting dscp info for handle ... 16
15:54:46.332  1412  1662 I bt_btif_dm    : get_cod remote_cod = 0x00000504
15:54:46.332  1412  1662 I bt_btif_dm    : get_cod remote_cod = 0x00000504
15:54:46.336  1412  1412 D BluetoothAdapterService: getAdapterService() - returning com.android.bluetooth.btservice.AdapterService@590f4fe
15:54:46.336  1412  1662 W bt_btif       : btif_hh_upstreams_evt: name = GamePadPlus V3
15:54:46.336  1412  1662 W bt_btif       : bta_hh_co_send_hid_info: fd = 108, name = [GamePadPlus V3], dscp_len = 187
15:54:46.336  1412  1662 W bt_btif       : bta_hh_co_send_hid_info: vendor_id = 0x1949, product_id = 0x0402, version= 0x0111,ctry_code=0x00
15:54:46.347  1412  1412 D BluetoothAdapterService: isQuetModeEnabled() - Enabled = false

and finally

15:54:46.547  1034  1142 I InputReader   : Device added: id=15, name='GamePadPlus V3', sources=0x01000511
15:54:46.548  2020  2020 D GamepadListener: Adding Device: GamePadPlus V3 pid: 1026 sources: 16778513
15:54:46.549  3026  3026 D GamepadListener: Adding Device: GamePadPlus V3 pid: 1026 sources: 16778513
15:54:46.549  2236  2236 I [OAO] ShellOverlayServiceJNI: NativePTKServiceNotifyDeviceConnectionChanged
15:54:46.549  2236  2236 D [OAO] ShellApplication: PTKService enumerated keyboard: {vendorId: 0x1949 (0n6473), productId: 0x402 (0n1026)}
15:54:46.554  1734  1734 D GamepadListener: Adding Device: GamePadPlus V3 pid: 1026 sources: 16778513
15:54:46.577  2971  2971 D GamepadListener: Adding Device: GamePadPlus V3 pid: 1026 sources: 16778513

@CybershoesVR
Copy link

also no success with:

    NimBLEDevice::setSecurityAuth(true, true, true);
    NimBLESecurity *SECURITY_MANDATORY = new BLESecurity();

    /**
     * @brief Set requested authentication mode
     * @param [in] auth_req A bitmask containing one or more of:
     * * ESP_LE_AUTH_NO_BOND              0x00
     * * ESP_LE_AUTH_BOND                 0x01
     * * ESP_LE_AUTH_REQ_MITM             (1 << 2)
     * * ESP_LE_AUTH_REQ_BOND_MITM        (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_MITM)
     * * ESP_LE_AUTH_REQ_SC_ONLY          (1 << 3)
     * * ESP_LE_AUTH_REQ_SC_BOND          (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_SC_ONLY)
     * * ESP_LE_AUTH_REQ_SC_MITM          (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY)
     * * ESP_LE_AUTH_REQ_SC_MITM_BOND     (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY | ESP_LE_AUTH_BOND)
     */
    SECURITY_MANDATORY->setAuthenticationMode(ESP_LE_AUTH_REQ_BOND_MITM); // ESP_LE_AUTH_REQ_BOND_MITM,ESP_LE_AUTH_BOND
    //SECURITY_MANDATORY->setCapability(ESP_IO_CAP_NONE);


    SECURITY_MANDATORY->setInitEncryptionKey(BLE_SM_PAIR_KEY_DIST_ENC);
    SECURITY_MANDATORY->setRespEncryptionKey(BLE_SM_PAIR_KEY_DIST_ENC);

@CybershoesVR
Copy link

CybershoesVR commented Oct 18, 2022

sometimes (once in 5-10 attempts) connection and reconnection (but then I need to confirm pairing again) works successfully with:

NimBLEDevice::setSecurityAuth(true, true, false);

@h2zero
Copy link
Owner

h2zero commented Oct 18, 2022

I'm not too sure what the error is yet, the logs suggest an error in a value passed during pairing. What kind of pairing does the other device expect?

If not using PIN codes or any other mitm protection then try setting the last 2 parameters of the NimBLEDevice::setSecurityAuth call to false. Otherwise just set the last parameter to false if mitm is required.

@h2zero
Copy link
Owner

h2zero commented Oct 18, 2022

You should also remove this:


NimBLESecurity *SECURITY_MANDATORY = new BLESecurity();

    /**
     * @brief Set requested authentication mode
     * @param [in] auth_req A bitmask containing one or more of:
     * * ESP_LE_AUTH_NO_BOND              0x00
     * * ESP_LE_AUTH_BOND                 0x01
     * * ESP_LE_AUTH_REQ_MITM             (1 << 2)
     * * ESP_LE_AUTH_REQ_BOND_MITM        (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_MITM)
     * * ESP_LE_AUTH_REQ_SC_ONLY          (1 << 3)
     * * ESP_LE_AUTH_REQ_SC_BOND          (ESP_LE_AUTH_BOND | ESP_LE_AUTH_REQ_SC_ONLY)
     * * ESP_LE_AUTH_REQ_SC_MITM          (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY)
     * * ESP_LE_AUTH_REQ_SC_MITM_BOND     (ESP_LE_AUTH_REQ_MITM | ESP_LE_AUTH_REQ_SC_ONLY | ESP_LE_AUTH_BOND)
     */
    SECURITY_MANDATORY->setAuthenticationMode(ESP_LE_AUTH_REQ_BOND_MITM); // ESP_LE_AUTH_REQ_BOND_MITM,ESP_LE_AUTH_BOND
    //SECURITY_MANDATORY->setCapability(ESP_IO_CAP_NONE);


    SECURITY_MANDATORY->setInitEncryptionKey(BLE_SM_PAIR_KEY_DIST_ENC);
    SECURITY_MANDATORY->setRespEncryptionKey(BLE_SM_PAIR_KEY_DIST_ENC);

That is conflicting with the security settings above it.

@JuanJoseMoralesCalvo
Copy link
Author

@CybershoesVR Try this workaround from chewara, it sounds like its happening the same:

class MyCallbacks : public BLEServerCallbacks {
void onConnect(BLEServer* pServer){
Serial.println("connected");
BLEDescriptor *desc = input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
uint8_t val[] = {0x01, 0x00};
desc->setValue(val, 2);
}

void onDisconnect(BLEServer* pServer){
Serial.println("disconnected");
}
};

Issue Open:
nkolban/esp32-snippets#632

@JuanJoseMoralesCalvo
Copy link
Author

You have to add something like this on the onConenct:

BLEDescriptor *desc = input->getDescriptorByUUID(BLEUUID((uint16_t)0x2902));
uint8_t val[] = {0x01, 0x00};
desc->setValue(val, 2);

@fabdelgado
Copy link
Contributor

I’m facing the same issue.

@JuanJoseMoralesCalvo Did your suggestion work for you?

@JuanJoseMoralesCalvo
Copy link
Author

The workaround on comment #12 didnt work as i understand its only for the nkolban esp32 libraries. Finally by adding security it worked.

NimBLESecurity *SECURITY_MANDATORY = new NimBLESecurity();
SECURITY_MANDATORY->setAuthenticationMode(ESP_LE_AUTH_BOND); // ESP_LE_AUTH_REQ_BOND_MITM,
SECURITY_MANDATORY->setCapability(ESP_IO_CAP_NONE);

@fabdelgado
Copy link
Contributor

On which lines of which file should I put this?

Please explain me if I should add or replace code?

@h2zero
Copy link
Owner

h2zero commented Nov 5, 2022

I would encourage not to use the security class as it has been deprecated.

The equivalent call is simply:

NimBLEDevice::setSecurityAuth(true, false, false); // enable bonding, no MITM, no SC

The IO caps default to NONE. Just put that line somewhere after initializing NimBLE.

@fabdelgado
Copy link
Contributor

@h2zero
Copy link
Owner

h2zero commented Nov 5, 2022

Looks good to me

@fabdelgado
Copy link
Contributor

I will try that!

@fabdelgado
Copy link
Contributor

fabdelgado commented Nov 6, 2022

It has not worked for me with my chromecast v3 Google TV.
You can review the video I have recorded for you.

WhatsApp.Video.2022-11-05.at.9.02.58.PM.mp4

@h2zero
Copy link
Owner

h2zero commented Nov 6, 2022

Hmm, please try erasing the flash of the esp32 then upload your code. Also remove any devices bonded to the TV if you can.

@fabdelgado
Copy link
Contributor

fabdelgado commented Nov 6, 2022

@h2zero this worked for me, thanks for the help.

WhatsApp.Video.2022-11-06.at.1.44.45.PM.mp4

This is the code that I have used, I have left it for future issues.

`void setup() {

NimBLEDevice::init("NimBLE");

NimBLEDevice::setSecurityAuth(true, false, false); // enable bonding, no MITM, no SC
}`

@fabdelgado
Copy link
Contributor

@h2zero I have another related problem, when I press forget device and then restart the Chromecast it unbinds the remote from Chromecast instead of ESP32.
This problem happened to me before the problem of connecting and disconnecting.
Do you have any idea?

@h2zero
Copy link
Owner

h2zero commented Nov 7, 2022

I don't have any idea why that would happen, wouldn't have anything to do with the esp32 though.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

4 participants