espressif / esp-idf

Espressif IoT Development Framework. Official development framework for Espressif SoCs.
Apache License 2.0
13.52k stars 7.26k forks source link

Undefined CCC behavior on writeless HID devices (IDFGH-11980) #13054

Open HelloOO7 opened 8 months ago

HelloOO7 commented 8 months ago

Answers checklist.

IDF version.

5.1.2

Espressif SoC revision.

ESP32-S3-WROOM-1

Operating System used.

Windows

How did you build your project?

VS Code IDE

If you are using Windows, please specify command line type.

CMD

Development Kit.

Custom Board

Power Supply used.

USB

What is the expected behavior?

When using the IDF's ble_hid component, creating an HID device that only sends notifications/indications and does not receive explicit CCC writes (or can receive writes, but none are issued by the host device) should be able to send the notifications regardless of whether the host device issues a write that would confirm its CCC value.

What is the actual behavior?

Currently, the value of hidd_report_item_t.ccc is uninitialized before the host device issues a CCC write, which sets the field to a consistent value (here). I have observed 3 possible behaviors that this can cause:

  1. On the esp_hid_device with no modifications made, and every other scenario where esp_hid_parse_report_map returns a result with reports_len of 1, everything works OK. It appears that this is because in my current environment, the malloc call here returns a pointer to uninitialized data in which the ccc field has the bits required for notification/indications randomly set.
  2. On the same example, if I change the previously mentioned malloc to a calloc, thus initializing the ccc field with a zero, every subsequent attempt to notify/indicate fails with BLE_HIDD: Indicate Not Enabled: 0.
  3. On other environments, if esp_hid_parse_report_map returns a result with reports_len greater than 1, chances are that the malloc will also return a pointer to a memory area that is zeroed out, resulting in a similar behavior to case 2.

In turn, unless the host device issues a CCC write, the value of the hidd_report_item_t.ccc field is undefined and often wrongly disables notifications/indications.

Steps to reproduce.

  1. Use the esp_hid_device example.
  2. Change this to a calloc to ensure consistent memory behavior.
  3. Connect to the example device from an Android host, then disconnect (this is needed because on first connection, the Android host appears to be issuing a CCC write, which corrects the behavior).
  4. Reset the board.
  5. Connect to the example device from the same host again (the device must be paired from step 3).
  6. The ESP should now report BLE_HIDD: Indicate Not Enabled every time it tries to indicate to the host device.

Debug Logs.

(410) HID_DEV_DEMO: setting hid gap, mode:1
(420) BLE_INIT: BT controller compile version [59725b5]
(420) BLE_INIT: Bluetooth MAC: 34:85:18:XX:XX:XX
(420) phy_init: phy_version 620,ec7ec30,Sep  5 2023,13:49:13
(490) BT_BTM: BTM_BleWriteAdvData, Partial data write into ADV
(490) HID_DEV_DEMO: setting ble device
(500) main_task: Returned from app_main()
(500) HID_DEV_BLE: START
(1810) HID_DEV_BLE: CONNECT
(2080) ESP_HID_GAP: BLE GAP AUTH SUCCESS
(2080) HID_DEV_DEMO: Send the volume
(2080) BLE_HIDD: Indicate Not Enabled: 0
(2180) BLE_HIDD: Indicate Not Enabled: 0

More Information.

No response

esp-zhp commented 8 months ago

@HelloOO7 thanks for reporting the issue,I will check it.