Connect ESP32 to bluetooth classic keyboard

StuartLittle57
Posts: 4
Joined: Mon Dec 06, 2021 4:09 pm

Connect ESP32 to bluetooth classic keyboard

Postby StuartLittle57 » Mon Dec 06, 2021 5:06 pm

For a proof of concept I need to connect to a Bluetooth classic keyboard and mouse and read the input. The ESP32 needs to connect to the mouse and the keyboard at the same time (not a priority right now). I can connect to the mouse and if I print the bytes coming from this mouse I can easily decode them (for a proof of concept this is good enough for now). The ESP can see the keyboard, but the authentication fails. So I would like some help with this keyboard.

I use the esp_hid_host example from esp idf. I disabled BLE, only BT classic is used.
The mouse is off and no other BT devices are present.
The keyboard is an Apple Wireless Keyboard. Model A1314.
I use the latest version of IDF and use a an ESP32 Wroom.
The keyboard pairs with my laptop just fine. You need to type a code and press enter.
I (2528) ESP_HIDH_DEMO: SCAN...
D (2538) event: running post ESP_HIDH_EVENTS:5 with handler 0x400d782c and context 0x3ffb7358 on loop 0x3ffca68c
0x400d782c: hidh_callback at build/../main/esp_hid_host_main.c:33

V (2538) ESP_HID_GAP: BT GAP DISC_STATE START
I (2548) ESP_HIDH_DEMO: EVENT: 5
BT : 78:ca:39:49:c4:2a, COD: major: PERIPHERAL, minor: 16, service: 0x001, RSSI: -60
BT : 78:ca:39:49:c4:2a, BDNAME: Apple Wireless Keyboard
V (6518) ESP_HID_GAP: BT GAP DISC_STATE STOP
I (6518) ESP_HIDH_DEMO: SCAN: 1 result
BT : 78:ca:39:49:c4:2a, RSSI: -60, USAGE: GENERIC, COD: PERIPHERAL[KEYBOARD] srv 0x001, UUID16: 0x0000, NAME: Apple Wireless Keyboard
W (7118) BT_SDP: process_service_attr_rsp

W (7408) BT_SDP: process_service_attr_rsp
After pressing enter on the keyboard:
D (18098) nvs: nvs_open_from_partition bt_config.conf 1
D (18098) nvs: nvs_set_blob bt_cfg_key0 784
W (18108) BT_BTM: btm_sec_clr_temp_auth_service() - no dev CB

D (18118) nvs: nvs_close 4
E (18118) BT_BTC: btc_dm_auth_cmpl_evt() Authentication fail reason 5
V (18118) ESP_HID_GAP: BT GAP EVENT AUTH_CMPL
E (18118) BT_HIDH: OPEN ERROR: ERR_AUTH_FAILED
D (18128) event: running post ESP_HIDH_EVENTS:0 with handler 0x400d898c and context 0x3ffb7318 on loop 0x3ffca68c
0x400d898c: esp_hidh_process_event_data_handler at esp-idf/components/esp_hid/src/esp_hidh.c:817

D (18138) event: running post ESP_HIDH_EVENTS:0 with handler 0x400d782c and context 0x3ffb7358 on loop 0x3ffca68c
0x400d782c: hidh_callback at build/../main/esp_hid_host_main.c:33

E (18148) ESP_HIDH_DEMO: OPEN failed!
How do I get the authentication to pass? A hardcoded pin or no pin is fine for the proof of concept.
Do I need to an HCI driver? If so, where can I find one or how do I create one?

StuartLittle57
Posts: 4
Joined: Mon Dec 06, 2021 4:09 pm

Re: Connect ESP32 to bluetooth classic keyboard

Postby StuartLittle57 » Tue Dec 07, 2021 3:06 pm

I got it to work. The problem is Espressif made a lot of changes to the example on September 8th. Switching to the example from the stable version of IDF: 4.3.1 solved the problem.

Eisbaeeer
Posts: 1
Joined: Fri Jul 15, 2022 8:07 am

Re: Connect ESP32 to bluetooth classic keyboard

Postby Eisbaeeer » Fri Jul 15, 2022 8:17 am

Hi
How did you solve that?
Can you provide am example. Im working on the same. Connecting ESP32 via classic bt to a keyboard.
Greets Lars

StuartLittle57
Posts: 4
Joined: Mon Dec 06, 2021 4:09 pm

Re: Connect ESP32 to bluetooth classic keyboard

Postby StuartLittle57 » Mon Jul 18, 2022 10:11 am

Hi Lars,

Here are related issues:
https://github.com/espressif/esp-idf/issues/8027
https://github.com/espressif/esp-idf/issues/8028

I simply modified the BT_HID_HOST example. It only worked for me with an older version of IDF, but that was 8 months ago, so maybe a newer version works too. I reduced the debug printing in the example as that caused a stackoverflow (it is printing in an interrupt). I also added a class for processing the keyboard events.

I don't think I can share the whole code. But I can share the class. Simply call the method inputCallback from hidh_callback event ESP_HIDH_INPUT_EVENT. This code has only been tested on an apple keyboard.

Code: Select all

class BT_HID_Keyboard
{
public:
    BT_HID_Keyboard(){}

    void inputCallback(const uint8_t* data, uint16_t length)
    {
        if (length >= 5)
        {
            uint8_t pressedButtons[3];
            pressedButtons[0] = data[2];
            pressedButtons[1] = data[3];
            pressedButtons[2] = data[4];

            uint8_t modifier = data[0];
            bool shift = (modifier & 0x22) !=0;

            for (int i=0; i < 3; ++i)
            {
                uint8_t keyCode = pressedButtons[i];
                if (keyCode != 0) // a key is pressed
                {
                    bool found = false;
                    // todo use std lib for search
                    for (int j=0; j < 3; ++j)
                    {
                        if (keyCode == m_pressedButtons[j])
                        {
                            found = true;
                            break;
                        }
                    }

                    if (!found) // not found = new = rising edge
                    {
                        if ( (keyCode >= 0x04) && (keyCode <= 0x1d)) // letter
                        {
                          if (shift)
                          {
                            m_text += char(keyCode - 0x04 + 'A');
                          }
                          else
                          {
                            m_text += char(keyCode - 0x04 + 'a');
                          }
                        }
                        else if(keyCode == 0x28) // return-key
                        {
                            m_text.clear();
                        }
                        else if(keyCode == 0x2A) // backspace
                        {
                            if (!m_text.empty())
                            {
                                m_text.pop_back();
                            }
                        }
                        else if ( (keyCode >= 0x1E) && (keyCode <= 0x27)) // digit
                        {
                            if (!shift)
                            {
                                m_text += (keyCode - 0x1E + 1) % 10 + '0';
                            }
                        }
                        else if(keyCode == 0x2C) // space
                        {
                            m_text += ' ';
                        }
                        //todo add mapping table
                    }
                }
            }

            m_pressedButtons[0] = pressedButtons[0];
            m_pressedButtons[1] = pressedButtons[1];
            m_pressedButtons[2] = pressedButtons[2];
        }
    }

    void printStatus()
    {
        printf("Keyboard: %s\n", m_text.c_str());
    }

private:
    uint8_t m_pressedButtons[3];

    std::string m_text;
};

XcvrMon
Posts: 1
Joined: Wed Nov 09, 2022 9:32 pm

Re: Connect ESP32 to bluetooth classic keyboard

Postby XcvrMon » Wed Nov 09, 2022 10:29 pm

Stuart, I joined the forum today. I found this topic and its close to what I want to do for my first project.
I want to pair and ESP32 with a Logitek (or similar) Qwerty Bluetooth keyboard. The serial keystrokes would be received, display and sent over a serial port.
Does your example do this?
Please advise. Thanks.
Any input from other members?

Who is online

Users browsing this forum: Bing [Bot] and 114 guests