@@ -149,14 +149,41 @@ void NimBLEHIDDevice::setBatteryLevel(uint8_t level, bool notify) {
149149 }
150150} // setBatteryLevel
151151
152+ /* *
153+ * @brief Locate the characteristic for a report ID.
154+ *
155+ * @param [in] reportId Report identifier to locate.
156+ * @param [out] reportType Type of report (input/output/feature). Not meaningful if the return value is nullptr.
157+ * @return NimBLECharacteristic* The characteristic.
158+ * @return nullptr If the characteristic does not exist.
159+ */
160+ NimBLECharacteristic* NimBLEHIDDevice::locateReportCharacteristicById (uint8_t reportId, uint8_t & reportType) {
161+ NimBLECharacteristic* candidate = m_hidSvc->getCharacteristic (inputReportChrUuid, 0 );
162+ for (uint16_t i = 1 ; (candidate != nullptr ) && (i != 0 ); i++) {
163+ NimBLEDescriptor* dsc = candidate->getDescriptorByUUID (featureReportDscUuid);
164+ NimBLEAttValue desc1_val_att = dsc->getValue ();
165+ const uint8_t * desc1_val = desc1_val_att.data ();
166+ reportType = desc1_val[1 ];
167+ if (desc1_val[0 ] == reportId) return candidate;
168+ candidate = m_hidSvc->getCharacteristic (inputReportChrUuid, i);
169+ }
170+ return nullptr ;
171+ }
172+
152173/* *
153174 * @brief Get the input report characteristic.
154- * @param [in] reportId input report ID, the same as in report map for input object related to the characteristic.
155- * @return A pointer to the input report characteristic.
175+ * @param [in] reportId Input report ID, the same as in report map for input object related to the characteristic.
176+ * @return NimBLECharacteristic* A pointer to the input report characteristic.
177+ * Store this value to avoid computational overhead.
178+ * @return nullptr If the report is already created as an output or feature report.
156179 * @details This will create the characteristic if not already created.
157180 */
158181NimBLECharacteristic* NimBLEHIDDevice::getInputReport (uint8_t reportId) {
159- NimBLECharacteristic* inputReportChr = m_hidSvc->getCharacteristic (inputReportChrUuid);
182+ uint8_t reportType;
183+ NimBLECharacteristic* inputReportChr = locateReportCharacteristicById (reportId, reportType);
184+ if ((inputReportChr != nullptr ) && (reportType != 0x01 ))
185+ // ERROR: this reportId exists, but it is not an input report
186+ return nullptr ;
160187 if (inputReportChr == nullptr ) {
161188 inputReportChr =
162189 m_hidSvc->createCharacteristic (inputReportChrUuid,
@@ -174,13 +201,17 @@ NimBLECharacteristic* NimBLEHIDDevice::getInputReport(uint8_t reportId) {
174201/* *
175202 * @brief Get the output report characteristic.
176203 * @param [in] reportId Output report ID, the same as in report map for output object related to the characteristic.
177- * @return A pointer to the output report characteristic.
204+ * @return NimBLECharacteristic* A pointer to the output report characteristic.
205+ * Store this value to avoid computational overhead.
206+ * @return nullptr If the report is already created as an input or feature report.
178207 * @details This will create the characteristic if not already created.
179- * @note The output report characteristic is optional and should only be created after the input report characteristic.
180208 */
181209NimBLECharacteristic* NimBLEHIDDevice::getOutputReport (uint8_t reportId) {
182- // Same uuid as input so this needs to be the second instance
183- NimBLECharacteristic* outputReportChr = m_hidSvc->getCharacteristic (inputReportChrUuid, 1 );
210+ uint8_t reportType;
211+ NimBLECharacteristic* outputReportChr = locateReportCharacteristicById (reportId, reportType);
212+ if ((outputReportChr != nullptr ) && (reportType != 0x02 ))
213+ // ERROR: this reportId exists, but it is not an output report
214+ return nullptr ;
184215 if (outputReportChr == nullptr ) {
185216 outputReportChr =
186217 m_hidSvc->createCharacteristic (inputReportChrUuid,
@@ -189,7 +220,6 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
189220 NimBLEDescriptor* outputReportDsc = outputReportChr->createDescriptor (
190221 featureReportDscUuid,
191222 NIMBLE_PROPERTY::READ | NIMBLE_PROPERTY::WRITE | NIMBLE_PROPERTY::READ_ENC | NIMBLE_PROPERTY::WRITE_ENC);
192-
193223 uint8_t desc1_val[] = {reportId, 0x02 };
194224 outputReportDsc->setValue (desc1_val, 2 );
195225 }
@@ -200,11 +230,17 @@ NimBLECharacteristic* NimBLEHIDDevice::getOutputReport(uint8_t reportId) {
200230/* *
201231 * @brief Get the feature report characteristic.
202232 * @param [in] reportId Feature report ID, the same as in report map for feature object related to the characteristic.
203- * @return A pointer to feature report characteristic.
233+ * @return NimBLECharacteristic* A pointer to feature report characteristic.
234+ * Store this value to avoid computational overhead.
235+ * @return nullptr If the report is already created as an input or output report.
204236 * @details This will create the characteristic if not already created.
205237 */
206238NimBLECharacteristic* NimBLEHIDDevice::getFeatureReport (uint8_t reportId) {
207- NimBLECharacteristic* featureReportChr = m_hidSvc->getCharacteristic (inputReportChrUuid);
239+ uint8_t reportType;
240+ NimBLECharacteristic* featureReportChr = locateReportCharacteristicById (reportId, reportType);
241+ if ((featureReportChr != nullptr ) && (reportType != 0x03 ))
242+ // ERROR: this reportId exists, but it is not a feature report
243+ return nullptr ;
208244 if (featureReportChr == nullptr ) {
209245 featureReportChr = m_hidSvc->createCharacteristic (
210246 inputReportChrUuid,
0 commit comments