diff --git a/README.md b/README.md index 678aaf8..883f31e 100644 --- a/README.md +++ b/README.md @@ -41,6 +41,8 @@ With `idf.py -p (PORT) flash` or `make flash` you can upload this build to an ES With `idf.py -p (PORT) monitor` or `make monitor` you can see the debug output (please use this output if you open an issue) or trigger basic test commands (mouse movement or a keyboard key press) on a connected target. +__Note: Currently tested IDF version: release/v5.0 (other ones won't be supported!)__ + ### esp32miniBT vs. Arduino Nano Connect This firmware is used on 2 different devices in context of our assistive devices: @@ -50,7 +52,7 @@ This firmware is used on 2 different devices in context of our assistive devices __Note:__ Please select the correct type of board in `idf.py menuconfig`! __Note:__ If you want to use this firmware on a custom board, you can select the external UART interface settings in menuconfig; for our boards the pinning, baudrate and UART config is pre-defined. - + # Usage via Console or second UART ## Control via stdin (make monitor) @@ -114,7 +116,14 @@ _Note:_ currently we only support the US keyboard layout. |Byte 0|Byte 1|Byte 2|Byte 3|Byte 4|Byte 5|Byte 6|Byte 7|Byte 8| |------|------|------|------|------|------|------|------|------| -| 0xFD | modifier mask | don't care | keycode 1 | keycode 2 | keycode 3 | keycode 4 | keycode 5 | keycode 6 | +| 0xFD | modifier mask | 0x00 | keycode 1 | keycode 2 | keycode 3 | keycode 4 | keycode 5 | keycode 6 | + +__Joystick:__ + + +|Byte 0|Byte 1|Byte 2|Byte 3-8|Byte 9|Byte 10|Byte 11|Byte 12|Byte 13| +|------|------|------|------|------|------|------|------|------| +| 0xFD | don't care | 0x01 | X,Y,Z,Rz,Rx,Ry axis (each _int8_t_) | hat switch (0 is rest position; 1-8 are directions) | buttons 0-7 | buttons 8-15 | buttons 16-23 | buttons 24-31 | ## RAW HID input from sourcecode @@ -138,7 +147,6 @@ Please use the functions provided by `esp_hidd_prf_api.c`. - Paul Stoffregen for the implementation of the keyboard layouts for his Teensyduino project: www.pjrc.com - Neil Kolban for his great contributions to the ESP32 SW (in particular the Bluetooth support): https://github.com/nkolban - Chegewara for help and support - -and to Espressif for providing the HID implementation within the esp-idf. +and to Espressif for providing the HID implementation within the esp-idf. diff --git a/main/CMakeLists.txt b/main/CMakeLists.txt index 31d5ae7..87a4793 100644 --- a/main/CMakeLists.txt +++ b/main/CMakeLists.txt @@ -3,6 +3,7 @@ idf_component_register(SRCS "ble_hidd_demo_main.c" "hid_dev.c" "hid_device_le_prf.c" INCLUDE_DIRS "." - REQUIRES esp_hid PRIV_REQUIRES esp_wifi esp_https_server esp_eth nvs_flash lwip fatfs esp_https_ota esp_hid app_update) + REQUIRES esp_hid + PRIV_REQUIRES esp_wifi esp_https_server esp_eth nvs_flash spi_flash lwip fatfs esp_https_ota esp_hid app_update) target_compile_options(${COMPONENT_LIB} PRIVATE -Wno-unused-const-variable) diff --git a/main/Kconfig.projbuild b/main/Kconfig.projbuild index 34e84f0..8f66758 100644 --- a/main/Kconfig.projbuild +++ b/main/Kconfig.projbuild @@ -31,14 +31,14 @@ menu "esp32_mouse_keyboard / FLipMouse & FABI config" range 1 2 endmenu config MODULE_USEKEYBOARD - bool "Enable BLE-HID keyboard (UNUSED)" + bool "Enable BLE-HID keyboard (UNUSED, mouse is always enabled)" default y help Enable the Keyboard interface for Bluetooth. config MODULE_USEMOUSE depends on MODULE_USEKEYBOARD - bool "Enable BLE-HID mouse (UNUSED)" + bool "Enable BLE-HID mouse (UNUSED, kbd is always enabled)" default y help Enable the Mouse interface for Bluetooth. @@ -54,8 +54,8 @@ menu "esp32_mouse_keyboard / FLipMouse & FABI config" config MODULE_USEJOYSTICK depends on MODULE_USEMOUSE - bool "Enable BLE-HID joystick (UNUSED)" - default n + bool "Enable BLE-HID joystick" + default y help Enable the Joystick interface for Bluetooth. diff --git a/main/ble_hidd_demo_main.c b/main/ble_hidd_demo_main.c index f35c9ef..9c96370 100644 --- a/main/ble_hidd_demo_main.c +++ b/main/ble_hidd_demo_main.c @@ -76,10 +76,9 @@ /** * Note: - * 1. Win10 does not support vendor report , So SUPPORT_REPORT_VENDOR is always set to FALSE, it defines in hidd_le_prf_int.h - * 2. Update connection parameters are not allowed during iPhone HID encryption, slave turns + * 1. Update connection parameters are not allowed during iPhone HID encryption, slave turns * off the ability to automatically update connection parameters during encryption. - * 3. After our HID device is connected, the iPhones write 1 to the Report Characteristic Configuration Descriptor, + * 2. After our HID device is connected, the iPhones write 1 to the Report Characteristic Configuration Descriptor, * even if the HID encryption is not completed. This should actually be written 1 after the HID encryption is completed. * we modify the permissions of the Report Characteristic Configuration Descriptor to `ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE_ENCRYPTED`. * if you got `GATT_INSUF_ENCRYPTION` error, please ignore. @@ -422,6 +421,7 @@ static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t * xEventGroupSetBits(eventgroup_system,SYSTEM_CURRENTLY_ADVERTISING); break; } + /** case ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT: { ESP_LOGI(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT", __func__); ESP_LOG_BUFFER_HEX(HID_DEMO_TAG, param->vendor_write.data, param->vendor_write.length); @@ -431,6 +431,7 @@ static void hidd_event_callback(esp_hidd_cb_event_t event, esp_hidd_cb_param_t * ESP_LOGI(HID_DEMO_TAG, "%s, ESP_HIDD_EVENT_BLE_LED_OUT_WRITE_EVT, keyboard LED value: %d", __func__, param->vendor_write.data[0]); break; } + */ case ESP_HIDD_EVENT_BLE_CONGEST: { if(param->congest.congested) @@ -556,6 +557,7 @@ void processCommand(struct cmdBuf *cmdBuffer) // $SW aabbccddeeff (select a BT addr to send the HID commands to) // $GC get connected devices // $NAME set name of bluetooth device + // $APx (0-4) Set the appearance value for advertising (0x03C0 - 0x03C4). See https://specificationrefs.bluetooth.com/assigned-values/Appearance%20Values.pdf page 8 // $GV get the value of the given key from NVS. Note: no spaces in ! max. key length: 15 // $SV set the value of the given key & store to NVS. Note: no spaces in ! // $CV clear all key/value pairs set with $SV @@ -570,6 +572,32 @@ void processCommand(struct cmdBuf *cmdBuffer) esp_ble_bond_dev_t * btdevlist; int counter; esp_err_t ret; + + /**++++ set BLE appearance ++++*/ + if(strncmp(input,"AP ", 2) == 0) + { + uint8_t appv = input[2] - '0'; + if(appv <= 4) + { + ESP_LOGI(EXT_UART_TAG,"setting appearance to NVS, will show on next reboot"); + nvs_set_u8(nvs_storage_h,"BLEAPPEAR",appv); + nvs_commit(nvs_storage_h); + if(cmdBuffer->sendToUART != 0) + { + uart_write_bytes(ext_uart_num, "AP:",strlen("AP:")); + uart_write_bytes(ext_uart_num, &input[2],1); + uart_write_bytes(ext_uart_num,nl,sizeof(nl)); //newline + } + } else { + ESP_LOGE(EXT_UART_TAG,"Cannot set appearance, value not correct. Use AP0 - AP4"); + if(cmdBuffer->sendToUART != 0) + { + uart_write_bytes(ext_uart_num, "AP:invalid number, AP0-AP4",strlen("AP:invalid number, AP0-AP4")); + uart_write_bytes(ext_uart_num,nl,sizeof(nl)); //newline + } + } + return; + } /**++++en-/disable logging++++*/ if(strcmp(input,"LG0") == 0) @@ -999,9 +1027,9 @@ void uart_parse_command (uint8_t character, struct cmdBuf * cmdBuffer) case CMDSTATE_GET_RAW: cmdBuffer->buf[cmdBuffer->bufferLength]=character; - if ((cmdBuffer->bufferLength == 1) && (character==0x01)) { // we have a joystick report: increase by 4 bytes - cmdBuffer->expectedBytes += 6; - //ESP_LOGI(EXT_UART_TAG,"expecting 4 more bytes for joystick"); + if ((cmdBuffer->bufferLength == 1) && (character==0x01)) { // we have a joystick report: increase by 5 bytes + cmdBuffer->expectedBytes += 5; + //ESP_LOGI(EXT_UART_TAG,"expecting 5 more bytes for joystick"); } cmdBuffer->bufferLength++; @@ -1011,25 +1039,35 @@ void uart_parse_command (uint8_t character, struct cmdBuf * cmdBuffer) ESP_LOGI(EXT_UART_TAG,"not connected, cannot send report"); } else { if (cmdBuffer->buf[1] == 0x00) { // keyboard report - //if hid_conn_id is set (!= -1) we send to one device only. Send to all otherwise - if(hid_conn_id == -1) - { - for(uint8_t i = 0; ibuf[0],&cmdBuffer->buf[2],6); - } - } else { - esp_hidd_send_keyboard_value(hid_conn_id,cmdBuffer->buf[0],&cmdBuffer->buf[2],6); - } + //if hid_conn_id is set (!= -1) we send to one device only. Send to all otherwise + if(hid_conn_id == -1) + { + for(uint8_t i = 0; ibuf[0],&cmdBuffer->buf[2],6); + } + } else { + esp_hidd_send_keyboard_value(hid_conn_id,cmdBuffer->buf[0],&cmdBuffer->buf[2],6); + } - //update timestamp - timestampLastSent = esp_timer_get_time(); - } else if (cmdBuffer->buf[1] == 0x01) { // joystick report - //ESP_LOGI(EXT_UART_TAG,"joystick: buttons: 0x%X:0x%X:0x%X:0x%X",cmdBuffer->buf[2],cmdBuffer->buf[3],cmdBuffer->buf[4],cmdBuffer->buf[5]); - //uint8_t joy[HID_JOYSTICK_IN_RPT_LEN]; - //memcpy(joy,&cmdBuffer->buf[2],HID_JOYSTICK_IN_RPT_LEN); - ///@todo esp_hidd_send_joystick_value... - } else if (cmdBuffer->buf[1] == 0x03) { // mouse report + //update timestamp + timestampLastSent = esp_timer_get_time(); + } else if (cmdBuffer->buf[1] == 0x01) { // joystick report + ESP_LOGI(EXT_UART_TAG,"joystick: axis: 0x%X:0x%X:0x%X:0x%X, hat: %d",cmdBuffer->buf[2],cmdBuffer->buf[3],cmdBuffer->buf[4],cmdBuffer->buf[5],cmdBuffer->buf[8]); + ESP_LOGI(EXT_UART_TAG,"joystick: buttons: 0x%X:0x%X:0x%X:0x%X",cmdBuffer->buf[9],cmdBuffer->buf[10],cmdBuffer->buf[11],cmdBuffer->buf[12]); + //@todo should be HID_JOYSTICK_IN_RPT_LEN, but not available here. + uint8_t joy[11]; + memcpy(joy,&cmdBuffer->buf[2],11); + //send joystick report + #if CONFIG_MODULE_USEJOYSTICK + for(uint8_t i = 0; ibuf[1] == 0x03) { // mouse report if(hid_conn_id == -1) { for(uint8_t i = 0; i HID_KEYBOARD_IN_RPT_LEN - 2) { + //if (num_key > HID_KEYBOARD_IN_RPT_LEN - 2) { + ///@note Here without padding byte as well. + if (num_key > HID_KEYBOARD_IN_RPT_LEN - 1) { ESP_LOGE(HID_LE_PRF_TAG, "%s(), the number key should not be more than %d", __func__, HID_KEYBOARD_IN_RPT_LEN); return; } @@ -128,10 +134,13 @@ void esp_hidd_send_keyboard_value(uint16_t conn_id, key_mask_t special_key_mask, buffer[0] = special_key_mask; for (int i = 0; i < num_key; i++) { - buffer[i+2] = keyboard_cmd[i]; + ///@note start @1 instead of @2 with padding byte. + buffer[i+1] = keyboard_cmd[i]; } - ESP_LOGD(HID_LE_PRF_TAG, "the key vaule = %d,%d,%d, %d, %d, %d,%d, %d", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); + //ESP_LOGD(HID_LE_PRF_TAG, "the key value = %d,%d,%d, %d, %d, %d,%d, %d", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6], buffer[7]); + ///@note here is the padding byte removed as well. + ESP_LOGD(HID_LE_PRF_TAG, "the key value = %d,%d,%d, %d, %d, %d,%d", buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6]); hid_dev_send_report(hidd_le_env.gatt_if, conn_id, HID_RPT_ID_KEY_IN, HID_REPORT_TYPE_INPUT, HID_KEYBOARD_IN_RPT_LEN, buffer); return; @@ -152,5 +161,51 @@ void esp_hidd_send_mouse_value(uint16_t conn_id, uint8_t mouse_button, int8_t mi return; } +#if CONFIG_MODULE_USEJOYSTICK +/** + * + * @brief Send a Joystick report, set individual axis + * + * @param conn_id HID over GATT connection ID to be used. + * @param x,y,z,rz,rx,ry Individual gamepad axis + * @param hat Hat switch status. Send 0 for rest/middleposition; 1-8 to for a direction. + * @param buttons Button bitmap, button 0 is bit 0 and so on. + */ +void esp_hidd_send_joy_value(uint16_t conn_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons) +{ + uint8_t data[HID_JOYSTICK_IN_RPT_LEN] = {0}; + + //build axis into array + data[0] = x; + data[1] = y; + data[2] = z; + data[3] = rz; + data[4] = rx; + data[5] = ry; + + //add hat & buttons + data[6] = hat; + data[7] = (uint8_t)(buttons & 0xFF); + data[8] = (uint8_t)((buttons>>8) & 0xFF); + data[9] = (uint8_t)((buttons>>16) & 0xFF); + data[10] = (uint8_t)((buttons>>24) & 0xFF); + + //use other joystick function to send data + esp_hidd_send_joy_report(conn_id, data); +} +/** + * + * @brief Send a Joystick report, use a byte array + * + * @param conn_id HID over GATT connection ID to be used. + * @param report Pointer to a 11 Byte sized array which contains the full joystick/gamepad report + * @warning This function reads 11 Bytes and sends them without checks. + */ +void esp_hidd_send_joy_report(uint16_t conn_id, uint8_t *report) +{ + hid_dev_send_report(hidd_le_env.gatt_if, conn_id, + HID_RPT_ID_JOY_IN, HID_REPORT_TYPE_INPUT, HID_JOYSTICK_IN_RPT_LEN, report); +} +#endif diff --git a/main/esp_hidd_prf_api.h b/main/esp_hidd_prf_api.h index d40e01f..afbd2b3 100644 --- a/main/esp_hidd_prf_api.h +++ b/main/esp_hidd_prf_api.h @@ -30,8 +30,6 @@ typedef enum { ESP_HIDD_EVENT_DEINIT_FINISH, ESP_HIDD_EVENT_BLE_CONNECT, ESP_HIDD_EVENT_BLE_DISCONNECT, - ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT, - ESP_HIDD_EVENT_BLE_LED_OUT_WRITE_EVT, ESP_HIDD_EVENT_BLE_CONGEST, } esp_hidd_cb_event_t; @@ -165,12 +163,66 @@ esp_err_t esp_hidd_profile_deinit(void); */ uint16_t esp_hidd_get_version(void); +/** + * + * @brief Send consumer keys. + * + * @param conn_id HID over GATT connection ID to be used. + * @param key_cmd Type of consumer key, use defines like HID_CONSUMER_xx (e.g. HID_CONSUMER_MUTE) + * @param key_pressed True / False if key should be pressed or not. + * + */ void esp_hidd_send_consumer_value(uint16_t conn_id, uint8_t key_cmd, bool key_pressed); +/** + * + * @brief Send a keyboard report. + * + * @param conn_id HID over GATT connection ID to be used. + * @param special_key_mask All special keys (Alt / Shift / CTRL) in one byte + * @param keyboard_cmd Array of keycodes to be sent + * @param num_key Count of keycodes in keyboard_cmd which should be sent. + * + */ void esp_hidd_send_keyboard_value(uint16_t conn_id, key_mask_t special_key_mask, uint8_t *keyboard_cmd, uint8_t num_key); +/** + * + * @brief Send a Mouse report. + * + * @param conn_id HID over GATT connection ID to be used. + * @param mouse_button Mouse button values, 1 is pressed, 0 is released. bit 0: left, bit 1: right, bit 2: middle button + * @param mickeys_x relative X axis movement + * @param mickeys_y relative Y axis movement + * @param wheel relative mouse wheel movement + */ void esp_hidd_send_mouse_value(uint16_t conn_id, uint8_t mouse_button, int8_t mickeys_x, int8_t mickeys_y, int8_t wheel); + +#if CONFIG_MODULE_USEJOYSTICK +/** + * + * @brief Send a Joystick report, set individual axis + * + * @param conn_id HID over GATT connection ID to be used. + * @param x,y,z,rz,rx,ry Individual gamepad axis + * @param hat Hat switch status. Send 0 for rest/middleposition; 1-8 to for a direction. + * @param buttons Button bitmap, button 0 is bit 0 and so on. + */ +void esp_hidd_send_joy_value(uint16_t conn_id, int8_t x, int8_t y, int8_t z, int8_t rz, int8_t rx, int8_t ry, uint8_t hat, uint32_t buttons); + +/** + * + * @brief Send a Joystick report, use a byte array + * + * @param conn_id HID over GATT connection ID to be used. + * @param report Pointer to a 11 Byte sized array which contains the full joystick/gamepad report + * @warning This function reads 11 Bytes and sends them without checks. + */ +void esp_hidd_send_joy_report(uint16_t conn_id, uint8_t *report); + +#endif + #ifdef __cplusplus } #endif diff --git a/main/hid_dev.h b/main/hid_dev.h index 17b406b..1d753e2 100644 --- a/main/hid_dev.h +++ b/main/hid_dev.h @@ -249,9 +249,5 @@ void hid_dev_send_report(esp_gatt_if_t gatts_if, uint16_t conn_id, void hid_consumer_build_report(uint8_t *buffer, consumer_cmd_t cmd); -void hid_keyboard_build_report(uint8_t *buffer, keyboard_cmd_t cmd); - -void hid_mouse_build_report(uint8_t *buffer, mouse_cmd_t cmd); - #endif /* HID_DEV_H__ */ diff --git a/main/hid_device_le_prf.c b/main/hid_device_le_prf.c index 1495b94..5db103b 100644 --- a/main/hid_device_le_prf.c +++ b/main/hid_device_le_prf.c @@ -54,9 +54,14 @@ static const uint8_t hidReportMap[] = { 0x81, 0x02, // Input: (Data, Variable, Absolute) // // Reserved byte + ///@todo do we need this reserved byte when removing the LED output? (if removed, the report must be adjusted as well!!!) + ///@note Will try, because 4 Bytes are necessary to save... + /** 0x95, 0x01, // Report Count (1) 0x75, 0x08, // Report Size (8) 0x81, 0x01, // Input: (Constant) + */ + /** // // LED report 0x95, 0x05, // Report Count (5) @@ -70,6 +75,7 @@ static const uint8_t hidReportMap[] = { 0x95, 0x01, // Report Count (1) 0x75, 0x03, // Report Size (3) 0x91, 0x01, // Output: (Constant) + **/ // // Key arrays (6 bytes) 0x95, 0x06, // Report Count (6) @@ -87,6 +93,7 @@ static const uint8_t hidReportMap[] = { 0x09, 0x01, // Usage (Consumer Control) 0xA1, 0x01, // Collection (Application) 0x85, 0x02, // Report Id (2) + /** 0x09, 0x02, // Usage (Numeric Key Pad) 0xA1, 0x02, // Collection (Logical) 0x05, 0x09, // Usage Pg (Button) @@ -98,6 +105,7 @@ static const uint8_t hidReportMap[] = { 0x95, 0x01, // Report Count (1) 0x81, 0x00, // Input (Data, Ary, Abs) 0xC0, // End Collection + **/ 0x05, 0x0C, // Usage Pg (Consumer Devices) 0x09, 0x86, // Usage (Channel) 0x15, 0xFF, // Logical Min (-1) @@ -128,6 +136,8 @@ static const uint8_t hidReportMap[] = { 0x75, 0x04, // Report Size (4) 0x95, 0x01, // Report Count (1) 0x81, 0x00, // Input (Data, Ary, Abs) + /** @note no idea what this is used for, but it destroys the byte alignment. + 0x09, 0x80, // Usage (Selection) 0xA1, 0x02, // Collection (Logical) 0x05, 0x09, // Usage Pg (Button) @@ -138,8 +148,11 @@ static const uint8_t hidReportMap[] = { 0x75, 0x02, // Report Size (2) 0x81, 0x00, // Input (Data, Ary, Abs) 0xC0, // End Collection + 0x81, 0x03, // Input (Const, Var, Abs) - 0xC0, // End Collectionq + * + * */ + 0xC0, // End Collection 0x05, 0x01, // Usage Page (Generic Desktop) @@ -171,18 +184,48 @@ static const uint8_t hidReportMap[] = { 0xC0, // End Collection 0xC0, // End Collection -#if (SUPPORT_REPORT_VENDOR == true) - 0x06, 0xFF, 0xFF, // Usage Page(Vendor defined) - 0x09, 0xA5, // Usage(Vendor Defined) - 0xA1, 0x01, // Collection(Application) - 0x85, 0x04, // Report Id (4) - 0x09, 0xA6, // Usage(Vendor defined) - 0x09, 0xA9, // Usage(Vendor defined) - 0x75, 0x08, // Report Size - 0x95, 0x7F, // Report Count = 127 Btyes - 0x91, 0x02, // Output(Data, Variable, Absolute) - 0xC0, // End Collection -#endif + #if CONFIG_MODULE_USEJOYSTICK + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x05, // Usage (Gamepad) + 0xA1, 0x01, // Collection (Application) + 0x85, 0x04, // Report Id (4) + /* 8 bit X, Y, Z, Rz, Rx, Ry (min -127, max 127 ) */ + /* implemented like Gamepad from tinyUSB */ + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x30, // Usage (desktop X) + 0x09, 0x31, // Usage (desktop Y) + 0x09, 0x32, // Usage (desktop Z) + 0x09, 0x35, // Usage (desktop RZ) + 0x09, 0x33, // Usage (desktop RX) + 0x09, 0x34, // Usage (desktop RY) + 0x15, 0x81, // Logical Minimum (-127) + 0x25, 0x7F, // Logical Maximum (127) + 0x95, 0x06, // Report Count (6) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input: (Data, Variable, Absolute) + /* 8 bit DPad/Hat Button Map */ + 0x05, 0x01, // Usage Page (Generic Desktop) + 0x09, 0x39, // Usage (hat switch) + 0x15, 0x01, // Logical Min (1) + 0x25, 0x08, // Logical Max (8) + + 0x35, 0x00, // Physical minimum (0) + 0x46, 0x3B, 0x01, // Physical maximum (315, size 2) + //0x46, 0x00, // Physical maximum (315, size 2) + 0x95, 0x01, // Report Count (1) + 0x75, 0x08, // Report Size (8) + 0x81, 0x02, // Input: (Data, Variable, Absolute) + /* 16 bit Button Map */ + 0x05, 0x09, // Usage Page (button) + 0x19, 0x01, // Usage Minimum (01) - Button 1 + 0x29, 0x20, // Usage Maximum (32) - Button 32 + 0x15, 0x00, // Logical Min (0) + 0x25, 0x01, // Logical Max (1) + 0x95, 0x20, // Report Count (32) + 0x75, 0x01, // Report Size (1) + 0x81, 0x02, // Input: (Data, Variable, Absolute) + 0xC0, // End Collection + #endif }; @@ -234,6 +277,12 @@ static uint16_t hidExtReportRefDesc = ESP_GATT_UUID_BATTERY_LEVEL; // HID Report Reference characteristic descriptor, mouse input static uint8_t hidReportRefMouseIn[HID_REPORT_REF_LEN] = { HID_RPT_ID_MOUSE_IN, HID_REPORT_TYPE_INPUT }; + +// HID Report Reference characteristic descriptor, joystick input +#if CONFIG_MODULE_USEJOYSTICK +static uint8_t hidReportRefJoyIn[HID_REPORT_REF_LEN] = + { HID_RPT_ID_JOY_IN, HID_REPORT_TYPE_INPUT }; +#endif // HID Report Reference characteristic descriptor, key input @@ -244,12 +293,6 @@ static uint8_t hidReportRefKeyIn[HID_REPORT_REF_LEN] = static uint8_t hidReportRefLedOut[HID_REPORT_REF_LEN] = { HID_RPT_ID_LED_OUT, HID_REPORT_TYPE_OUTPUT }; -#if (SUPPORT_REPORT_VENDOR == true) - -static uint8_t hidReportRefVendorOut[HID_REPORT_REF_LEN] = - {HID_RPT_ID_VENDOR_OUT, HID_REPORT_TYPE_OUTPUT}; -#endif - // HID Report Reference characteristic descriptor, Feature static uint8_t hidReportRefFeature[HID_REPORT_REF_LEN] = { HID_RPT_ID_FEATURE, HID_REPORT_TYPE_FEATURE }; @@ -411,13 +454,14 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = ESP_GATT_PERM_READ, sizeof(hidReportRefKeyIn), sizeof(hidReportRefKeyIn), hidReportRefKeyIn}}, - +/** // Report Characteristic Declaration [HIDD_LE_IDX_REPORT_LED_OUT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, (uint8_t *)&char_prop_read_write_write_nr}}, + [HIDD_LE_IDX_REPORT_LED_OUT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid, ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, HIDD_LE_REPORT_MAX_LEN, 0, @@ -426,6 +470,7 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = ESP_GATT_PERM_READ, sizeof(hidReportRefLedOut), sizeof(hidReportRefLedOut), hidReportRefLedOut}}, +**/ [HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, @@ -446,21 +491,28 @@ static esp_gatts_attr_db_t hidd_le_gatt_db[HIDD_LE_IDX_NB] = ESP_GATT_PERM_READ, sizeof(hidReportRefMouseIn), sizeof(hidReportRefMouseIn), hidReportRefMouseIn}}, -#if (SUPPORT_REPORT_VENDOR == true) - // Report Characteristic Declaration - [HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, +#if CONFIG_MODULE_USEJOYSTICK + + [HIDD_LE_IDX_REPORT_JOY_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, CHAR_DECLARATION_SIZE, CHAR_DECLARATION_SIZE, - (uint8_t *)&char_prop_read_write_notify}}, - [HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid, - ESP_GATT_PERM_READ|ESP_GATT_PERM_WRITE, + (uint8_t *)&char_prop_read_notify}}, + + [HIDD_LE_IDX_REPORT_JOY_IN_VAL] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_uuid, + ESP_GATT_PERM_READ, HIDD_LE_REPORT_MAX_LEN, 0, NULL}}, - [HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid, + + [HIDD_LE_IDX_REPORT_JOY_IN_CCC] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_client_config_uuid, + (ESP_GATT_PERM_READ | ESP_GATT_PERM_WRITE), + sizeof(uint16_t), 0, + NULL}}, + + [HIDD_LE_IDX_REPORT_JOY_REP_REF] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&hid_report_ref_descr_uuid, ESP_GATT_PERM_READ, - sizeof(hidReportRefVendorOut), sizeof(hidReportRefVendorOut), - hidReportRefVendorOut}}, -#endif + sizeof(hidReportRefJoyIn), sizeof(hidReportRefJoyIn), + hidReportRefJoyIn}}, +#endif // Report Characteristic Declaration [HIDD_LE_IDX_REPORT_CC_IN_CHAR] = {{ESP_GATT_AUTO_RSP}, {ESP_UUID_LEN_16, (uint8_t *)&character_declaration_uuid, ESP_GATT_PERM_READ, @@ -598,7 +650,7 @@ void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, case ESP_GATTS_CLOSE_EVT: break; case ESP_GATTS_WRITE_EVT: { - esp_hidd_cb_param_t cb_param = {0}; + /**esp_hidd_cb_param_t cb_param = {0}; if (param->write.handle == hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_LED_OUT_VAL] && hidd_le_env.hidd_cb != NULL) { cb_param.vendor_write.conn_id = param->write.conn_id; @@ -606,17 +658,8 @@ void esp_hidd_prf_cb_hdl(esp_gatts_cb_event_t event, esp_gatt_if_t gatts_if, cb_param.vendor_write.length = param->write.len; cb_param.vendor_write.data = param->write.value; (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_LED_OUT_WRITE_EVT, &cb_param); - } -#if (SUPPORT_REPORT_VENDOR == true) - if (param->write.handle == hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL] && - hidd_le_env.hidd_cb != NULL) {; - cb_param.vendor_write.conn_id = param->write.conn_id; - cb_param.vendor_write.report_id = HID_RPT_ID_VENDOR_OUT; - cb_param.vendor_write.length = param->write.len; - cb_param.vendor_write.data = param->write.value; - (hidd_le_env.hidd_cb)(ESP_HIDD_EVENT_BLE_VENDOR_REPORT_WRITE_EVT, &cb_param); - } -#endif + }**/ + ESP_LOGE(HID_LE_PRF_TAG,"%s(), write evt, but no out report",__func__); break; } case ESP_GATTS_CREAT_ATTR_TAB_EVT: { @@ -777,65 +820,86 @@ void hidd_get_attr_value(uint16_t handle, uint16_t *length, uint8_t **value) static void hid_add_id_tbl(void) { + uint8_t index = 0; // Key input report - hid_rpt_map[0].id = hidReportRefKeyIn[0]; - hid_rpt_map[0].type = hidReportRefKeyIn[1]; - hid_rpt_map[0].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_VAL]; - hid_rpt_map[0].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_CCC]; - hid_rpt_map[0].mode = HID_PROTOCOL_MODE_REPORT; + hid_rpt_map[index].id = hidReportRefKeyIn[0]; + hid_rpt_map[index].type = hidReportRefKeyIn[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_VAL]; + hid_rpt_map[index].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_KEY_IN_CCC]; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_REPORT; + index++; // Consumer Control input report - hid_rpt_map[1].id = hidReportRefCCIn[0]; - hid_rpt_map[1].type = hidReportRefCCIn[1]; - hid_rpt_map[1].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_VAL]; - hid_rpt_map[1].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_CCC]; - hid_rpt_map[1].mode = HID_PROTOCOL_MODE_REPORT; + hid_rpt_map[index].id = hidReportRefCCIn[0]; + hid_rpt_map[index].type = hidReportRefCCIn[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_VAL]; + hid_rpt_map[index].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_CC_IN_CCC]; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_REPORT; + index++; // LED output report - hid_rpt_map[2].id = hidReportRefLedOut[0]; - hid_rpt_map[2].type = hidReportRefLedOut[1]; - hid_rpt_map[2].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_LED_OUT_VAL]; - hid_rpt_map[2].cccdHandle = 0; - hid_rpt_map[2].mode = HID_PROTOCOL_MODE_REPORT; + /** + hid_rpt_map[index].id = hidReportRefLedOut[0]; + hid_rpt_map[index].type = hidReportRefLedOut[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_LED_OUT_VAL]; + hid_rpt_map[index].cccdHandle = 0; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_REPORT; + index++; + **/ // Mouse input report - hid_rpt_map[3].id = hidReportRefMouseIn[0]; - hid_rpt_map[3].type = hidReportRefMouseIn[1]; - hid_rpt_map[3].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL]; - hid_rpt_map[3].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL]; - hid_rpt_map[3].mode = HID_PROTOCOL_MODE_REPORT; + hid_rpt_map[index].id = hidReportRefMouseIn[0]; + hid_rpt_map[index].type = hidReportRefMouseIn[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL]; + hid_rpt_map[index].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_MOUSE_IN_VAL]; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_REPORT; + index++; + + + // joystick report + #if CONFIG_MODULE_USEJOYSTICK + hid_rpt_map[index].id = hidReportRefJoyIn[0]; + hid_rpt_map[index].type = hidReportRefJoyIn[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_JOY_IN_VAL]; + hid_rpt_map[index].cccdHandle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_JOY_IN_VAL]; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_REPORT; + index++; + #endif // Boot keyboard input report // Use same ID and type as key input report - hid_rpt_map[4].id = hidReportRefKeyIn[0]; - hid_rpt_map[4].type = hidReportRefKeyIn[1]; - hid_rpt_map[4].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL]; - hid_rpt_map[4].cccdHandle = 0; - hid_rpt_map[4].mode = HID_PROTOCOL_MODE_BOOT; + hid_rpt_map[index].id = hidReportRefKeyIn[0]; + hid_rpt_map[index].type = hidReportRefKeyIn[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL]; + hid_rpt_map[index].cccdHandle = 0; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_BOOT; + index++; // Boot keyboard output report // Use same ID and type as LED output report - hid_rpt_map[5].id = hidReportRefLedOut[0]; - hid_rpt_map[5].type = hidReportRefLedOut[1]; - hid_rpt_map[5].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL]; - hid_rpt_map[5].cccdHandle = 0; - hid_rpt_map[5].mode = HID_PROTOCOL_MODE_BOOT; + hid_rpt_map[index].id = hidReportRefLedOut[0]; + hid_rpt_map[index].type = hidReportRefLedOut[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_KB_OUT_REPORT_VAL]; + hid_rpt_map[index].cccdHandle = 0; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_BOOT; + index++; // Boot mouse input report // Use same ID and type as mouse input report - hid_rpt_map[6].id = hidReportRefMouseIn[0]; - hid_rpt_map[6].type = hidReportRefMouseIn[1]; - hid_rpt_map[6].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL]; - hid_rpt_map[6].cccdHandle = 0; - hid_rpt_map[6].mode = HID_PROTOCOL_MODE_BOOT; + hid_rpt_map[index].id = hidReportRefMouseIn[0]; + hid_rpt_map[index].type = hidReportRefMouseIn[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_BOOT_MOUSE_IN_REPORT_VAL]; + hid_rpt_map[index].cccdHandle = 0; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_BOOT; + index++; // Feature report - hid_rpt_map[7].id = hidReportRefFeature[0]; - hid_rpt_map[7].type = hidReportRefFeature[1]; - hid_rpt_map[7].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VAL]; - hid_rpt_map[7].cccdHandle = 0; - hid_rpt_map[7].mode = HID_PROTOCOL_MODE_REPORT; - + hid_rpt_map[index].id = hidReportRefFeature[0]; + hid_rpt_map[index].type = hidReportRefFeature[1]; + hid_rpt_map[index].handle = hidd_le_env.hidd_inst.att_tbl[HIDD_LE_IDX_REPORT_VAL]; + hid_rpt_map[index].cccdHandle = 0; + hid_rpt_map[index].mode = HID_PROTOCOL_MODE_REPORT; + index++; // Setup report ID map hid_dev_register_reports(HID_NUM_REPORTS, hid_rpt_map); diff --git a/main/hidd_le_prf_int.h b/main/hidd_le_prf_int.h index fbfa1f6..c2d0418 100644 --- a/main/hidd_le_prf_int.h +++ b/main/hidd_le_prf_int.h @@ -23,7 +23,6 @@ #include "esp_gap_ble_api.h" #include "hid_dev.h" -#define SUPPORT_REPORT_VENDOR false //HID BLE profile log tag #define HID_LE_PRF_TAG "HID_LE_PRF" @@ -43,13 +42,17 @@ #define HID_MAX_APPS 1 // Number of HID reports defined in the service -#define HID_NUM_REPORTS 9 +#if CONFIG_MODULE_USEJOYSTICK + #define HID_NUM_REPORTS 10 +#else + #define HID_NUM_REPORTS 9 +#endif // HID Report IDs for the service #define HID_RPT_ID_KEY_IN 1 // Keyboard input report ID -#define HID_RPT_ID_CC_IN 2 //Consumer Control input report ID +#define HID_RPT_ID_CC_IN 2 // Consumer Control input report ID #define HID_RPT_ID_MOUSE_IN 3 // Mouse input report ID -#define HID_RPT_ID_VENDOR_OUT 4 // Vendor output report ID +#define HID_RPT_ID_JOY_IN 4 // Joystick input report ID #define HID_RPT_ID_LED_OUT 1 // LED output report ID #define HID_RPT_ID_FEATURE 0 // Feature report ID @@ -61,7 +64,7 @@ #define ATT_SVC_HID 0x1812 /// Maximal number of Report Char. that can be added in the DB for one HIDS - Up to 11 -#define HIDD_LE_NB_REPORT_INST_MAX (5) +#define HIDD_LE_NB_REPORT_INST_MAX (6) /// Maximal length of Report Char. Value #define HIDD_LE_REPORT_MAX_LEN (255) @@ -136,27 +139,30 @@ enum { HIDD_LE_IDX_REPORT_KEY_IN_CCC, HIDD_LE_IDX_REPORT_KEY_IN_REP_REF, ///Report Led output + /** HIDD_LE_IDX_REPORT_LED_OUT_CHAR, HIDD_LE_IDX_REPORT_LED_OUT_VAL, HIDD_LE_IDX_REPORT_LED_OUT_REP_REF, - -#if (SUPPORT_REPORT_VENDOR == true) - /// Report Vendor - HIDD_LE_IDX_REPORT_VENDOR_OUT_CHAR, - HIDD_LE_IDX_REPORT_VENDOR_OUT_VAL, - HIDD_LE_IDX_REPORT_VENDOR_OUT_REP_REF, -#endif - HIDD_LE_IDX_REPORT_CC_IN_CHAR, - HIDD_LE_IDX_REPORT_CC_IN_VAL, - HIDD_LE_IDX_REPORT_CC_IN_CCC, - HIDD_LE_IDX_REPORT_CC_IN_REP_REF, - + **/ // Report mouse input HIDD_LE_IDX_REPORT_MOUSE_IN_CHAR, HIDD_LE_IDX_REPORT_MOUSE_IN_VAL, HIDD_LE_IDX_REPORT_MOUSE_IN_CCC, HIDD_LE_IDX_REPORT_MOUSE_REP_REF, + //Report joystick input + #if CONFIG_MODULE_USEJOYSTICK + HIDD_LE_IDX_REPORT_JOY_IN_CHAR, + HIDD_LE_IDX_REPORT_JOY_IN_VAL, + HIDD_LE_IDX_REPORT_JOY_IN_CCC, + HIDD_LE_IDX_REPORT_JOY_REP_REF, + #endif + + HIDD_LE_IDX_REPORT_CC_IN_CHAR, + HIDD_LE_IDX_REPORT_CC_IN_VAL, + HIDD_LE_IDX_REPORT_CC_IN_CCC, + HIDD_LE_IDX_REPORT_CC_IN_REP_REF, + // Boot Keyboard Input Report HIDD_LE_IDX_BOOT_KB_IN_REPORT_CHAR, HIDD_LE_IDX_BOOT_KB_IN_REPORT_VAL, @@ -181,64 +187,6 @@ enum { }; -/// Attribute Table Indexes -enum { - HIDD_LE_INFO_CHAR, - HIDD_LE_CTNL_PT_CHAR, - HIDD_LE_REPORT_MAP_CHAR, - HIDD_LE_REPORT_CHAR, - HIDD_LE_PROTO_MODE_CHAR, - HIDD_LE_BOOT_KB_IN_REPORT_CHAR, - HIDD_LE_BOOT_KB_OUT_REPORT_CHAR, - HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR, - HIDD_LE_CHAR_MAX //= HIDD_LE_REPORT_CHAR + HIDD_LE_NB_REPORT_INST_MAX, -}; - -///att read event table Indexs -enum { - HIDD_LE_READ_INFO_EVT, - HIDD_LE_READ_CTNL_PT_EVT, - HIDD_LE_READ_REPORT_MAP_EVT, - HIDD_LE_READ_REPORT_EVT, - HIDD_LE_READ_PROTO_MODE_EVT, - HIDD_LE_BOOT_KB_IN_REPORT_EVT, - HIDD_LE_BOOT_KB_OUT_REPORT_EVT, - HIDD_LE_BOOT_MOUSE_IN_REPORT_EVT, - - HID_LE_EVT_MAX -}; - -/// Client Characteristic Configuration Codes -enum { - HIDD_LE_DESC_MASK = 0x10, - - HIDD_LE_BOOT_KB_IN_REPORT_CFG = HIDD_LE_BOOT_KB_IN_REPORT_CHAR | HIDD_LE_DESC_MASK, - HIDD_LE_BOOT_MOUSE_IN_REPORT_CFG = HIDD_LE_BOOT_MOUSE_IN_REPORT_CHAR | HIDD_LE_DESC_MASK, - HIDD_LE_REPORT_CFG = HIDD_LE_REPORT_CHAR | HIDD_LE_DESC_MASK, -}; - -/// Features Flag Values -enum { - HIDD_LE_CFG_KEYBOARD = 0x01, - HIDD_LE_CFG_MOUSE = 0x02, - HIDD_LE_CFG_PROTO_MODE = 0x04, - HIDD_LE_CFG_MAP_EXT_REF = 0x08, - HIDD_LE_CFG_BOOT_KB_WR = 0x10, - HIDD_LE_CFG_BOOT_MOUSE_WR = 0x20, -}; - -/// Report Char. Configuration Flag Values -enum { - HIDD_LE_CFG_REPORT_IN = 0x01, - HIDD_LE_CFG_REPORT_OUT = 0x02, - //HOGPD_CFG_REPORT_FEAT can be used as a mask to check Report type - HIDD_LE_CFG_REPORT_FEAT = 0x03, - HIDD_LE_CFG_REPORT_WR = 0x10, -}; - -/// Pointer to the connection clean-up function -#define HIDD_LE_CLEANUP_FNCT (NULL) - /* * TYPE DEFINITIONS **************************************************************************************** diff --git a/sdkconfig.defaults b/sdkconfig.defaults index 25e5fc8..befd726 100644 --- a/sdkconfig.defaults +++ b/sdkconfig.defaults @@ -16,4 +16,10 @@ CONFIG_XTAL_FREQ=0 #CONFIG_ESPTOOLPY_FLASHSIZE_2MB=y #CONFIG_ESPTOOLPY_FLASHSIZE="2MB" +# automatic flash size update when esptool is used, used for detecting board CONFIG_ESPTOOLPY_HEADER_FLASHSIZE_UPDATE=y + +# enable all HID interfaces by default +CONFIG_MODULE_USEKEYBOARD=y +CONFIG_MODULE_USEMOUSE=y +CONFIG_MODULE_USEJOYSTICK=y