From 7e02d64ef98c053771dedb011135967f48c9d2ed Mon Sep 17 00:00:00 2001 From: afpineda <74291754+afpineda@users.noreply.github.com> Date: Mon, 16 Dec 2024 12:39:45 +0100 Subject: [PATCH 1/4] Add ".development" to gitignore Arduino IDE requires this file when developing an Arduino library, but that file must not be included in the release. --- .gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/.gitignore b/.gitignore index 111405a1c..b37ecce25 100644 --- a/.gitignore +++ b/.gitignore @@ -1 +1,2 @@ docs/doxydocs +.development From 36fc00c427593843f69939dbd3fba7a58ac93e93 Mon Sep 17 00:00:00 2001 From: afpineda <74291754+afpineda@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:27:44 +0100 Subject: [PATCH 2/4] Fix get Input/Output/Feature Report --- src/NimBLEHIDDevice.cpp | 57 +++++++++++++++++++++++++++++++++-------- src/NimBLEHIDDevice.h | 2 ++ 2 files changed, 49 insertions(+), 10 deletions(-) diff --git a/src/NimBLEHIDDevice.cpp b/src/NimBLEHIDDevice.cpp index a6416f121..a63748761 100644 --- a/src/NimBLEHIDDevice.cpp +++ b/src/NimBLEHIDDevice.cpp @@ -22,6 +22,7 @@ # include "NimBLEServer.h" # include "NimBLEService.h" # include "NimBLE2904.h" +# include static constexpr uint16_t deviceInfoSvcUuid = 0x180a; static constexpr uint16_t hidSvcUuid = 0x1812; @@ -149,14 +150,43 @@ void NimBLEHIDDevice::setBatteryLevel(uint8_t level, bool notify) { } } // setBatteryLevel +/** + * @brief Locate the characteristic for a report ID. + * + * @param [in] reportId Report identifier to locate. + * @param [out] reportType Type of report (input/output/feature). Not meaningful if the return value is nullptr. + * @return NimBLECharacteristic* The characteristic. + * @return nullptr If the characteristic does not exist. + */ +NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicById(uint8_t reportId, uint8_t &reportType) +{ + NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic(inputReportChrUuid,0); + for (uint16_t i = 1; (candidate != nullptr) && (i !=0); i++) + { + NimBLEDescriptor* dsc = candidate->getDescriptorByUUID(featureReportDscUuid); + NimBLEAttValue desc1_val_att = dsc->getValue(); + const uint8_t *desc1_val = desc1_val_att.data(); + reportType = desc1_val[1]; + if (desc1_val[0] == reportId) + return candidate; + candidate = m_hidSvc->getCharacteristic(inputReportChrUuid,i); + } + return nullptr; +} + /** * @brief Get the input report characteristic. - * @param [in] reportId input report ID, the same as in report map for input object related to the characteristic. - * @return A pointer to the input report characteristic. + * @param [in] reportId Input report ID, the same as in report map for input object related to the characteristic. + * @return NimBLECharacteristic* A pointer to the input report characteristic. + * @return nullptr If the report is already created as an output or feature report. * @details This will create the characteristic if not already created. */ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) { - NimBLECharacteristic* inputReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid); + uint8_t reportType; + NimBLECharacteristic* inputReportChr = locateReportCharacteristicById(reportId, reportType); + if ((inputReportChr != nullptr) && (reportType != 0x01)) + // ERROR: this reportId exists, but it is not an input report + return nullptr; if (inputReportChr == nullptr) { inputReportChr = m_hidSvc->createCharacteristic(inputReportChrUuid, @@ -174,13 +204,16 @@ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) { /** * @brief Get the output report characteristic. * @param [in] reportId Output report ID, the same as in report map for output object related to the characteristic. - * @return A pointer to the output report characteristic. + * @return NimBLECharacteristic* A pointer to the output report characteristic. + * @return nullptr If the report is already created as an input or feature report. * @details This will create the characteristic if not already created. - * @note The output report characteristic is optional and should only be created after the input report characteristic. */ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) { - // Same uuid as input so this needs to be the second instance - NimBLECharacteristic* outputReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid, 1); + uint8_t reportType; + NimBLECharacteristic* outputReportChr = locateReportCharacteristicById(reportId, reportType); + if ((outputReportChr != nullptr) && (reportType != 0x02)) + // ERROR: this reportId exists, but it is not an output report + return nullptr; if (outputReportChr == nullptr) { outputReportChr = m_hidSvc->createCharacteristic(inputReportChrUuid, @@ -189,7 +222,6 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) { NimBLEDescriptor* outputReportDsc = outputReportChr->createDescriptor( featureReportDscUuid, NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC); - uint8_t desc1_val[] = {reportId, 0x02}; outputReportDsc->setValue(desc1_val, 2); } @@ -200,11 +232,16 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) { /** * @brief Get the feature report characteristic. * @param [in] reportId Feature report ID, the same as in report map for feature object related to the characteristic. - * @return A pointer to feature report characteristic. + * @return NimBLECharacteristic* A pointer to feature report characteristic. + * @return nullptr If the report is already created as an input or output report. * @details This will create the characteristic if not already created. */ NimBLECharacteristic* NimBLEHIDDevice::getFeatureReport(uint8_t reportId) { - NimBLECharacteristic* featureReportChr = m_hidSvc->getCharacteristic(inputReportChrUuid); + uint8_t reportType; + NimBLECharacteristic* featureReportChr = locateReportCharacteristicById(reportId, reportType); + if ((featureReportChr != nullptr) && (reportType != 0x03)) + // ERROR: this reportId exists, but it is not a feature report + return nullptr; if (featureReportChr == nullptr) { featureReportChr = m_hidSvc->createCharacteristic( inputReportChrUuid, diff --git a/src/NimBLEHIDDevice.h b/src/NimBLEHIDDevice.h index 0737e7581..359bfb5ab 100644 --- a/src/NimBLEHIDDevice.h +++ b/src/NimBLEHIDDevice.h @@ -81,6 +81,8 @@ class NimBLEHIDDevice { NimBLECharacteristic* m_hidControlChr{nullptr}; // 0x2a4c NimBLECharacteristic* m_protocolModeChr{nullptr}; // 0x2a4e NimBLECharacteristic* m_batteryLevelChr{nullptr}; // 0x2a19 + + NimBLECharacteristic* locateReportCharacteristicById(uint8_t reportId, uint8_t &reportType); }; #endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL) From 3a409b6966d45a01245481f9413c9da232595291 Mon Sep 17 00:00:00 2001 From: afpineda <74291754+afpineda@users.noreply.github.com> Date: Tue, 17 Dec 2024 12:52:30 +0100 Subject: [PATCH 3/4] Remove unneeded header --- src/NimBLEHIDDevice.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/src/NimBLEHIDDevice.cpp b/src/NimBLEHIDDevice.cpp index a63748761..7df583534 100644 --- a/src/NimBLEHIDDevice.cpp +++ b/src/NimBLEHIDDevice.cpp @@ -22,7 +22,6 @@ # include "NimBLEServer.h" # include "NimBLEService.h" # include "NimBLE2904.h" -# include static constexpr uint16_t deviceInfoSvcUuid = 0x180a; static constexpr uint16_t hidSvcUuid = 0x1812; From 8608b8a19ebb8555ba62de60977ac0dc8289f738 Mon Sep 17 00:00:00 2001 From: afpineda <74291754+afpineda@users.noreply.github.com> Date: Thu, 19 Dec 2024 08:36:03 +0100 Subject: [PATCH 4/4] Format code and update a few Doxygen commentaries --- src/NimBLEHIDDevice.cpp | 32 ++++++++++++++++---------------- src/NimBLEHIDDevice.h | 2 +- 2 files changed, 17 insertions(+), 17 deletions(-) diff --git a/src/NimBLEHIDDevice.cpp b/src/NimBLEHIDDevice.cpp index 7df583534..e07efc494 100644 --- a/src/NimBLEHIDDevice.cpp +++ b/src/NimBLEHIDDevice.cpp @@ -157,18 +157,15 @@ void NimBLEHIDDevice::setBatteryLevel(uint8_t level, bool notify) { * @return NimBLECharacteristic* The characteristic. * @return nullptr If the characteristic does not exist. */ -NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicById(uint8_t reportId, uint8_t &reportType) -{ - NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic(inputReportChrUuid,0); - for (uint16_t i = 1; (candidate != nullptr) && (i !=0); i++) - { - NimBLEDescriptor* dsc = candidate->getDescriptorByUUID(featureReportDscUuid); - NimBLEAttValue desc1_val_att = dsc->getValue(); - const uint8_t *desc1_val = desc1_val_att.data(); - reportType = desc1_val[1]; - if (desc1_val[0] == reportId) - return candidate; - candidate = m_hidSvc->getCharacteristic(inputReportChrUuid,i); +NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicById(uint8_t reportId, uint8_t& reportType) { + NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, 0); + for (uint16_t i = 1; (candidate != nullptr) && (i != 0); i++) { + NimBLEDescriptor* dsc = candidate->getDescriptorByUUID(featureReportDscUuid); + NimBLEAttValue desc1_val_att = dsc->getValue(); + const uint8_t* desc1_val = desc1_val_att.data(); + reportType = desc1_val[1]; + if (desc1_val[0] == reportId) return candidate; + candidate = m_hidSvc->getCharacteristic(inputReportChrUuid, i); } return nullptr; } @@ -177,11 +174,12 @@ NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicById(uint8_t re * @brief Get the input report characteristic. * @param [in] reportId Input report ID, the same as in report map for input object related to the characteristic. * @return NimBLECharacteristic* A pointer to the input report characteristic. + * Store this value to avoid computational overhead. * @return nullptr If the report is already created as an output or feature report. * @details This will create the characteristic if not already created. */ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) { - uint8_t reportType; + uint8_t reportType; NimBLECharacteristic* inputReportChr = locateReportCharacteristicById(reportId, reportType); if ((inputReportChr != nullptr) && (reportType != 0x01)) // ERROR: this reportId exists, but it is not an input report @@ -204,11 +202,12 @@ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) { * @brief Get the output report characteristic. * @param [in] reportId Output report ID, the same as in report map for output object related to the characteristic. * @return NimBLECharacteristic* A pointer to the output report characteristic. + * Store this value to avoid computational overhead. * @return nullptr If the report is already created as an input or feature report. * @details This will create the characteristic if not already created. */ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) { - uint8_t reportType; + uint8_t reportType; NimBLECharacteristic* outputReportChr = locateReportCharacteristicById(reportId, reportType); if ((outputReportChr != nullptr) && (reportType != 0x02)) // ERROR: this reportId exists, but it is not an output report @@ -232,13 +231,14 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) { * @brief Get the feature report characteristic. * @param [in] reportId Feature report ID, the same as in report map for feature object related to the characteristic. * @return NimBLECharacteristic* A pointer to feature report characteristic. + * Store this value to avoid computational overhead. * @return nullptr If the report is already created as an input or output report. * @details This will create the characteristic if not already created. */ NimBLECharacteristic* NimBLEHIDDevice::getFeatureReport(uint8_t reportId) { - uint8_t reportType; + uint8_t reportType; NimBLECharacteristic* featureReportChr = locateReportCharacteristicById(reportId, reportType); - if ((featureReportChr != nullptr) && (reportType != 0x03)) + if ((featureReportChr != nullptr) && (reportType != 0x03)) // ERROR: this reportId exists, but it is not a feature report return nullptr; if (featureReportChr == nullptr) { diff --git a/src/NimBLEHIDDevice.h b/src/NimBLEHIDDevice.h index 359bfb5ab..9b97cd79b 100644 --- a/src/NimBLEHIDDevice.h +++ b/src/NimBLEHIDDevice.h @@ -82,7 +82,7 @@ class NimBLEHIDDevice { NimBLECharacteristic* m_protocolModeChr{nullptr}; // 0x2a4e NimBLECharacteristic* m_batteryLevelChr{nullptr}; // 0x2a19 - NimBLECharacteristic* locateReportCharacteristicById(uint8_t reportId, uint8_t &reportType); + NimBLECharacteristic* locateReportCharacteristicById(uint8_t reportId, uint8_t& reportType); }; #endif // CONFIG_BT_ENABLED && CONFIG_BT_NIMBLE_ROLE_BROADCASTER && defined(CONFIG_BT_NIMBLE_ROLE_PERIPHERAL)